<commit_before>package org.sagebionetworks.web.client.widget.entity;

import java.util.Map;

import org.sagebionetworks.markdown.constants.WidgetConstants;
import org.sagebionetworks.schema.adapter.JSONObjectAdapterException;
import org.sagebionetworks.web.client.DisplayConstants;
import org.sagebionetworks.web.client.DisplayUtils;
import org.sagebionetworks.web.client.DisplayUtils.ButtonType;
import org.sagebionetworks.web.client.IconsImageBundle;
import org.sagebionetworks.web.client.SynapseClientAsync;
import org.sagebionetworks.web.client.SynapseJSNIUtils;
import org.sagebionetworks.web.client.cookie.CookieProvider;
import org.sagebionetworks.web.client.events.WidgetDescriptorUpdatedEvent;
import org.sagebionetworks.web.client.events.WidgetDescriptorUpdatedHandler;
import org.sagebionetworks.web.client.presenter.BaseEditWidgetDescriptorPresenter;
import org.sagebionetworks.web.client.resources.ResourceLoader;
import org.sagebionetworks.web.client.utils.TOOLTIP_POSITION;
import org.sagebionetworks.web.client.widget.entity.MarkdownEditorWidget.CloseHandler;
import org.sagebionetworks.web.client.widget.entity.MarkdownEditorWidget.ManagementHandler;
import org.sagebionetworks.web.client.widget.entity.registration.WidgetRegistrar;
import org.sagebionetworks.web.client.widget.modal.Dialog;
import org.sagebionetworks.web.shared.WebConstants;
import org.sagebionetworks.web.shared.WikiPageKey;

import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.HorizontalPanel;
import com.extjs.gxt.ui.client.widget.Label;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.inject.Inject;

/**
 * Lightweight widget used to resolve markdown
 * 
 * @author Jay
 *
 */
public class MarkdownEditorWidgetViewImpl extends FlowPanel implements MarkdownEditorWidgetView {
	
	private SynapseClientAsync synapseClient;
	private SynapseJSNIUtils synapseJSNIUtils;
	private WidgetRegistrar widgetRegistrar;
	private IconsImageBundle iconsImageBundle;
	BaseEditWidgetDescriptorPresenter widgetDescriptorEditor;
	private CookieProvider cookies;
	private TextArea markdownTextArea;
	private WikiPageKey wikiKey;
	private boolean isWikiEditor;
	private com.google.gwt.user.client.ui.Button editWidgetButton;
	private WidgetDescriptorUpdatedHandler callback;
	private WidgetSelectionState widgetSelectionState;
	private ResourceLoader resourceLoader;
	private MarkdownWidget markdownWidget;
	private Presenter presenter;
	private Dialog dialog;
	
	@Inject
	public MarkdownEditorWidgetViewImpl(SynapseClientAsync synapseClient,
			SynapseJSNIUtils synapseJSNIUtils, WidgetRegistrar widgetRegistrar,
			IconsImageBundle iconsImageBundle,
			BaseEditWidgetDescriptorPresenter widgetDescriptorEditor,
			CookieProvider cookies,
			ResourceLoader resourceLoader, 
			MarkdownWidget markdownWidget, 
			Dialog dialog) {
		super();
		this.synapseClient = synapseClient;
		this.synapseJSNIUtils = synapseJSNIUtils;
		this.widgetRegistrar = widgetRegistrar;
		this.iconsImageBundle = iconsImageBundle;
		this.widgetDescriptorEditor = widgetDescriptorEditor;
		this.cookies = cookies;
		this.resourceLoader = resourceLoader;
		this.markdownWidget = markdownWidget;
		this.dialog = dialog;
		markdownWidget.addStyleName("margin-10");
		widgetSelectionState = new WidgetSelectionState();
	}
	
	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}
	
	/**
	 * 
	 * @param ownerId
	 * @param ownerType
	 * @param markdownTextArea
	 * @param formPanel
	 * @param callback
	 * @param saveHandler if no save handler is specified, then a Save button is not shown.  If it is specified, then Save is shown and saveClicked is called when that button is clicked.
	 */
	public void configure(final WikiPageKey wikiKey, 
			WikiPageKey formattingGuideWikiPageKey,
			final TextArea markdownTextArea, 
			LayoutContainer formPanel,
			boolean showFieldLabel, 
			final boolean isWikiEditor,
			final WidgetDescriptorUpdatedHandler callback,
			final CloseHandler saveHandler,
			final ManagementHandler managementHandler) {
		if (formattingGuideWikiPageKey != null)
			initFormattingGuide(formattingGuideWikiPageKey);
		this.markdownTextArea = markdownTextArea;
		resizeMarkdownTextArea();
		this.wikiKey = wikiKey;
		this.isWikiEditor = isWikiEditor;
		this.callback = callback;
		
		//Toolbar
		final HorizontalPanel mdCommands = new HorizontalPanel();
		mdCommands.setSpacing(2);
		mdCommands.addStyleName("view markdown-editor-commands-container");
		editWidgetButton = getNewCommand("Edit Widget", "glyphicon-pencil",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleEditWidgetCommand();
			}
		}); 
		mdCommands.add(editWidgetButton);
		
		Button insertButton = new Button("Insert", AbstractImagePrototype.create(iconsImageBundle.glyphCirclePlus16()));
		
		insertButton.addStyleName("whiteBackgroundGxt");
		insertButton.setWidth(55);
		insertButton.setMenu(createWidgetMenu(callback));
		FormData descriptionLabelFormData = new FormData();
		descriptionLabelFormData.setMargins(new Margins(0,15,0,17));
		if (showFieldLabel)
			formPanel.add(new Label("Description:"),descriptionLabelFormData);
		FormData mdCommandFormData = new FormData();
		formPanel.add(mdCommands,mdCommandFormData);
		
		markdownTextArea.addStyleName("col-xs-12 col-sm-12 col-md-12 col-lg-12");
		markdownTextArea.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				updateEditWidget();
			}
		});
		
		markdownTextArea.addKeyUpHandler(new KeyUpHandler() {
			
			@Override
			public void onKeyUp(KeyUpEvent event) {
				updateEditWidget();
				resizeMarkdownTextArea();
			}
		});
		
		// followed by description.
		SimplePanel descriptionWrapper= new SimplePanel();
		descriptionWrapper.add(markdownTextArea);
		
		FormData descriptionData = new FormData("-5");
		//descriptionData.setHeight(310);		
        formPanel.add(descriptionWrapper, descriptionData);
		
		//Preview
		final com.google.gwt.user.client.ui.Button previewButton =  new com.google.gwt.user.client.ui.Button();
		previewButton.removeStyleName("gwt-Button");
		previewButton.setText(DisplayConstants.ENTITY_DESCRIPTION_PREVIEW_BUTTON_TEXT);
		previewButton.addStyleName("btn btn-default");
		previewButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				presenter.showPreview(markdownTextArea.getValue(), isWikiEditor);
			}
		});
		
		FormData previewFormData = new FormData("-5");
		previewFormData.setMargins(new Margins(10,0,0,0));
		
		LayoutContainer overallRow = DisplayUtils.createRowContainer();
		LayoutContainer row = DisplayUtils.createRowContainer();
		FlowPanel commands = new FlowPanel();
		commands.addStyleName("margin-top-5 col-md-12");
		row.add(commands);
		overallRow.add(row);
		formPanel.add(overallRow, previewFormData);
		final com.google.gwt.user.client.ui.Button deleteButton =  DisplayUtils.createButton(DisplayConstants.BUTTON_DELETE_WIKI, ButtonType.DANGER);
		final com.google.gwt.user.client.ui.Button attachmentsButton =  DisplayUtils.createButton(DisplayConstants.BUTTON_WIKI_ATTACHMENTS, ButtonType.DEFAULT);
		boolean canManage = managementHandler != null;
		if (canManage) {
			deleteButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					managementHandler.deleteClicked();
				}
			});
			
			attachmentsButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					managementHandler.attachmentsClicked();
				}
			});
		}
		final com.google.gwt.user.client.ui.Button saveButton =  DisplayUtils.createButton(DisplayConstants.SAVE_BUTTON_LABEL, ButtonType.PRIMARY);
		final com.google.gwt.user.client.ui.Button cancelButton = DisplayUtils.createButton(DisplayConstants.BUTTON_CANCEL, ButtonType.DEFAULT);
		boolean canSave = saveHandler != null;
		if (canSave) {
			saveButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					DisplayUtils.changeButtonToSaving(saveButton);
					saveHandler.saveClicked();
				}
			});
						
			cancelButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					saveHandler.cancelClicked();
				}
			});
		}
		
		//add to container
		//save, attachments, preview
		if (canSave) {
			saveButton.addStyleName("margin-right-5");
			commands.add(saveButton);
		}
			
		if (canManage) {
			attachmentsButton.addStyleName("margin-right-5");
			commands.add(attachmentsButton);
		}
		previewButton.addStyleName("margin-right-5");
		commands.add(previewButton);
		
		//then cancel, delete
		if (canManage) {
			deleteButton.addStyleName("pull-right");
			commands.add(deleteButton);
		}
		if (canSave) {
			cancelButton.addStyleName("pull-right margin-right-5");
			commands.add(cancelButton);
		}
		
		
		//Formatting Guide
		com.google.gwt.user.client.ui.Button formatLink = getNewCommand(DisplayConstants.ENTITY_DESCRIPTION_TIPS_TEXT, null, "glyphicon-question-sign", new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				//pop up format guide
				showFormattingGuideDialog();
			}
		});
		mdCommands.add(formatLink);
		mdCommands.add(insertButton);
		
		//basic commands
		String startTag = "**";
		String endTag = startTag;
		com.google.gwt.user.client.ui.Button boldCommand = getNewCommand("Bold", "glyphicon-bold", getBasicCommandClickHandler(startTag, endTag, false));
		boldCommand.addStyleName("margin-left-10");
		mdCommands.add(boldCommand);

		startTag = "_";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button italicCommand = getNewCommand("Italicize", "glyphicon-italic",  getBasicCommandClickHandler(startTag, endTag, false));
		mdCommands.add(italicCommand);

		startTag = "--";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button strikeCommand = getNewCommand("Strikeout", "", getBasicCommandClickHandler(startTag, endTag, false));
		strikeCommand.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("strike")));
		strikeCommand.addStyleName("font-size-15");
		mdCommands.add(strikeCommand);

		startTag = "\n```\n";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button codeCommand = getNewCommand("Code Block", "Optionally specify the language for syntax highlighting.", "", getBasicCommandClickHandler(startTag, endTag, true));
		mdCommands.add(codeCommand);
		
		startTag = "$$\\(";
		endTag = "\\)$$";
		com.google.gwt.user.client.ui.Button mathCommand = getNewCommand("TeX", "LaTeX math equation.", "", getBasicCommandClickHandler(startTag, endTag, false));
		mdCommands.add(mathCommand);
		
		
		startTag = "~";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button subscript = getNewCommand("", "Subscript", "", getBasicCommandClickHandler(startTag, endTag, false));
		subscript.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("subscript")));
		subscript.addStyleName("font-size-15");
		mdCommands.add(subscript);
		
		startTag = "^";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button superscript = getNewCommand("", "Superscript", "", getBasicCommandClickHandler(startTag, endTag, false));
		superscript.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("superscript")));
		superscript.addStyleName("font-size-15");
		mdCommands.add(superscript);
		
		Button headingButton = new Button("Heading");
		DisplayUtils.addToolTip(headingButton, "Heading");
		headingButton.addStyleName("whiteBackgroundGxt boldText");
		headingButton.setWidth(60);
		headingButton.setMenu(createHeadingMenu());
		headingButton.addStyleName("margin-right-10");
		mdCommands.add(headingButton);
		
		if (isWikiEditor) {
			com.google.gwt.user.client.ui.Button attachment = getNewCommand("Insert Attachment", "glyphicon-paperclip",new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					handleInsertWidgetCommand(WidgetConstants.ATTACHMENT_PREVIEW_CONTENT_TYPE, callback);
				}
			}); 

			mdCommands.add(attachment);
		}

		com.google.gwt.user.client.ui.Button image = getNewCommand("Insert Image", "glyphicon-camera",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand(WidgetConstants.IMAGE_CONTENT_TYPE, callback);
			}
		});
		mdCommands.add(image);
		
		com.google.gwt.user.client.ui.Button video = getNewCommand("Insert Video", "glyphicon-facetime-video",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand(WidgetConstants.VIDEO_CONTENT_TYPE, callback);
			}
		}); 
		mdCommands.add(video);

		com.google.gwt.user.client.ui.Button link = getNewCommand("Insert Link", "glyphicon-link",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand( WidgetConstants.LINK_CONTENT_TYPE, callback);
			}
		}); 

		mdCommands.add(link);
		formPanel.layout(true);
		//defers code until after the browser redraws the page (because of the gxt LayoutContainer life cycle). 
		//scrolls the browser window such that the markdown command bar is at the top of the screen
		Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
			@Override
			public void execute() {
				if (mdCommands != null && mdCommands.getElement() != null)
					Window.scrollTo(0, mdCommands.getElement().getAbsoluteTop());
			}
		});
		
		dialog.removeFromParent();
		mdCommands.add(dialog);
	}
	
	public void handleEditWidgetCommand() {
		if (widgetSelectionState != null && widgetSelectionState.isWidgetSelected()) {
			final int widgetStartIndex = widgetSelectionState.getWidgetStartIndex();
			final int widgetEndIndex = widgetSelectionState.getWidgetEndIndex();
			String innerText = widgetSelectionState.getInnerWidgetText();
			markdownTextArea.setSelectionRange(widgetStartIndex, innerText.length());
			String contentTypeKey = widgetRegistrar.getWidgetContentType(innerText);
			Map<String, String> widgetDescriptor = widgetRegistrar.getWidgetDescriptor(innerText);
			BaseEditWidgetDescriptorPresenter.editExistingWidget(widgetDescriptorEditor, wikiKey, contentTypeKey, widgetDescriptor, new WidgetDescriptorUpdatedHandler() {
				@Override
			public void onUpdate(WidgetDescriptorUpdatedEvent event) {
					//replace old widget text
					String text = markdownTextArea.getText();
					if (widgetStartIndex > -1 && widgetEndIndex > -1) {
						markdownTextArea.setText(text.substring(0, widgetStartIndex) + text.substring(widgetEndIndex));
						markdownTextArea.setCursorPos(widgetStartIndex);
						if (event.getInsertValue()!=null) {
							insertMarkdown(event.getInsertValue());
						}
						if (callback != null)
							callback.onUpdate(event);
					}
				}<commit_msg>no need to remove Dialog from parent before adding to command bar<commit_after>package org.sagebionetworks.web.client.widget.entity;

import java.util.Map;

import org.sagebionetworks.markdown.constants.WidgetConstants;
import org.sagebionetworks.schema.adapter.JSONObjectAdapterException;
import org.sagebionetworks.web.client.DisplayConstants;
import org.sagebionetworks.web.client.DisplayUtils;
import org.sagebionetworks.web.client.DisplayUtils.ButtonType;
import org.sagebionetworks.web.client.IconsImageBundle;
import org.sagebionetworks.web.client.SynapseClientAsync;
import org.sagebionetworks.web.client.SynapseJSNIUtils;
import org.sagebionetworks.web.client.cookie.CookieProvider;
import org.sagebionetworks.web.client.events.WidgetDescriptorUpdatedEvent;
import org.sagebionetworks.web.client.events.WidgetDescriptorUpdatedHandler;
import org.sagebionetworks.web.client.presenter.BaseEditWidgetDescriptorPresenter;
import org.sagebionetworks.web.client.resources.ResourceLoader;
import org.sagebionetworks.web.client.utils.TOOLTIP_POSITION;
import org.sagebionetworks.web.client.widget.entity.MarkdownEditorWidget.CloseHandler;
import org.sagebionetworks.web.client.widget.entity.MarkdownEditorWidget.ManagementHandler;
import org.sagebionetworks.web.client.widget.entity.registration.WidgetRegistrar;
import org.sagebionetworks.web.client.widget.modal.Dialog;
import org.sagebionetworks.web.shared.WebConstants;
import org.sagebionetworks.web.shared.WikiPageKey;

import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.widget.HorizontalPanel;
import com.extjs.gxt.ui.client.widget.Label;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.menu.Menu;
import com.extjs.gxt.ui.client.widget.menu.MenuItem;
import com.extjs.gxt.ui.client.widget.menu.SeparatorMenuItem;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.TextArea;
import com.google.inject.Inject;

/**
 * Lightweight widget used to resolve markdown
 * 
 * @author Jay
 *
 */
public class MarkdownEditorWidgetViewImpl extends FlowPanel implements MarkdownEditorWidgetView {
	
	private SynapseClientAsync synapseClient;
	private SynapseJSNIUtils synapseJSNIUtils;
	private WidgetRegistrar widgetRegistrar;
	private IconsImageBundle iconsImageBundle;
	BaseEditWidgetDescriptorPresenter widgetDescriptorEditor;
	private CookieProvider cookies;
	private TextArea markdownTextArea;
	private WikiPageKey wikiKey;
	private boolean isWikiEditor;
	private com.google.gwt.user.client.ui.Button editWidgetButton;
	private WidgetDescriptorUpdatedHandler callback;
	private WidgetSelectionState widgetSelectionState;
	private ResourceLoader resourceLoader;
	private MarkdownWidget markdownWidget;
	private Presenter presenter;
	private Dialog dialog;
	
	@Inject
	public MarkdownEditorWidgetViewImpl(SynapseClientAsync synapseClient,
			SynapseJSNIUtils synapseJSNIUtils, WidgetRegistrar widgetRegistrar,
			IconsImageBundle iconsImageBundle,
			BaseEditWidgetDescriptorPresenter widgetDescriptorEditor,
			CookieProvider cookies,
			ResourceLoader resourceLoader, 
			MarkdownWidget markdownWidget, 
			Dialog dialog) {
		super();
		this.synapseClient = synapseClient;
		this.synapseJSNIUtils = synapseJSNIUtils;
		this.widgetRegistrar = widgetRegistrar;
		this.iconsImageBundle = iconsImageBundle;
		this.widgetDescriptorEditor = widgetDescriptorEditor;
		this.cookies = cookies;
		this.resourceLoader = resourceLoader;
		this.markdownWidget = markdownWidget;
		this.dialog = dialog;
		markdownWidget.addStyleName("margin-10");
		widgetSelectionState = new WidgetSelectionState();
	}
	
	@Override
	public void setPresenter(Presenter presenter) {
		this.presenter = presenter;
	}
	
	/**
	 * 
	 * @param ownerId
	 * @param ownerType
	 * @param markdownTextArea
	 * @param formPanel
	 * @param callback
	 * @param saveHandler if no save handler is specified, then a Save button is not shown.  If it is specified, then Save is shown and saveClicked is called when that button is clicked.
	 */
	public void configure(final WikiPageKey wikiKey, 
			WikiPageKey formattingGuideWikiPageKey,
			final TextArea markdownTextArea, 
			LayoutContainer formPanel,
			boolean showFieldLabel, 
			final boolean isWikiEditor,
			final WidgetDescriptorUpdatedHandler callback,
			final CloseHandler saveHandler,
			final ManagementHandler managementHandler) {
		if (formattingGuideWikiPageKey != null)
			initFormattingGuide(formattingGuideWikiPageKey);
		this.markdownTextArea = markdownTextArea;
		resizeMarkdownTextArea();
		this.wikiKey = wikiKey;
		this.isWikiEditor = isWikiEditor;
		this.callback = callback;
		
		//Toolbar
		final HorizontalPanel mdCommands = new HorizontalPanel();
		mdCommands.setSpacing(2);
		mdCommands.addStyleName("view markdown-editor-commands-container");
		editWidgetButton = getNewCommand("Edit Widget", "glyphicon-pencil",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleEditWidgetCommand();
			}
		}); 
		mdCommands.add(editWidgetButton);
		
		Button insertButton = new Button("Insert", AbstractImagePrototype.create(iconsImageBundle.glyphCirclePlus16()));
		
		insertButton.addStyleName("whiteBackgroundGxt");
		insertButton.setWidth(55);
		insertButton.setMenu(createWidgetMenu(callback));
		FormData descriptionLabelFormData = new FormData();
		descriptionLabelFormData.setMargins(new Margins(0,15,0,17));
		if (showFieldLabel)
			formPanel.add(new Label("Description:"),descriptionLabelFormData);
		FormData mdCommandFormData = new FormData();
		formPanel.add(mdCommands,mdCommandFormData);
		
		markdownTextArea.addStyleName("col-xs-12 col-sm-12 col-md-12 col-lg-12");
		markdownTextArea.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				updateEditWidget();
			}
		});
		
		markdownTextArea.addKeyUpHandler(new KeyUpHandler() {
			
			@Override
			public void onKeyUp(KeyUpEvent event) {
				updateEditWidget();
				resizeMarkdownTextArea();
			}
		});
		
		// followed by description.
		SimplePanel descriptionWrapper= new SimplePanel();
		descriptionWrapper.add(markdownTextArea);
		
		FormData descriptionData = new FormData("-5");
		//descriptionData.setHeight(310);		
        formPanel.add(descriptionWrapper, descriptionData);
		
		//Preview
		final com.google.gwt.user.client.ui.Button previewButton =  new com.google.gwt.user.client.ui.Button();
		previewButton.removeStyleName("gwt-Button");
		previewButton.setText(DisplayConstants.ENTITY_DESCRIPTION_PREVIEW_BUTTON_TEXT);
		previewButton.addStyleName("btn btn-default");
		previewButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				presenter.showPreview(markdownTextArea.getValue(), isWikiEditor);
			}
		});
		
		FormData previewFormData = new FormData("-5");
		previewFormData.setMargins(new Margins(10,0,0,0));
		
		LayoutContainer overallRow = DisplayUtils.createRowContainer();
		LayoutContainer row = DisplayUtils.createRowContainer();
		FlowPanel commands = new FlowPanel();
		commands.addStyleName("margin-top-5 col-md-12");
		row.add(commands);
		overallRow.add(row);
		formPanel.add(overallRow, previewFormData);
		final com.google.gwt.user.client.ui.Button deleteButton =  DisplayUtils.createButton(DisplayConstants.BUTTON_DELETE_WIKI, ButtonType.DANGER);
		final com.google.gwt.user.client.ui.Button attachmentsButton =  DisplayUtils.createButton(DisplayConstants.BUTTON_WIKI_ATTACHMENTS, ButtonType.DEFAULT);
		boolean canManage = managementHandler != null;
		if (canManage) {
			deleteButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					managementHandler.deleteClicked();
				}
			});
			
			attachmentsButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					managementHandler.attachmentsClicked();
				}
			});
		}
		final com.google.gwt.user.client.ui.Button saveButton =  DisplayUtils.createButton(DisplayConstants.SAVE_BUTTON_LABEL, ButtonType.PRIMARY);
		final com.google.gwt.user.client.ui.Button cancelButton = DisplayUtils.createButton(DisplayConstants.BUTTON_CANCEL, ButtonType.DEFAULT);
		boolean canSave = saveHandler != null;
		if (canSave) {
			saveButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					DisplayUtils.changeButtonToSaving(saveButton);
					saveHandler.saveClicked();
				}
			});
						
			cancelButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					saveHandler.cancelClicked();
				}
			});
		}
		
		//add to container
		//save, attachments, preview
		if (canSave) {
			saveButton.addStyleName("margin-right-5");
			commands.add(saveButton);
		}
			
		if (canManage) {
			attachmentsButton.addStyleName("margin-right-5");
			commands.add(attachmentsButton);
		}
		previewButton.addStyleName("margin-right-5");
		commands.add(previewButton);
		
		//then cancel, delete
		if (canManage) {
			deleteButton.addStyleName("pull-right");
			commands.add(deleteButton);
		}
		if (canSave) {
			cancelButton.addStyleName("pull-right margin-right-5");
			commands.add(cancelButton);
		}
		
		
		//Formatting Guide
		com.google.gwt.user.client.ui.Button formatLink = getNewCommand(DisplayConstants.ENTITY_DESCRIPTION_TIPS_TEXT, null, "glyphicon-question-sign", new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				//pop up format guide
				showFormattingGuideDialog();
			}
		});
		mdCommands.add(formatLink);
		mdCommands.add(insertButton);
		
		//basic commands
		String startTag = "**";
		String endTag = startTag;
		com.google.gwt.user.client.ui.Button boldCommand = getNewCommand("Bold", "glyphicon-bold", getBasicCommandClickHandler(startTag, endTag, false));
		boldCommand.addStyleName("margin-left-10");
		mdCommands.add(boldCommand);

		startTag = "_";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button italicCommand = getNewCommand("Italicize", "glyphicon-italic",  getBasicCommandClickHandler(startTag, endTag, false));
		mdCommands.add(italicCommand);

		startTag = "--";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button strikeCommand = getNewCommand("Strikeout", "", getBasicCommandClickHandler(startTag, endTag, false));
		strikeCommand.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("strike")));
		strikeCommand.addStyleName("font-size-15");
		mdCommands.add(strikeCommand);

		startTag = "\n```\n";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button codeCommand = getNewCommand("Code Block", "Optionally specify the language for syntax highlighting.", "", getBasicCommandClickHandler(startTag, endTag, true));
		mdCommands.add(codeCommand);
		
		startTag = "$$\\(";
		endTag = "\\)$$";
		com.google.gwt.user.client.ui.Button mathCommand = getNewCommand("TeX", "LaTeX math equation.", "", getBasicCommandClickHandler(startTag, endTag, false));
		mdCommands.add(mathCommand);
		
		
		startTag = "~";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button subscript = getNewCommand("", "Subscript", "", getBasicCommandClickHandler(startTag, endTag, false));
		subscript.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("subscript")));
		subscript.addStyleName("font-size-15");
		mdCommands.add(subscript);
		
		startTag = "^";
		endTag = startTag;
		com.google.gwt.user.client.ui.Button superscript = getNewCommand("", "Superscript", "", getBasicCommandClickHandler(startTag, endTag, false));
		superscript.setHTML(SafeHtmlUtils.fromSafeConstant(DisplayUtils.getFontelloIcon("superscript")));
		superscript.addStyleName("font-size-15");
		mdCommands.add(superscript);
		
		Button headingButton = new Button("Heading");
		DisplayUtils.addToolTip(headingButton, "Heading");
		headingButton.addStyleName("whiteBackgroundGxt boldText");
		headingButton.setWidth(60);
		headingButton.setMenu(createHeadingMenu());
		headingButton.addStyleName("margin-right-10");
		mdCommands.add(headingButton);
		
		if (isWikiEditor) {
			com.google.gwt.user.client.ui.Button attachment = getNewCommand("Insert Attachment", "glyphicon-paperclip",new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					handleInsertWidgetCommand(WidgetConstants.ATTACHMENT_PREVIEW_CONTENT_TYPE, callback);
				}
			}); 

			mdCommands.add(attachment);
		}

		com.google.gwt.user.client.ui.Button image = getNewCommand("Insert Image", "glyphicon-camera",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand(WidgetConstants.IMAGE_CONTENT_TYPE, callback);
			}
		});
		mdCommands.add(image);
		
		com.google.gwt.user.client.ui.Button video = getNewCommand("Insert Video", "glyphicon-facetime-video",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand(WidgetConstants.VIDEO_CONTENT_TYPE, callback);
			}
		}); 
		mdCommands.add(video);

		com.google.gwt.user.client.ui.Button link = getNewCommand("Insert Link", "glyphicon-link",new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				handleInsertWidgetCommand( WidgetConstants.LINK_CONTENT_TYPE, callback);
			}
		}); 

		mdCommands.add(link);
		formPanel.layout(true);
		//defers code until after the browser redraws the page (because of the gxt LayoutContainer life cycle). 
		//scrolls the browser window such that the markdown command bar is at the top of the screen
		Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
			@Override
			public void execute() {
				if (mdCommands != null && mdCommands.getElement() != null)
					Window.scrollTo(0, mdCommands.getElement().getAbsoluteTop());
			}
		});
		
		mdCommands.add(dialog);
	}
	
	public void handleEditWidgetCommand() {
		if (widgetSelectionState != null && widgetSelectionState.isWidgetSelected()) {
			final int widgetStartIndex = widgetSelectionState.getWidgetStartIndex();
			final int widgetEndIndex = widgetSelectionState.getWidgetEndIndex();
			String innerText = widgetSelectionState.getInnerWidgetText();
			markdownTextArea.setSelectionRange(widgetStartIndex, innerText.length());
			String contentTypeKey = widgetRegistrar.getWidgetContentType(innerText);
			Map<String, String> widgetDescriptor = widgetRegistrar.getWidgetDescriptor(innerText);
			BaseEditWidgetDescriptorPresenter.editExistingWidget(widgetDescriptorEditor, wikiKey, contentTypeKey, widgetDescriptor, new WidgetDescriptorUpdatedHandler() {
				@Override
			public void onUpdate(WidgetDescriptorUpdatedEvent event) {
					//replace old widget text
					String text = markdownTextArea.getText();
					if (widgetStartIndex > -1 && widgetEndIndex > -1) {
						markdownTextArea.setText(text.substring(0, widgetStartIndex) + text.substring(widgetEndIndex));
						markdownTextArea.setCursorPos(widgetStartIndex);
						if (event.getInsertValue()!=null) {
							insertMarkdown(event.getInsertValue());
						}
						if (callback != null)
							callback.onUpdate(event);
					}
				}
{'fraction_non_alphanumeric': 0.10779011291393871, 'fraction_numerical': 0.0034158838599487617, 'mean_word_length': 5.30091669988043, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5715498', 'n_tokens_mistral': 10681, 'n_tokens_neox': 9482, 'n_words': 1608}