/******************************************************************************* * 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.api.editor.annotation; import java.util.IdentityHashMap; import java.util.Map; import org.eclipse.che.ide.api.editor.text.Position; import org.eclipse.che.ide.api.editor.text.annotation.Annotation; import org.eclipse.che.ide.api.editor.document.Document; import org.eclipse.che.ide.api.editor.text.TextPosition; import org.eclipse.che.ide.api.editor.text.TextRange; import org.eclipse.che.ide.api.editor.texteditor.HasTextMarkers; import org.eclipse.che.ide.api.editor.texteditor.HasTextMarkers.MarkerRegistration; import org.eclipse.che.ide.util.loging.Log; /** * Render the inline marks on the text. */ public class InlineAnnotationRenderer implements AnnotationModelHandler, ClearAnnotationModelHandler { /** The currently show markers. */ private final IdentityHashMap<Annotation, MarkerRegistration> markers = new IdentityHashMap<>(); /** The component that handles markers. */ private HasTextMarkers hasTextMarkers; /** The document. */ private Document document; /** * Sets the component that handles markers. * * @param hasTextMarkers the new component */ public void setHasTextMarkers(final HasTextMarkers hasTextMarkers) { this.hasTextMarkers = hasTextMarkers; } @Override public void onAnnotationModel(final AnnotationModelEvent event) { // remove removed and changed annotations for (final Annotation annotation : event.getRemovedAnnotations()) { removeAnnotationItem(annotation); } for (final Annotation annotation : event.getChangedAnnotations()) { removeAnnotationItem(annotation); } // add new and changed (new version) annotation final Map<String, String> decorations = event.getAnnotationModel().getAnnotationDecorations(); for (final Annotation annotation : event.getAddedAnnotations()) { addAnnotationItem(event.getAnnotationModel(), annotation, decorations); } for (final Annotation annotation : event.getChangedAnnotations()) { addAnnotationItem(event.getAnnotationModel(), annotation, decorations); } } /** * Add an inline annotation. * * @param annotationModel the annotation model * @param annotation the annotation to add * @param decorations the available decorations */ private void addAnnotationItem(AnnotationModel annotationModel, Annotation annotation, Map<String, String> decorations) { if (this.hasTextMarkers != null) { final String className = decorations.get(annotation.getType()); if (className == null) { return; } final Position position = annotationModel.getPosition(annotation); if (position == null) { Log.warn(InlineAnnotationRenderer.class, "Can't add annotation with no position"); return; } final TextPosition from = this.document.getPositionFromIndex(position.getOffset()); final TextPosition to = this.document.getPositionFromIndex(position.getOffset() + position.getLength()); final MarkerRegistration registration = this.hasTextMarkers.addMarker(new TextRange(from, to), className); if (registration != null) { this.markers.put(annotation, registration); } } } /** * Remove an annotation. * * @param annotation the annotation to remove */ private void removeAnnotationItem(final Annotation annotation) { final MarkerRegistration marker = this.markers.get(annotation); if (marker != null) { marker.clearMark(); } else { Log.warn(InlineAnnotationRenderer.class, "Inline marker with no handle: " + annotation); } } /** * Sets the document. * @param document the new value */ public void setDocument(final Document document) { this.document = document; } @Override public void onClearModel(final ClearAnnotationModelEvent event) { for (final MarkerRegistration registration: this.markers.values()) { registration.clearMark(); } } }