Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorangelozerr2017-11-23 11:31:44 -0500
committerMickael Istria2017-11-29 09:10:15 -0500
commit3b60a74ba0cdddbfac2322cd6743d790d16af3f9 (patch)
tree48c615767099f1ed7a0dd92fa4b0cb5159181bcb /org.eclipse.jface.text
parentb7a0de702cc68c0768dca3f44f97a4fce211c693 (diff)
downloadeclipse.platform.text-3b60a74ba0cdddbfac2322cd6743d790d16af3f9.tar.gz
eclipse.platform.text-3b60a74ba0cdddbfac2322cd6743d790d16af3f9.tar.xz
eclipse.platform.text-3b60a74ba0cdddbfac2322cd6743d790d16af3f9.zip
Bug 527675 - [CodeMining] Provide inline annotations supportI20171129-2000
Change-Id: I699f425123580cddfa771f91aa0b6c08c7c245c7 Signed-off-by: angelozerr <angelo.zerr@gmail.com>
Diffstat (limited to 'org.eclipse.jface.text')
-rw-r--r--org.eclipse.jface.text/META-INF/MANIFEST.MF1
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/AbstractInlinedAnnotation.java102
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java169
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java352
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java67
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineHeaderAnnotation.java44
-rw-r--r--org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/Positions.java62
7 files changed, 797 insertions, 0 deletions
diff --git a/org.eclipse.jface.text/META-INF/MANIFEST.MF b/org.eclipse.jface.text/META-INF/MANIFEST.MF
index dff65ab29..ca017ba5b 100644
--- a/org.eclipse.jface.text/META-INF/MANIFEST.MF
+++ b/org.eclipse.jface.text/META-INF/MANIFEST.MF
@@ -25,6 +25,7 @@ Export-Package:
org.eclipse.jface.text.revisions,
org.eclipse.jface.text.rules,
org.eclipse.jface.text.source,
+ org.eclipse.jface.text.source.inlined,
org.eclipse.jface.text.source.projection,
org.eclipse.jface.text.source.projection.images,
org.eclipse.jface.text.templates,
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/AbstractInlinedAnnotation.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/AbstractInlinedAnnotation.java
new file mode 100644
index 000000000..6bf0c5c12
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/AbstractInlinedAnnotation.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+
+/**
+ * Abstract class for inlined annotation.
+ *
+ * @since 3.13.0
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public abstract class AbstractInlinedAnnotation extends Annotation {
+
+ /**
+ * The type of inlined annotations.
+ */
+ public static final String TYPE= "org.eclipse.jface.text.source.inlined"; //$NON-NLS-1$
+
+ /**
+ * The position where the annotation must be drawn.
+ */
+ private final Position position;
+
+ /**
+ * The {@link StyledText} widget where the annotation must be drawn.
+ */
+ private final StyledText textWidget;
+
+ /**
+ * Inlined annotation constructor.
+ *
+ * @param position the position where the annotation must be drawn.
+ * @param textWidget the {@link StyledText} widget where the annotation must be drawn.
+ */
+ protected AbstractInlinedAnnotation(Position position, StyledText textWidget) {
+ super(TYPE, false, ""); //$NON-NLS-1$
+ this.position= position;
+ this.textWidget= textWidget;
+ }
+
+ /**
+ * Returns the position where the annotation must be drawn.
+ *
+ * @return the position where the annotation must be drawn.
+ */
+ public Position getPosition() {
+ return position;
+ }
+
+ /**
+ * Returns the {@link StyledText} widget where the annotation must be drawn.
+ *
+ * @return the {@link StyledText} widget where the annotation must be drawn.
+ */
+ public StyledText getTextWidget() {
+ return textWidget;
+ }
+
+ /**
+ * Redraw the inlined annotation.
+ */
+ public void redraw() {
+ StyledText text= getTextWidget();
+ InlinedAnnotationSupport.runInUIThread(text, (t) -> {
+ Position pos= getPosition();
+ InlinedAnnotationDrawingStrategy.draw(this, null, t, pos.getOffset(), pos.getLength(), null);
+ });
+ }
+
+ /**
+ * Draw the inlined annotation. By default it draw the text of the annotation with gray color.
+ * User can override this method to draw anything.
+ *
+ * @param gc the graphics context
+ * @param textWidget the text widget to draw on
+ * @param offset the offset of the line
+ * @param length the length of the line
+ * @param color the color of the line
+ * @param x the x position of the annotation
+ * @param y the y position of the annotation
+ */
+ public void draw(GC gc, StyledText textWidget, int offset, int length, Color color, int x, int y) {
+ gc.setForeground(color);
+ gc.setBackground(textWidget.getBackground());
+ gc.drawText(getText(), x, y);
+ }
+
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java
new file mode 100644
index 000000000..85d90bb0e
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationDrawingStrategy.java
@@ -0,0 +1,169 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GlyphMetrics;
+import org.eclipse.swt.graphics.Rectangle;
+
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
+
+/**
+ * {@link IDrawingStrategy} implementation to render {@link AbstractInlinedAnnotation}.
+ *
+ * @since 3.13.0
+ */
+class InlinedAnnotationDrawingStrategy implements IDrawingStrategy {
+
+ @Override
+ public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
+ if (!(annotation instanceof AbstractInlinedAnnotation)) {
+ return;
+ }
+ InlinedAnnotationDrawingStrategy.draw((AbstractInlinedAnnotation) annotation, gc, textWidget, offset, length,
+ color);
+ }
+
+ /**
+ * Draw the inlined annotation.
+ *
+ * @param annotation the annotation to be drawn
+ * @param gc the graphics context, <code>null</code> when in clearing mode
+ * @param textWidget the text widget to draw on
+ * @param offset the offset of the line
+ * @param length the length of the line
+ * @param color the color of the line
+ */
+ public static void draw(AbstractInlinedAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
+ Color color) {
+ if (annotation.isMarkedDeleted()) {
+ // When annotation is deleted, redraw the styled text to hide old draw of
+ // annotations
+ textWidget.redraw();
+ // update caret offset since line spacing has changed.
+ textWidget.setCaretOffset(textWidget.getCaretOffset());
+ return;
+ }
+ if (annotation instanceof LineHeaderAnnotation) {
+ draw((LineHeaderAnnotation) annotation, gc, textWidget, offset, length, color);
+ } else {
+ draw((LineContentAnnotation) annotation, gc, textWidget, offset, length, color);
+ }
+ }
+
+ /**
+ * Draw the line header annotation in the line spacing of the previous line.
+ *
+ * @param annotation the annotation to be drawn
+ * @param gc the graphics context, <code>null</code> when in clearing mode
+ * @param textWidget the text widget to draw on
+ * @param offset the offset of the line
+ * @param length the length of the line
+ * @param color the color of the line
+ */
+ private static void draw(LineHeaderAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
+ Color color) {
+ // compute current, previous line index.
+ int lineIndex= -1;
+ try {
+ lineIndex= textWidget.getLineAtOffset(offset);
+ } catch (Exception e) {
+ return;
+ }
+ int previousLineIndex= lineIndex - 1;
+ if (gc != null) {
+ // Compute the location of the annotation
+ int x= textWidget.getLocationAtOffset(offset).x;
+ int y= 0;
+ int height= annotation.getHeight();
+ if (lineIndex > 0) {
+ int previousOffset= textWidget.getOffsetAtLine(previousLineIndex);
+ y= textWidget.getLocationAtOffset(previousOffset).y + height;
+ }
+ Rectangle clipping= gc.getClipping();
+ if (clipping.contains(x, y)) {
+ // GC clipping contains the x, y where annotation must be drawn.
+
+ // Colorize line spacing area with the background of StyledText to avoid having highlighted line color
+ gc.setBackground(textWidget.getBackground());
+ Rectangle client= textWidget.getClientArea();
+ textWidget.drawBackground(gc, x, y, client.width, height);
+
+ // draw the annotation
+ annotation.draw(gc, textWidget, offset, length, color, x, y);
+ return;
+ } else {
+ if (!(clipping.y - height == y)) {
+ // Clipping doesn't include the y of previous line spacing, stop the redraw
+ // range.
+ return;
+ }
+ }
+ }
+
+ if (previousLineIndex < 0) {
+ // There are none previous line, do nothing
+ return;
+ }
+ // refresh the previous line range where line header annotation must be drawn.
+ int previousOffset= textWidget.getOffsetAtLine(previousLineIndex);
+ int lineLength= offset - previousOffset;
+ textWidget.redrawRange(previousOffset, lineLength, true);
+ }
+
+ /**
+ * Draw the line content annotation inside line in the empty area computed by
+ * {@link GlyphMetrics}.
+ *
+ * @param annotation the annotation to be drawn
+ * @param gc the graphics context, <code>null</code> when in clearing mode
+ * @param textWidget the text widget to draw on
+ * @param offset the offset of the line
+ * @param length the length of the line
+ * @param color the color of the line
+ */
+ private static void draw(LineContentAnnotation annotation, GC gc, StyledText textWidget, int offset, int length,
+ Color color) {
+ if (gc != null) {
+ // Compute the location of the annotation
+ FontMetrics fontMetrics= gc.getFontMetrics();
+ Rectangle bounds= textWidget.getTextBounds(offset, offset);
+ int x= bounds.x + fontMetrics.getLeading();
+ int y= bounds.y + fontMetrics.getDescent();
+
+ // Draw the line content annotation
+ annotation.draw(gc, textWidget, offset, length, color, x, y);
+
+ // The inline annotation replaces one character by taking a place width
+ // GlyphMetrics
+ // Here we need to redraw this first character because GlyphMetrics clip this
+ // character.
+ String s= textWidget.getText(offset, offset);
+ StyleRange style= textWidget.getStyleRangeAtOffset(offset);
+ if (style != null) {
+ if (style.background != null) {
+ gc.setBackground(style.background);
+ }
+ if (style.foreground != null) {
+ gc.setForeground(style.foreground);
+ }
+ }
+ gc.drawString(s, bounds.x + bounds.width - gc.stringExtent(s).x, bounds.y, true);
+ } else {
+ textWidget.redrawRange(offset, length, true);
+ }
+ }
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java
new file mode 100644
index 000000000..bf6b9c407
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/InlinedAnnotationSupport.java
@@ -0,0 +1,352 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.custom.StyledTextLineSpacingProvider;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ISynchronizable;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationPainter;
+import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModelExtension;
+import org.eclipse.jface.text.source.IAnnotationModelExtension2;
+import org.eclipse.jface.text.source.ISourceViewer;
+
+/**
+ * Support to draw inlined annotations:
+ *
+ * <ul>
+ * <li>line header annotation with {@link LineHeaderAnnotation}.</li>
+ * <li>line content annotation with {@link LineContentAnnotation}.</li>
+ * </ul>
+ *
+ * @since 3.13.0
+ */
+public class InlinedAnnotationSupport implements StyledTextLineSpacingProvider {
+
+ /**
+ * The annotation inlined strategy singleton.
+ */
+ private static final IDrawingStrategy INLINED_STRATEGY= new InlinedAnnotationDrawingStrategy();
+
+ /**
+ * The annotation inlined strategy ID.
+ */
+ private static final String INLINED_STRATEGY_ID= "inlined"; //$NON-NLS-1$
+
+ /**
+ * The source viewer
+ */
+ private ISourceViewer fViewer;
+
+ /**
+ * The annotation painter to use to draw the inlined annotations.
+ */
+ private AnnotationPainter fPainter;
+
+ /**
+ * Holds the current inlined annotations.
+ */
+ private Set<AbstractInlinedAnnotation> fInlinedAnnotations;
+
+ /**
+ * Install the inlined annotation support for the given viewer.
+ *
+ * @param viewer the source viewer
+ * @param painter the annotation painter to use to draw the inlined annotations.
+ */
+ public void install(ISourceViewer viewer, AnnotationPainter painter) {
+ Assert.isNotNull(viewer);
+ Assert.isNotNull(painter);
+ fViewer= viewer;
+ fPainter= painter;
+ initPainter();
+ StyledText text= fViewer.getTextWidget();
+ if (text == null || text.isDisposed()) {
+ return;
+ }
+ setColor(text.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY));
+ text.setLineSpacingProvider(this);
+ }
+
+ /**
+ * Initialize painter with inlined drawing strategy.
+ */
+ private void initPainter() {
+ fPainter.addDrawingStrategy(INLINED_STRATEGY_ID, INLINED_STRATEGY);
+ fPainter.addAnnotationType(AbstractInlinedAnnotation.TYPE, INLINED_STRATEGY_ID);
+ }
+
+ /**
+ * Set the color to use to draw the inlined annotations.
+ *
+ * @param color the color to use to draw the inlined annotations.
+ */
+ public void setColor(Color color) {
+ fPainter.setAnnotationTypeColor(AbstractInlinedAnnotation.TYPE, color);
+ }
+
+ /**
+ * Unisntall the inlined annotation support
+ */
+ public void uninstall() {
+ fViewer= null;
+ fPainter= null;
+ }
+
+ /**
+ * Update the given inlined annotation.
+ *
+ * @param annotations the inlined annotation.
+ */
+ public void updateAnnotations(Set<AbstractInlinedAnnotation> annotations) {
+ IDocument document= fViewer != null ? fViewer.getDocument() : null;
+ if (document == null) {
+ // this case comes from when editor is closed before rendered is done.
+ return;
+ }
+ IAnnotationModel annotationModel= fViewer.getAnnotationModel();
+ if (annotationModel == null) {
+ return;
+ }
+ StyledText styledText= fViewer.getTextWidget();
+ Map<AbstractInlinedAnnotation, Position> annotationsToAdd= new HashMap<>();
+ List<AbstractInlinedAnnotation> annotationsToRemove= fInlinedAnnotations != null
+ ? new ArrayList<>(fInlinedAnnotations)
+ : Collections.emptyList();
+ // Loop for annotations to update
+ for (AbstractInlinedAnnotation ann : annotations) {
+ if (!annotationsToRemove.remove(ann)) {
+ // The annotation was not created, add it
+ annotationsToAdd.put(ann, ann.getPosition());
+ }
+ if (ann instanceof LineContentAnnotation) {
+ // Create metrics with well width to add space where the inline annotation must
+ // be drawn.
+ runInUIThread(styledText, (text) -> {
+ StyleRange s= new StyleRange();
+ s.start= ann.getPosition().getOffset();
+ s.length= 1;
+ s.metrics= ((LineContentAnnotation) ann).createMetrics();
+ text.setStyleRange(s);
+ });
+ }
+ }
+ // Process annotations to remove
+ for (AbstractInlinedAnnotation ann : annotationsToRemove) {
+ // Mark annotation as deleted to ignore the draw
+ ann.markDeleted(true);
+ if (ann instanceof LineContentAnnotation) {
+ // Set metrics to null to remove space of the inline annotation
+ runInUIThread(styledText, (text) -> {
+ StyleRange s= new StyleRange();
+ s.start= ann.getPosition().getOffset();
+ s.length= 1;
+ s.metrics= null;
+ text.setStyleRange(s);
+ });
+ }
+ }
+ // Update annotation model
+ synchronized (getLockObject(annotationModel)) {
+ if (annotationsToAdd.size() == 0 && annotationsToRemove.size() == 0) {
+ // None change, do nothing. Here the user could change position of codemining
+ // range
+ // (ex: user key press
+ // "Enter"), but we don't need to redraw the viewer because change of position
+ // is done by AnnotationPainter.
+ } else {
+ if (annotationModel instanceof IAnnotationModelExtension) {
+ ((IAnnotationModelExtension) annotationModel).replaceAnnotations(
+ annotationsToRemove.toArray(new Annotation[annotationsToRemove.size()]), annotationsToAdd);
+ } else {
+ removeInlinedAnnotations();
+ Iterator<Entry<AbstractInlinedAnnotation, Position>> iter= annotationsToAdd.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry<AbstractInlinedAnnotation, Position> mapEntry= iter.next();
+ annotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
+ }
+ }
+ }
+ fInlinedAnnotations= annotations;
+ }
+ }
+
+ /**
+ * Returns the existing codemining annotation with the given position information and null
+ * otherwise.
+ *
+ * @param pos the position
+ * @return the existing codemining annotation with the given position information and null
+ * otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends AbstractInlinedAnnotation> T findExistingAnnotation(Position pos) {
+ if (fInlinedAnnotations == null) {
+ return null;
+ }
+ for (AbstractInlinedAnnotation ann : fInlinedAnnotations) {
+ if (ann.getPosition().offset == pos.offset) {
+ try {
+ return (T) ann;
+ } catch (ClassCastException e) {
+ // Do nothing
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the lock object for the given annotation model.
+ *
+ * @param annotationModel the annotation model
+ * @return the annotation model's lock object
+ */
+ private Object getLockObject(IAnnotationModel annotationModel) {
+ if (annotationModel instanceof ISynchronizable) {
+ Object lock= ((ISynchronizable) annotationModel).getLockObject();
+ if (lock != null)
+ return lock;
+ }
+ return annotationModel;
+ }
+
+ /**
+ * Remove the inlined annotations.
+ */
+ private void removeInlinedAnnotations() {
+
+ IAnnotationModel annotationModel= fViewer.getAnnotationModel();
+ if (annotationModel == null || fInlinedAnnotations == null)
+ return;
+
+ synchronized (getLockObject(annotationModel)) {
+ if (annotationModel instanceof IAnnotationModelExtension) {
+ ((IAnnotationModelExtension) annotationModel).replaceAnnotations(
+ fInlinedAnnotations.toArray(new Annotation[fInlinedAnnotations.size()]), null);
+ } else {
+ for (AbstractInlinedAnnotation annotation : fInlinedAnnotations)
+ annotationModel.removeAnnotation(annotation);
+ }
+ fInlinedAnnotations= null;
+ }
+ }
+
+ /**
+ * Returns the line spacing from the given line index with the codemining annotations height and
+ * null otherwise.
+ */
+ @SuppressWarnings("boxing")
+ @Override
+ public Integer getLineSpacing(int lineIndex) {
+ AbstractInlinedAnnotation annotation= getInlinedAnnotationAtLine(fViewer, lineIndex);
+ return (annotation instanceof LineHeaderAnnotation)
+ ? ((LineHeaderAnnotation) annotation).getHeight()
+ : null;
+ }
+
+ /**
+ * Returns the {@link AbstractInlinedAnnotation} from the given line index and null otherwise.
+ *
+ * @param viewer the source viewer
+ * @param lineIndex the line index.
+ * @return the {@link AbstractInlinedAnnotation} from the given line index and null otherwise.
+ */
+ public static AbstractInlinedAnnotation getInlinedAnnotationAtLine(ISourceViewer viewer, int lineIndex) {
+ if (viewer == null) {
+ return null;
+ }
+ IAnnotationModel annotationModel= viewer.getAnnotationModel();
+ if (annotationModel == null) {
+ return null;
+ }
+ IDocument document= viewer.getDocument();
+ int lineNumber= lineIndex + 1;
+ if (lineNumber > document.getNumberOfLines()) {
+ return null;
+ }
+ try {
+ IRegion line= document.getLineInformation(lineNumber);
+ Iterator<Annotation> iter= (annotationModel instanceof IAnnotationModelExtension2)
+ ? ((IAnnotationModelExtension2) annotationModel).getAnnotationIterator(line.getOffset(),
+ line.getLength(), true, true)
+ : annotationModel.getAnnotationIterator();
+ while (iter.hasNext()) {
+ Annotation ann= iter.next();
+ if (ann instanceof AbstractInlinedAnnotation) {
+ Position p= annotationModel.getPosition(ann);
+ if (p != null) {
+ if (p.overlapsWith(line.getOffset(), line.getLength())) {
+ return (AbstractInlinedAnnotation) ann;
+ }
+ }
+ }
+ }
+ } catch (BadLocationException e) {
+ return null;
+ }
+ return null;
+ }
+
+ /**
+ * Execute UI {@link StyledText} function which requires UI Thread.
+ *
+ * @param text the styled text
+ * @param fn the function to execute.
+ */
+ static void runInUIThread(StyledText text, Consumer<StyledText> fn) {
+ if (text == null || text.isDisposed()) {
+ return;
+ }
+ Display display= text.getDisplay();
+ if (display.getThread() == Thread.currentThread()) {
+ try {
+ fn.accept(text);
+ } catch (Exception e) {
+ // Ignore UI error
+ }
+ } else {
+ display.asyncExec(() -> {
+ if (text.isDisposed()) {
+ return;
+ }
+ try {
+ fn.accept(text);
+ } catch (Exception e) {
+ // Ignore UI error
+ }
+ });
+ }
+ }
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java
new file mode 100644
index 000000000..88f33f67e
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineContentAnnotation.java
@@ -0,0 +1,67 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.FontMetrics;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GlyphMetrics;
+
+import org.eclipse.jface.text.Position;
+
+/**
+ * Inlined annotation which is drawn in the line content and which takes some place with a given
+ * width.
+ *
+ * @since 3.13.0
+ */
+public class LineContentAnnotation extends AbstractInlinedAnnotation {
+
+ /**
+ * Line content annotation constructor.
+ *
+ * @param position the position where the annotation must be drawn.
+ * @param textWidget the {@link StyledText} widget where the annotation must be drawn.
+ */
+ public LineContentAnnotation(Position position, StyledText textWidget) {
+ super(position, textWidget);
+ }
+
+ /**
+ * Returns an instance of GlyphMetrics used to takes 'width' place when the annotation is drawn
+ * inside the line.
+ *
+ * @return an instance of GlyphMetrics used to takes 'width' place when the annotation is drawn
+ * inside the line.
+ */
+ public GlyphMetrics createMetrics() {
+ return new GlyphMetrics(0, 0, getWidth());
+ }
+
+ /**
+ * Returns the annotation width. By default it computes the well width for the text annotation.
+ *
+ * @return the annotation width.
+ */
+ public int getWidth() {
+ String text= super.getText();
+ if (text == null) {
+ return 0;
+ }
+ int nbChars= text.length() + 1;
+ StyledText styledText= super.getTextWidget();
+ GC gc= new GC(styledText);
+ FontMetrics fontMetrics= gc.getFontMetrics();
+ int width= nbChars * fontMetrics.getAverageCharWidth();
+ gc.dispose();
+ return width;
+ }
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineHeaderAnnotation.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineHeaderAnnotation.java
new file mode 100644
index 000000000..e9f3dc7f3
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/LineHeaderAnnotation.java
@@ -0,0 +1,44 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import org.eclipse.swt.custom.StyledText;
+
+import org.eclipse.jface.text.Position;
+
+/**
+ * Inlined annotation which is drawn before a line and which takes some place with a given height.
+ *
+ * @since 3.13.0
+ */
+public class LineHeaderAnnotation extends AbstractInlinedAnnotation {
+
+ /**
+ * Line header annotation constructor.
+ *
+ * @param position the position where the annotation must be drawn.
+ * @param textWidget the {@link StyledText} widget where the annotation must be drawn.
+ */
+ public LineHeaderAnnotation(Position position, StyledText textWidget) {
+ super(position, textWidget);
+ }
+
+ /**
+ * Returns the annotation height. By default, returns the {@link StyledText#getLineHeight()}.
+ *
+ * @return the annotation height.
+ */
+ public int getHeight() {
+ StyledText styledText= super.getTextWidget();
+ return styledText.getLineHeight();
+ }
+
+}
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/Positions.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/Positions.java
new file mode 100644
index 000000000..5ae9c9855
--- /dev/null
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/inlined/Positions.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2017 Angelo ZERR.
+ * 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:
+ * Angelo Zerr <angelo.zerr@gmail.com> - [CodeMining] Provide inline annotations support - Bug 527675
+ */
+package org.eclipse.jface.text.source.inlined;
+
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.Position;
+
+/**
+ * Utilities class to retrieve position.
+ *
+ * @since 3.13.0
+ */
+public class Positions {
+
+ /**
+ * Returns the line position by taking care or not of of leading spaces.
+ *
+ * @param lineIndex the line index
+ * @param document the document
+ * @param leadingSpaces true if line spacing must take care of and not otherwise.
+ * @return the line position by taking care of leading spaces.
+ * @throws BadLocationException if the line number is invalid in this document
+ */
+ public static Position of(int lineIndex, IDocument document, boolean leadingSpaces) throws BadLocationException {
+ int offset= document.getLineOffset(lineIndex);
+ int lineLength= document.getLineLength(lineIndex);
+ String line= document.get(offset, lineLength);
+ if (leadingSpaces) {
+ offset+= getLeadingSpaces(line);
+ }
+ return new Position(offset, 1);
+ }
+
+ /**
+ * Returns the leading spaces of the given line text.
+ *
+ * @param line the line text.
+ * @return the leading spaces of the given line text.
+ */
+ private static int getLeadingSpaces(String line) {
+ int counter= 0;
+ char[] chars= line.toCharArray();
+ for (char c : chars) {
+ if (c == '\t')
+ counter++;
+ else if (c == ' ')
+ counter++;
+ else
+ break;
+ }
+ return counter;
+ }
+}

Back to the top