/******************************************************************************* * 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 elemental.dom.Element; import org.eclipse.che.ide.editor.orion.client.jso.ModelChangedEventOverlay; 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.OrionEditorOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionExtRulerOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionStyleOverlay; import org.eclipse.che.ide.editor.orion.client.jso.OrionTextModelOverlay; import org.eclipse.che.ide.jseditor.client.gutter.Gutter; import org.eclipse.che.ide.jseditor.client.gutter.Gutters; import org.eclipse.che.ide.util.dom.Elements; /** * Orion implementation of the ruler for adding breakpoints marks. * * @author Anatoliy Bazko */ public class OrionBreakpointRuler implements Gutter { private static final String CHE_BREAKPOINT = "che.breakpoint"; private final OrionExtRulerOverlay orionExtRulerOverlay; private final OrionEditorOverlay editorOverlay; private final OrionAnnotationModelOverlay annotationModel; private OrionTextModelOverlay.EventHandler<ModelChangedEventOverlay> modelChangingEventHandler; public OrionBreakpointRuler(OrionExtRulerOverlay rulerOverlay, OrionEditorOverlay editorOverlay) { this.orionExtRulerOverlay = rulerOverlay; this.editorOverlay = editorOverlay; this.orionExtRulerOverlay.addAnnotationType(CHE_BREAKPOINT, 1); this.annotationModel = orionExtRulerOverlay.getAnnotationModel(); } /** {@inheritDoc} */ @Override public void addGutterItem(int line, String gutterId, Element element) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return; } OrionAnnotationOverlay annotation = toAnnotation(element, line); annotationModel.addAnnotation(annotation); } /** {@inheritDoc} */ @Override public void addGutterItem(int line, String gutterId, Element element, final LineNumberingChangeCallback lineCallback) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return; } addGutterItem(line, gutterId, element); if (modelChangingEventHandler == null) { modelChangingEventHandler = new OrionTextModelOverlay.EventHandler<ModelChangedEventOverlay>() { @Override public void onEvent(ModelChangedEventOverlay parameter) { int linesAdded = parameter.addedLineCount(); int linesRemoved = parameter.removedLineCount(); int fromLine = editorOverlay.getModel().getLineAtOffset(parameter.start()); String line = editorOverlay.getModel().getLine(fromLine); if (linesAdded > 0 || linesRemoved > 0 || line.trim().isEmpty()) { removeAnnotations(getAnnotationsFrom(fromLine)); lineCallback.onLineNumberingChange(fromLine, linesRemoved, linesAdded); } } }; this.editorOverlay.getModel().addEventListener("Changed", modelChangingEventHandler, false); } } /** {@inheritDoc} */ @Override public void removeGutterItem(int line, String gutterId) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return; } OrionAnnotationOverlay[] annotations = getAnnotations(line); removeAnnotations(annotations); } /** {@inheritDoc} */ @Override public Element getGutterItem(int line, String gutterId) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return null; } OrionAnnotationOverlay[] annotations = getAnnotations(line); for (OrionAnnotationOverlay annotation : annotations) { if (isBreakpointAnnotation(annotation)) { return Elements.createDivElement(annotation.getStyle().getStyleClass()); } } return null; } /** {@inheritDoc} */ @Override public void clearGutter(String gutterId) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return; } OrionAnnotationOverlay[] annotations = getAllAnnotations(); removeAnnotations(annotations); } /** {@inheritDoc} */ @Override public void setGutterItem(int line, String gutterId, Element element) { if (!Gutters.BREAKPOINTS_GUTTER.equals(gutterId)) { return; } OrionAnnotationOverlay[] oldAnnotations = getAnnotations(line); removeAnnotations(oldAnnotations); addGutterItem(line, gutterId, element); } private void removeAnnotations(OrionAnnotationOverlay[] annotations) { for (OrionAnnotationOverlay annotation : annotations) { if (isBreakpointAnnotation(annotation)) { annotationModel.removeAnnotation(annotation); } } } private OrionAnnotationOverlay toAnnotation(Element element, int line) { int lineStart = editorOverlay.getModel().getLineStart(line); int lineEnd = editorOverlay.getModel().getLineEnd(line); OrionAnnotationOverlay annotation = OrionAnnotationOverlay.create(); OrionStyleOverlay styleOverlay = OrionStyleOverlay.create(); styleOverlay.setStyleClass(element.getClassName()); annotation.setStyle(styleOverlay); annotation.setType(CHE_BREAKPOINT); annotation.setStart(lineStart); annotation.setEnd(lineEnd); return annotation; } private OrionAnnotationOverlay[] getAnnotations(int line) { int lineStart = editorOverlay.getModel().getLineStart(line); int lineEnd = editorOverlay.getModel().getLineEnd(line); return doGetAnnotations(lineStart, lineEnd); } private OrionAnnotationOverlay[] getAnnotationsFrom(int fromLine) { int lineStart = editorOverlay.getModel().getLineStart(fromLine); return doGetAnnotations(lineStart, Integer.MAX_VALUE); } private OrionAnnotationOverlay[] getAllAnnotations() { return doGetAnnotations(0, Integer.MAX_VALUE); } private OrionAnnotationOverlay[] doGetAnnotations(int lineStart, int lineEnd) { return orionExtRulerOverlay.getAnnotationsByType(annotationModel, lineStart, lineEnd); } private boolean isBreakpointAnnotation(OrionAnnotationOverlay annotation) { return CHE_BREAKPOINT.equals(annotation.getType()); } }