/*******************************************************************************
* Copyright (c) 2014-2015 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.JSONBoolean;
import com.google.gwt.json.client.JSONNumber;
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.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.event.SelectionChangedEvent;
import org.eclipse.che.ide.api.event.SelectionChangedHandler;
import org.eclipse.che.ide.api.text.Position;
import org.eclipse.che.ide.api.text.Region;
import org.eclipse.che.ide.api.text.RegionImpl;
import org.eclipse.che.ide.api.text.annotation.Annotation;
import org.eclipse.che.ide.api.texteditor.HandlesUndoRedo;
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.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.OrionKeyBindingModule;
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.OrionTextThemeOverlay;
import org.eclipse.che.ide.editor.orion.client.jso.OrionTextViewOverlay;
import org.eclipse.che.ide.editor.orion.client.jso.UiUtilsOverlay;
import org.eclipse.che.ide.hotkeys.HotKeyItem;
import org.eclipse.che.ide.jseditor.client.annotation.AnnotationModel;
import org.eclipse.che.ide.jseditor.client.annotation.AnnotationModelEvent;
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionProposal;
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionReadyCallback;
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionsSource;
import org.eclipse.che.ide.jseditor.client.editortype.EditorType;
import org.eclipse.che.ide.jseditor.client.events.CursorActivityEvent;
import org.eclipse.che.ide.jseditor.client.events.CursorActivityHandler;
import org.eclipse.che.ide.jseditor.client.events.GutterClickEvent;
import org.eclipse.che.ide.jseditor.client.events.GutterClickHandler;
import org.eclipse.che.ide.jseditor.client.events.HasCursorActivityHandlers;
import org.eclipse.che.ide.jseditor.client.events.HasScrollHandlers;
import org.eclipse.che.ide.jseditor.client.events.ScrollEvent;
import org.eclipse.che.ide.jseditor.client.events.ScrollHandler;
import org.eclipse.che.ide.jseditor.client.gutter.Gutter;
import org.eclipse.che.ide.jseditor.client.gutter.Gutters;
import org.eclipse.che.ide.jseditor.client.gutter.HasGutter;
import org.eclipse.che.ide.jseditor.client.keymap.Keybinding;
import org.eclipse.che.ide.jseditor.client.keymap.Keymap;
import org.eclipse.che.ide.jseditor.client.keymap.KeymapChangeEvent;
import org.eclipse.che.ide.jseditor.client.keymap.KeymapChangeHandler;
import org.eclipse.che.ide.jseditor.client.link.LinkedMode;
import org.eclipse.che.ide.jseditor.client.position.PositionConverter;
import org.eclipse.che.ide.jseditor.client.prefmodel.KeymapPrefReader;
import org.eclipse.che.ide.jseditor.client.requirejs.ModuleHolder;
import org.eclipse.che.ide.jseditor.client.text.TextRange;
import org.eclipse.che.ide.jseditor.client.texteditor.CompositeEditorWidget;
import org.eclipse.che.ide.jseditor.client.texteditor.ContentInitializedHandler;
import org.eclipse.che.ide.jseditor.client.texteditor.EditorWidget;
import org.eclipse.che.ide.jseditor.client.texteditor.LineStyler;
import org.eclipse.che.ide.util.browser.UserAgent;
import org.eclipse.che.ide.util.loging.Log;
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 CompositeEditorWidget implements 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 OrionCodeEditWidgetOverlay codeEditWidgetModule;
private final ModuleHolder moduleHolder;
private final EventBus eventBus;
private final KeyModeInstances keyModeInstances;
private final JavaScriptObject uiUtilsOverlay;
private final KeymapPrefReader keymapPrefReader;
private final ContentAssistWidgetFactory contentAssistWidgetFactory;
@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 Keymap keymap;
private Provider<OrionKeyBindingModule> keyBindingModuleProvider;
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 KeymapPrefReader keymapPrefReader,
final Provider<OrionKeyBindingModule> keyBindingModuleProvider,
final ContentAssistWidgetFactory contentAssistWidgetFactory,
@Assisted final List<String> editorModes,
@Assisted final WidgetInitializedCallback widgetInitializedCallback) {
this.keyBindingModuleProvider = keyBindingModuleProvider;
this.contentAssistWidgetFactory = contentAssistWidgetFactory;
this.moduleHolder = moduleHolder;
this.keyModeInstances = keyModeInstances;
this.eventBus = eventBus;
initWidget(UIBINDER.createAndBindUi(this));
this.keymapPrefReader = keymapPrefReader;
this.codeEditWidgetModule = moduleHolder.getModule("CodeEditWidget").cast();
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());
codeEditWidgetModule.createEditorView(panel.getElement(), JavaScriptObject.createObject())
.then(new EditorViewCreatedOperation(widgetInitializedCallback));
}
private static JavaScriptObject getEditorSettings() {
final JSONObject json = new JSONObject();
json.put("theme", new JSONObject(OrionTextThemeOverlay.getDefautTheme()));
// TextViewOptions (tabs)
json.put("expandTab", JSONBoolean.getInstance(true));
json.put("tabSize", new JSONNumber(4));
// SourceCodeActions (typing)
json.put("autoPairParentheses", JSONBoolean.getInstance(true));
json.put("autoPairBraces", JSONBoolean.getInstance(true));
json.put("autoPairSquareBrackets", JSONBoolean.getInstance(true));
json.put("autoPairAngleBrackets", JSONBoolean.getInstance(true));
json.put("autoPairQuotations", JSONBoolean.getInstance(true));
json.put("autoCompleteComments", JSONBoolean.getInstance(true));
json.put("smartIndentation", JSONBoolean.getInstance(true));
// editor features (rulers)
json.put("annotationRuler", JSONBoolean.getInstance(true));
json.put("lineNumberRuler", JSONBoolean.getInstance(true));
json.put("foldingRuler", JSONBoolean.getInstance(true));
json.put("overviewRuler", JSONBoolean.getInstance(true));
json.put("zoomRuler", JSONBoolean.getInstance(true));
// language tools
json.put("showOccurrences", JSONBoolean.getInstance(true));
json.put("contentAssistAutoTrigger", JSONBoolean.getInstance(true));
return json.getJavaScriptObject();
}
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) {
this.editorOverlay.getTextView().getOptions().setReadOnly(isReadOnly);
this.editorOverlay.getTextView().update();
}
@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.jseditor.client.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(OrionEventContants.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(OrionEventContants.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(OrionEventContants.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(OrionEventContants.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(OrionEventContants.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 = this.keymapPrefReader.readPref(OrionEditorExtension.ORION_EDITOR_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 EditorType getEditorType() {
return EditorType.getInstance(OrionEditorExtension.ORION_EDITOR_KEY);
}
@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;
if (UserAgent.isMac()) {
strokeOverlay = OrionKeyStrokeOverlay.create(keybinding.getKeyCode(),
keybinding.isCmd(),
keybinding.isShift(),
keybinding.isAlt(),
keybinding.isControl(),
"keydown",
keyBindingModuleProvider.get());
} else {
strokeOverlay = OrionKeyStrokeOverlay.create(keybinding.getKeyCode(),
keybinding.isControl(),
keybinding.isShift(),
keybinding.isAlt(),
false,
"keydown",
keyBindingModuleProvider.get());
}
String actionId = "che-action-" + keybinding.getAction().toString();
editorOverlay.getTextView().setKeyBinding(strokeOverlay, actionId);
editorOverlay.getTextView().setAction(actionId, new Action() {
@Override
public void onAction() {
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(OrionEventContants.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 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();
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()));
jsArray.push(problem);
}
editorOverlay.showProblems(jsArray);
}
private String getSeverity(String type) {
switch (type) {
case "org.eclipse.jdt.ui.error":
return "error";
case "org.eclipse.jdt.ui.warning":
return "warning";
default:
return "task";
}
}
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();
}
@Override
public Gutter getGutter() {
return gutter;
}
/**
* 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);
editorViewOverlay.updateSettings(getEditorSettings());
widgetInitializedCallback.initialized(OrionEditorWidget.this);
}
}
}