/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.editor.orion.client; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.JsArray; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.DomEvent; import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.HasChangeHandlers; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.json.client.JSONObject; import com.google.gwt.resources.client.CssResource; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.SimplePanel; import com.google.inject.Provider; import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.AssistedInject; import com.google.web.bindery.event.shared.EventBus; import org.eclipse.che.api.promises.client.Operation; import org.eclipse.che.api.promises.client.OperationException; import org.eclipse.che.ide.api.dialogs.DialogFactory; import org.eclipse.che.ide.api.editor.annotation.AnnotationModel; import org.eclipse.che.ide.api.editor.annotation.AnnotationModelEvent; import org.eclipse.che.ide.api.editor.codeassist.AdditionalInfoCallback; import org.eclipse.che.ide.api.editor.codeassist.CompletionProposal; import org.eclipse.che.ide.api.editor.codeassist.CompletionReadyCallback; import org.eclipse.che.ide.api.editor.codeassist.CompletionsSource; import org.eclipse.che.ide.api.editor.events.CursorActivityEvent; import org.eclipse.che.ide.api.editor.events.CursorActivityHandler; import org.eclipse.che.ide.api.editor.events.GutterClickEvent; import org.eclipse.che.ide.api.editor.events.GutterClickHandler; import org.eclipse.che.ide.api.editor.events.HasCursorActivityHandlers; import org.eclipse.che.ide.api.editor.gutter.Gutter; import org.eclipse.che.ide.api.editor.gutter.Gutters; import org.eclipse.che.ide.api.editor.gutter.HasGutter; import org.eclipse.che.ide.api.editor.keymap.KeyBinding; import org.eclipse.che.ide.api.editor.keymap.Keymap; import org.eclipse.che.ide.api.editor.keymap.KeymapChangeEvent; import org.eclipse.che.ide.api.editor.keymap.KeymapChangeHandler; import org.eclipse.che.ide.api.editor.link.LinkedMode; import org.eclipse.che.ide.api.editor.position.PositionConverter; import org.eclipse.che.ide.api.editor.text.Position; import org.eclipse.che.ide.api.editor.text.Region; import org.eclipse.che.ide.api.editor.text.RegionImpl; import org.eclipse.che.ide.api.editor.text.TextRange; import org.eclipse.che.ide.api.editor.text.annotation.Annotation; import org.eclipse.che.ide.api.editor.texteditor.ContentInitializedHandler; import org.eclipse.che.ide.api.editor.texteditor.EditorWidget; import org.eclipse.che.ide.api.editor.texteditor.HandlesUndoRedo; import org.eclipse.che.ide.api.editor.texteditor.LineStyler; import org.eclipse.che.ide.api.event.EditorSettingsChangedEvent; import org.eclipse.che.ide.api.event.EditorSettingsChangedEvent.EditorSettingsChangedHandler; import org.eclipse.che.ide.api.event.SelectionChangedEvent; import org.eclipse.che.ide.api.event.SelectionChangedHandler; import org.eclipse.che.ide.api.hotkeys.HotKeyItem; import org.eclipse.che.ide.api.preferences.PreferencesManager; import org.eclipse.che.ide.editor.orion.client.events.HasScrollHandlers; import org.eclipse.che.ide.editor.orion.client.events.ScrollEvent; import org.eclipse.che.ide.editor.orion.client.events.ScrollHandler; import org.eclipse.che.ide.editor.orion.client.incremental.find.IncrementalFindReportStatusObserver; import org.eclipse.che.ide.editor.orion.client.jso.OrionAnnotationModelOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionAnnotationOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionCodeEditWidgetOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionContentAssistOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionEditorOptionsOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionEditorOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionEditorViewOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionEventTargetOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionExtRulerOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionInputChangedEventOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionKeyBindingsRelationOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionKeyModeOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionKeyStrokeOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionProblemOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionRulerClickEventOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionSelectionOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionStyleOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionTextViewOverlay; import org.eclipse.che.ide.editor.orion.client.jso.StatusMessageReporterOverlay; import org.eclipse.che.ide.editor.orion.client.jso.UiUtilsOverlay; import org.eclipse.che.ide.editor.preferences.editorproperties.EditorPropertiesManager; import org.eclipse.che.ide.editor.preferences.keymaps.KeyMapsPreferencePresenter; import org.eclipse.che.ide.status.message.StatusMessageReporter; import org.eclipse.che.ide.util.browser.UserAgent; import org.eclipse.che.ide.util.loging.Log; import org.eclipse.che.requirejs.ModuleHolder; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import static org.eclipse.che.ide.editor.orion.client.KeyMode.EMACS; import static org.eclipse.che.ide.editor.orion.client.KeyMode.VI; /** * Orion implementation for {@link EditorWidget}. * * @author "Mickaël Leduque" */ public class OrionEditorWidget extends Composite implements EditorWidget, HasChangeHandlers, HasCursorActivityHandlers, HasScrollHandlers, HasGutter { /** The UI binder instance. */ private static final OrionEditorWidgetUiBinder UIBINDER = GWT.create(OrionEditorWidgetUiBinder.class); /** The logger. */ private static final Logger LOG = Logger.getLogger(OrionEditorWidget.class.getSimpleName()); private final ModuleHolder moduleHolder; private final EventBus eventBus; private final KeyModeInstances keyModeInstances; private final JavaScriptObject uiUtilsOverlay; private final ContentAssistWidgetFactory contentAssistWidgetFactory; private final DialogFactory dialogFactory; private final PreferencesManager preferencesManager; @UiField SimplePanel panel; /** The instance of the orion editor native element style. */ @UiField EditorElementStyle editorElementStyle; private OrionEditorViewOverlay editorViewOverlay; private OrionEditorOverlay editorOverlay; private String modeName; private OrionExtRulerOverlay orionLineNumberRuler; /** Component that handles undo/redo. */ private HandlesUndoRedo undoRedo; private OrionDocument embeddedDocument; private OrionKeyModeOverlay cheContentAssistMode; private EditorPropertiesManager editorPropertiesManager; private Keymap keymap; private ContentAssistWidget assistWidget; private Gutter gutter; private boolean changeHandlerAdded = false; private boolean focusHandlerAdded = false; private boolean blurHandlerAdded = false; private boolean scrollHandlerAdded = false; private boolean cursorHandlerAdded = false; private boolean gutterClickHandlerAdded = false; /** Component that handles line styling. */ private LineStyler lineStyler; @AssistedInject public OrionEditorWidget(final ModuleHolder moduleHolder, final KeyModeInstances keyModeInstances, final EventBus eventBus, final EditorPropertiesManager editorPropertiesManager, final Provider<OrionCodeEditWidgetOverlay> orionCodeEditWidgetProvider, final ContentAssistWidgetFactory contentAssistWidgetFactory, final DialogFactory dialogFactory, final PreferencesManager preferencesManager, @Assisted final List<String> editorModes, @Assisted final WidgetInitializedCallback widgetInitializedCallback, final Provider<OrionEditorOptionsOverlay> editorOptionsProvider, final StatusMessageReporter statusMessageReporter, final IncrementalFindReportStatusObserver incrementalFindObserver) { this.contentAssistWidgetFactory = contentAssistWidgetFactory; this.moduleHolder = moduleHolder; this.keyModeInstances = keyModeInstances; this.eventBus = eventBus; this.dialogFactory = dialogFactory; this.preferencesManager = preferencesManager; initWidget(UIBINDER.createAndBindUi(this)); this.editorPropertiesManager = editorPropertiesManager; this.uiUtilsOverlay = moduleHolder.getModule("UiUtils"); // just first choice for the moment if (editorModes != null && !editorModes.isEmpty()) { setMode(editorModes.get(0)); } panel.getElement().setId("orion-parent-" + Document.get().createUniqueId()); panel.getElement().addClassName(this.editorElementStyle.editorParent()); OrionEditorOptionsOverlay editorOptions = initEditorOptions(editorOptionsProvider.get(), statusMessageReporter); orionCodeEditWidgetProvider.get().createEditorView(panel.getElement(), editorOptions) .then(new EditorViewCreatedOperation(widgetInitializedCallback)); incrementalFindObserver.setEditorWidget(this); statusMessageReporter.registerObserver(incrementalFindObserver); registerPromptFunction(); eventBus.addHandler(EditorSettingsChangedEvent.TYPE, new EditorSettingsChangedHandler() { @Override public void onEditorSettingsChanged(EditorSettingsChangedEvent event) { final JSONObject properties = editorPropertiesManager.getJsonEditorProperties(); editorViewOverlay.updateSettings(properties.getJavaScriptObject()); } }); } private OrionEditorOptionsOverlay initEditorOptions(OrionEditorOptionsOverlay orionEditorOptionsOverlay, StatusMessageReporter statusMessageReporter) { StatusMessageReporterOverlay statusMessageReporterOverlay = StatusMessageReporterOverlay.create(statusMessageReporter); orionEditorOptionsOverlay.setStatusReporter(statusMessageReporterOverlay); return orionEditorOptionsOverlay; } private Gutter initBreakpointRuler(ModuleHolder moduleHolder) { JavaScriptObject orionEventTargetModule = moduleHolder.getModule("OrionEventTarget"); orionLineNumberRuler = editorOverlay.getTextView().getRulers()[1]; orionLineNumberRuler.overrideOnClickEvent(); OrionEventTargetOverlay.addMixin(orionEventTargetModule, orionLineNumberRuler); return new OrionBreakpointRuler(orionLineNumberRuler, editorOverlay); } @Override public String getValue() { return editorOverlay.getText(); } @Override public void setValue(String newValue, final ContentInitializedHandler initializationHandler) { editorOverlay.addEventListener(OrionInputChangedEventOverlay.TYPE, new OrionEditorOverlay.EventHandler<OrionInputChangedEventOverlay>() { @Override public void onEvent(OrionInputChangedEventOverlay event) { if (initializationHandler != null) { initializationHandler.onContentInitialized(); } } }, true); this.editorViewOverlay.setContents(newValue, modeName); this.editorOverlay.getUndoStack().reset(); } @Override public String getMode() { return modeName; } public void setMode(final String modeName) { String mode = modeName; if (modeName.equals("text/x-java")) { mode = "text/x-java-source"; } LOG.fine("Requested mode: " + modeName + " kept " + mode); this.modeName = mode; } @Override public boolean isReadOnly() { return this.editorOverlay.getTextView().getOptions().isReadOnly(); } @Override public void setReadOnly(final boolean isReadOnly) { editorViewOverlay.setReadonly(isReadOnly); final JSONObject properties = editorPropertiesManager.getJsonEditorProperties(); editorViewOverlay.updateSettings(properties.getJavaScriptObject()); } @Override public void setAnnotationRulerVisible(boolean show) { editorOverlay.setAnnotationRulerVisible(show); } @Override public void setFoldingRulerVisible(boolean show) { editorOverlay.setFoldingRulerVisible(show); } @Override public void setZoomRulerVisible(boolean show) { editorOverlay.setZoomRulerVisible(show); } @Override public void setOverviewRulerVisible(boolean show) { editorOverlay.setOverviewRulerVisible(show); } @Override public boolean isDirty() { return this.editorOverlay.isDirty(); } @Override public void markClean() { this.editorOverlay.setDirty(false); } private void selectKeyMode(Keymap keymap) { resetKeyModes(); Keymap usedKeymap = keymap; if (usedKeymap == null) { usedKeymap = KeyMode.DEFAULT; } if (KeyMode.DEFAULT.equals(usedKeymap)) { // nothing to do } else if (EMACS.equals(usedKeymap)) { this.editorOverlay.getTextView().addKeyMode(keyModeInstances.getInstance(EMACS)); } else if (VI.equals(usedKeymap)) { this.editorOverlay.getTextView().addKeyMode(keyModeInstances.getInstance(VI)); } else { usedKeymap = KeyMode.DEFAULT; Log.error(OrionEditorWidget.class, "Unknown keymap type: " + keymap + " - changing to default one."); } this.keymap = usedKeymap; } private void resetKeyModes() { this.editorOverlay.getTextView().removeKeyMode(keyModeInstances.getInstance(VI)); this.editorOverlay.getTextView().removeKeyMode(keyModeInstances.getInstance(EMACS)); } @Override public org.eclipse.che.ide.api.editor.document.Document getDocument() { if (this.embeddedDocument == null) { this.embeddedDocument = new OrionDocument(this.editorOverlay.getTextView(), this, editorOverlay); } return this.embeddedDocument; } @Override public Region getSelectedRange() { final OrionSelectionOverlay selection = this.editorOverlay.getSelection(); final int start = selection.getStart(); final int end = selection.getEnd(); if (start < 0 || end > this.editorOverlay.getModel().getCharCount() || start > end) { throw new RuntimeException("Invalid selection"); } return new RegionImpl(start, end - start); } @Override public void setSelectedRange(final Region selection, final boolean show) { this.editorOverlay.setSelection(selection.getOffset(), selection.getLength(), show); } @Override public void setDisplayRange(final Region range) { // show the line at the head of the range final int headOffset = range.getOffset() + range.getLength(); if (range.getLength() < 0) { this.editorOverlay.getTextView().setTopIndex(headOffset); } else { this.editorOverlay.getTextView().setBottomIndex(headOffset); } } @Override public int getTabSize() { return this.editorOverlay.getTextView().getOptions().getTabSize(); } @Override public void setTabSize(int tabSize) { this.editorOverlay.getTextView().getOptions().setTabSize(tabSize); } @Override public HandlerRegistration addChangeHandler(final ChangeHandler handler) { if (!changeHandlerAdded) { changeHandlerAdded = true; final OrionTextViewOverlay textView = this.editorOverlay.getTextView(); textView.addEventListener(OrionEventConstants.MODEL_CHANGED_EVENT, new OrionTextViewOverlay.EventHandlerNoParameter() { @Override public void onEvent() { fireChangeEvent(); } }); } return addHandler(handler, ChangeEvent.getType()); } private void fireChangeEvent() { DomEvent.fireNativeEvent(Document.get().createChangeEvent(), this); } @Override public HandlerRegistration addCursorActivityHandler(CursorActivityHandler handler) { if (!cursorHandlerAdded) { cursorHandlerAdded = true; final OrionTextViewOverlay textView = this.editorOverlay.getTextView(); textView.addEventListener(OrionEventConstants.SELECTION_EVENT, new OrionTextViewOverlay.EventHandlerNoParameter() { @Override public void onEvent() { fireCursorActivityEvent(); } }); } return addHandler(handler, CursorActivityEvent.TYPE); } private void fireCursorActivityEvent() { fireEvent(new CursorActivityEvent()); } @Override public HandlerRegistration addFocusHandler(FocusHandler handler) { if (!focusHandlerAdded) { focusHandlerAdded = true; final OrionTextViewOverlay textView = this.editorOverlay.getTextView(); textView.addEventListener(OrionEventConstants.FOCUS_EVENT, new OrionTextViewOverlay.EventHandlerNoParameter() { @Override public void onEvent() { fireFocusEvent(); } }); } return addHandler(handler, FocusEvent.getType()); } private void fireFocusEvent() { DomEvent.fireNativeEvent(Document.get().createFocusEvent(), this); } @Override public HandlerRegistration addBlurHandler(BlurHandler handler) { if (!blurHandlerAdded) { blurHandlerAdded = true; final OrionTextViewOverlay textView = this.editorOverlay.getTextView(); textView.addEventListener(OrionEventConstants.BLUR_EVENT, new OrionTextViewOverlay.EventHandlerNoParameter() { @Override public void onEvent() { fireBlurEvent(); } }); } return addHandler(handler, BlurEvent.getType()); } private void fireBlurEvent() { DomEvent.fireNativeEvent(Document.get().createBlurEvent(), this); } @Override public HandlerRegistration addScrollHandler(final ScrollHandler handler) { if (!scrollHandlerAdded) { scrollHandlerAdded = true; final OrionTextViewOverlay textView = this.editorOverlay.getTextView(); textView.addEventListener(OrionEventConstants.SCROLL_EVENT, new OrionTextViewOverlay.EventHandlerNoParameter() { @Override public void onEvent() { fireScrollEvent(); } }); } return addHandler(handler, ScrollEvent.TYPE); } private void fireScrollEvent() { fireEvent(new ScrollEvent()); } private void setupKeymode() { final String propertyValue = preferencesManager.getValue(KeyMapsPreferencePresenter.KEYMAP_PREF_KEY); Keymap keymap; try { keymap = Keymap.fromKey(propertyValue); } catch (final IllegalArgumentException e) { LOG.log(Level.WARNING, "Unknown value in keymap preference.", e); return; } selectKeyMode(keymap); } @Override public Keymap getKeymap() { return this.keymap; } @Override public PositionConverter getPositionConverter() { return embeddedDocument.getPositionConverter(); } @Override public void setFocus() { this.editorOverlay.focus(); } @Override public void showMessage(final String message) { this.editorOverlay.reportStatus(message); } @Override protected void onLoad() { // fix for native editor height if (panel.getElement().getChildCount() > 0) { final Element child = panel.getElement().getFirstChildElement(); child.setId("orion-editor-" + Document.get().createUniqueId()); child.getStyle().clearHeight(); } else { LOG.severe("Orion insertion failed."); } } @Override public void onResize() { // redraw text and rulers // maybe just redrawing the text would be enough this.editorOverlay.getTextView().redraw(); } @Override public HandlesUndoRedo getUndoRedo() { return this.undoRedo; } @Override public void addKeyBinding(final KeyBinding keyBinding) { addKeyBinding(keyBinding, ""); } @Override public void addKeyBinding(final KeyBinding keyBinding, String actionDescription) { OrionKeyStrokeOverlay strokeOverlay; JavaScriptObject keyBindingModule = moduleHolder.getModule("OrionKeyBinding").cast(); String type = keyBinding.getType(); boolean modifier1 = UserAgent.isMac() ? keyBinding.isCmd() : keyBinding.isControl(); boolean modifier2 = keyBinding.isShift(); boolean modifier3 = keyBinding.isAlt(); boolean modifier4 = UserAgent.isMac() ? keyBinding.isControl() : false; if (keyBinding.isCharacterBinding()) { strokeOverlay = OrionKeyStrokeOverlay.create(keyBinding.getCharacter(), modifier1, modifier2, modifier3, modifier4, type, keyBindingModule); } else { strokeOverlay = OrionKeyStrokeOverlay.create(keyBinding.getKeyCodeNumber(), modifier1, modifier2, modifier3, modifier4, type, keyBindingModule); } String actionId = "che-action-" + keyBinding.getAction().toString(); editorOverlay.getTextView().setKeyBinding(strokeOverlay, actionId); editorOverlay.getTextView().setAction(actionId, new Action() { @Override public boolean onAction() { return keyBinding.getAction().action(); } }, actionDescription); } @Override public List<HotKeyItem> getHotKeys() { OrionTextViewOverlay orionTextViewOverlay = editorOverlay.getTextView(); List<HotKeyItem> hotKeyItems = new ArrayList<>(); JsArray<OrionKeyBindingsRelationOverlay> keyBindings = OrionKeyModeOverlay.getKeyBindings_(orionTextViewOverlay); for (int i = 0; i < keyBindings.length(); i++) { OrionKeyBindingsRelationOverlay key = keyBindings.get(i); String actionId = key.getActionId(); String actionDescription = orionTextViewOverlay.getActionDescription(actionId); String hotKey = UiUtilsOverlay.getUserKeyString(uiUtilsOverlay, key.getKeyBindings()); if (actionDescription != null) { hotKeyItems.add(new HotKeyItem(actionDescription, hotKey)); } } return hotKeyItems; } @Override public MarkerRegistration addMarker(final TextRange range, final String className) { final OrionAnnotationOverlay annotation = OrionAnnotationOverlay.create(); OrionStyleOverlay styleOverlay = OrionStyleOverlay.create(); styleOverlay.setStyleClass(className); int start = embeddedDocument.getIndexFromPosition(range.getFrom()); int end = embeddedDocument.getIndexFromPosition(range.getTo()); annotation.setStart(start); annotation.setEnd(end); annotation.setRangeStyle(styleOverlay); annotation.setType("che-marker"); editorOverlay.getAnnotationModel().addAnnotation(annotation); return new MarkerRegistration() { @Override public void clearMark() { editorOverlay.getAnnotationModel().removeAnnotation(annotation); } }; } @Override public void showCompletionsProposals(final List<CompletionProposal> proposals) { if (proposals == null || proposals.isEmpty()) { /** Hide autocompletion when it's visible and it is nothing to propose */ if (assistWidget.isVisible()) { assistWidget.hide(); } return; } assistWidget.show(proposals); } @Override public void showCompletionProposals(final CompletionsSource completionsSource) { completionsSource.computeCompletions(new CompletionReadyCallback() { @Override public void onCompletionReady(List<CompletionProposal> proposals) { showCompletionsProposals(proposals); } }); } @Override public LineStyler getLineStyler() { return lineStyler; } @Override public HandlerRegistration addGutterClickHandler(final GutterClickHandler handler) { if (!gutterClickHandlerAdded) { gutterClickHandlerAdded = true; orionLineNumberRuler.addEventListener(OrionEventConstants.RULER_CLICK_EVENT, new OrionExtRulerOverlay.EventHandler<OrionRulerClickEventOverlay>() { @Override public void onEvent(OrionRulerClickEventOverlay parameter) { final int lineIndex = parameter.getLineIndex(); fireGutterClickEvent(lineIndex); } }, false); } return addHandler(handler, GutterClickEvent.TYPE); } private void fireGutterClickEvent(final int line) { final GutterClickEvent gutterEvent = new GutterClickEvent(line, Gutters.BREAKPOINTS_GUTTER, null); fireEvent(gutterEvent); this.embeddedDocument.getDocEventBus().fireEvent(gutterEvent); } @Override public void showCompletionProposals() { editorOverlay.getContentAssist().activate(); } @Override public void showCompletionProposals(final CompletionsSource completionsSource, final AdditionalInfoCallback additionalInfoCallback) { showCompletionProposals(completionsSource); } @Override public void refresh() { this.editorOverlay.getTextView().redraw(); } @Override public boolean isCompletionProposalsShowing() { return assistWidget.isVisible(); } public void scrollToLine(int line) { this.editorOverlay.getTextView().setTopIndex(line); } public void showErrors(AnnotationModelEvent event) { List<Annotation> addedAnnotations = event.getAddedAnnotations(); JsArray<OrionProblemOverlay> jsArray = JsArray.createArray().cast(); AnnotationModel annotationModel = event.getAnnotationModel(); OrionAnnotationSeverityProvider severityProvider = null; if (annotationModel instanceof OrionAnnotationSeverityProvider) { severityProvider = (OrionAnnotationSeverityProvider)annotationModel; } for (Annotation annotation : addedAnnotations) { Position position = annotationModel.getPosition(annotation); OrionProblemOverlay problem = JavaScriptObject.createObject().cast(); problem.setDescription(annotation.getText()); problem.setStart(position.getOffset()); problem.setEnd(position.getOffset() + position.getLength()); problem.setId("che-annotation"); problem.setSeverity(getSeverity(annotation.getType(), severityProvider)); jsArray.push(problem); } editorOverlay.showProblems(jsArray); } private String getSeverity(String type, OrionAnnotationSeverityProvider provider) { if (provider != null) { return provider.getSeverity(type); } else { return "error"; } } public void clearErrors() { editorOverlay.showProblems(JavaScriptObject.createArray().<JsArray<OrionProblemOverlay>>cast()); } public OrionTextViewOverlay getTextView() { return editorOverlay.getTextView(); } public LinkedMode getLinkedMode() { return editorOverlay.getLinkedMode(editorOverlay.getAnnotationModel()); } public void showCompletionInformation() { if (assistWidget.isVisible()) { assistWidget.showCompletionInfo(); } } public OrionAnnotationModelOverlay getAnnotationModel() { return editorOverlay.getAnnotationModel(); } /** * Returns {@link OrionEditorOverlay}. */ public OrionEditorOverlay getEditor() { return editorOverlay; } @Override public Gutter getGutter() { return gutter; } public int getTopVisibleLine() { return editorOverlay.getTextView().getTopIndex(); } public void setTopLine(int line) { editorOverlay.getTextView().setTopIndex(line); } /** * UI binder interface for this component. * * @author "Mickaël Leduque" */ interface OrionEditorWidgetUiBinder extends UiBinder<SimplePanel, OrionEditorWidget> { } /** * CSS style for the orion native editor element. * * @author "Mickaël Leduque" */ public interface EditorElementStyle extends CssResource { @ClassName("editor-parent") String editorParent(); } private class EditorViewCreatedOperation implements Operation<OrionEditorViewOverlay> { private final WidgetInitializedCallback widgetInitializedCallback; private EditorViewCreatedOperation(WidgetInitializedCallback widgetInitializedCallback) { this.widgetInitializedCallback = widgetInitializedCallback; } @Override public void apply(OrionEditorViewOverlay arg) throws OperationException { editorViewOverlay = arg; editorOverlay = arg.getEditor(); final OrionContentAssistOverlay contentAssist = editorOverlay.getContentAssist(); eventBus.addHandler(SelectionChangedEvent.TYPE, new SelectionChangedHandler() { @Override public void onSelectionChanged(SelectionChangedEvent event) { if (contentAssist.isActive()) { contentAssist.deactivate(); } } }); lineStyler = new OrionLineStyler(editorOverlay); final OrionTextViewOverlay textView = editorOverlay.getTextView(); keyModeInstances.add(VI, OrionKeyModeOverlay.getViKeyMode(moduleHolder.getModule("OrionVi"), textView)); keyModeInstances.add(EMACS, OrionKeyModeOverlay.getEmacsKeyMode(moduleHolder.getModule("OrionEmacs"), textView)); setupKeymode(); eventBus.addHandler(KeymapChangeEvent.TYPE, new KeymapChangeHandler() { @Override public void onKeymapChanged(final KeymapChangeEvent event) { setupKeymode(); } }); undoRedo = new OrionUndoRedo(editorOverlay.getUndoStack()); editorOverlay.setZoomRulerVisible(true); editorOverlay.getAnnotationStyler().addAnnotationType("che-marker", 100); cheContentAssistMode = OrionKeyModeOverlay.getCheCodeAssistMode(moduleHolder.getModule("CheContentAssistMode"), editorOverlay.getTextView()); assistWidget = contentAssistWidgetFactory.create(OrionEditorWidget.this, cheContentAssistMode); gutter = initBreakpointRuler(moduleHolder); final JSONObject editorProperties = editorPropertiesManager.getJsonEditorProperties(); editorViewOverlay.updateSettings(editorProperties.getJavaScriptObject()); widgetInitializedCallback.initialized(OrionEditorWidget.this); } } /** * Registers global prompt function to be accessible directly from JavaScript. * <p/> * Function promptIDE(title, text, defaultValue, callback) * title Dialog title * text The text to display in the dialog box * defaultValue The default value * callback function(value) * clicking "OK" will return input value * clicking "Cancel" will return null */ private native void registerPromptFunction() /*-{ if (!$wnd["promptIDE"]) { var instance = this; $wnd["promptIDE"] = function (title, text, defaultValue, callback) { instance.@org.eclipse.che.ide.editor.orion.client.OrionEditorWidget::askLineNumber(*)(title, text, defaultValue, callback); }; } }-*/; /** * Custom callback to pass given value to native javascript function. */ private class InputCallback implements org.eclipse.che.ide.api.dialogs.InputCallback { private JavaScriptObject callback; public InputCallback(JavaScriptObject callback) { this.callback = callback; } @Override public native void accepted(String value) /*-{ var callback = this.@org.eclipse.che.ide.editor.orion.client.OrionEditorWidget.InputCallback::callback; callback(value); }-*/; } private void askLineNumber(String title, String text, String defaultValue, final JavaScriptObject callback) { if (defaultValue == null) { defaultValue = ""; } else { // It's strange situation defaultValue.length() returns 'undefined' but must return a number. // Reinitialise the variable resolves the problem. defaultValue = "" + defaultValue; } dialogFactory.createInputDialog(title, text, defaultValue, 0, defaultValue.length(), new InputCallback(callback), null).show(); } }