diff options
6 files changed, 182 insertions, 3 deletions
diff --git a/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/CodeMiningDemo.java b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/CodeMiningDemo.java index a1bc647d336..ef748918de0 100644 --- a/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/CodeMiningDemo.java +++ b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/CodeMiningDemo.java @@ -49,14 +49,21 @@ public class CodeMiningDemo { ISourceViewer sourceViewer = new SourceViewer(shell, null, SWT.V_SCROLL | SWT.BORDER); sourceViewer.setDocument( new Document("// Type class & new keyword and see references CodeMining\n" - + "// Name class with a number N to emulate Nms before resolving the references CodeMining \n\n" + + "// Name class with a number N to emulate Nms before resolving the references CodeMining\n" + + "// Empty lines show a header annotating they're empty.\n" + + "// The word `echo` is echoed.\n" + + "// Lines containing `end` get an annotation at their end\n\n" + "class A\n" + "new A\n" + "new A\n\n" + "class 5\n" + "new 5\n" + "new 5\n" + "new 5"), new AnnotationModel()); // Add AnnotationPainter (required by CodeMining) addAnnotationPainter(sourceViewer); // Initialize codemining providers ((ISourceViewerExtension5) sourceViewer).setCodeMiningProviders(new ICodeMiningProvider[] { - new ClassReferenceCodeMiningProvider(), new ClassImplementationsCodeMiningProvider(), new ToEchoWithHeaderAndInlineCodeMiningProvider("class") }); + new ClassReferenceCodeMiningProvider(), // + new ClassImplementationsCodeMiningProvider(), // + new ToEchoWithHeaderAndInlineCodeMiningProvider("echo"), // + new EmptyLineCodeMiningProvider(), // + new EchoAtEndOfLineCodeMiningProvider()}); // Execute codemining in a reconciler MonoReconciler reconciler = new MonoReconciler(new IReconcilingStrategy() { diff --git a/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EchoAtEndOfLineCodeMiningProvider.java b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EchoAtEndOfLineCodeMiningProvider.java new file mode 100644 index 00000000000..732881befcf --- /dev/null +++ b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EchoAtEndOfLineCodeMiningProvider.java @@ -0,0 +1,64 @@ +/******************************************************************************* + * Copyright (c) 2022, Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.jface.text.examples.codemining; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; +import org.eclipse.jface.text.codemining.ICodeMining; +import org.eclipse.jface.text.codemining.LineEndCodeMining; +import org.eclipse.swt.events.MouseEvent; + +public class EchoAtEndOfLineCodeMiningProvider extends AbstractCodeMiningProvider { + + @Override + public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, + IProgressMonitor monitor) { + IDocument document = viewer.getDocument(); + List<ICodeMining> res = new ArrayList<>(); + for (int i = 0; i < document.getNumberOfLines(); i++) { + try { + if (document.get(document.getLineOffset(i), document.getLineLength(i)).contains("end")) { + res.add(new LineEndCodeMining(document, i, this) { + @Override + public String getLabel() { + return "End of line"; + } + @Override + public boolean isResolved() { + return true; + } + @Override + public Consumer<MouseEvent> getAction() { + return e -> System.err.println(getLabel() + getPosition()); + } + }); + } + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + } + return CompletableFuture.completedFuture(res); + } + + @Override + public void dispose() { + + } + +} diff --git a/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EmptyLineCodeMiningProvider.java b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EmptyLineCodeMiningProvider.java new file mode 100644 index 00000000000..0645d44e82b --- /dev/null +++ b/org.eclipse.jface.text.examples/src/org/eclipse/jface/text/examples/codemining/EmptyLineCodeMiningProvider.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2022, Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.jface.text.examples.codemining; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; +import org.eclipse.jface.text.codemining.ICodeMining; +import org.eclipse.jface.text.codemining.LineHeaderCodeMining; + +public class EmptyLineCodeMiningProvider extends AbstractCodeMiningProvider { + + @Override + public CompletableFuture<List<? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, + IProgressMonitor monitor) { + IDocument document = viewer.getDocument(); + List<LineHeaderCodeMining> emptyLineHeaders = new ArrayList<>(); + for (int line = 0; line < document.getNumberOfLines(); line++) { + try { + if (document.getLineLength(line) == 1) { + emptyLineHeaders.add(new LineHeaderCodeMining(line, document, this) { + @Override + public String getLabel() { + return "Next line is empty"; + } + }); + } + } catch (BadLocationException ex) { + ex.printStackTrace(); + } + } + return CompletableFuture.completedFuture(emptyLineHeaders); + } + +} diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/LineEndCodeMining.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/LineEndCodeMining.java new file mode 100644 index 00000000000..23861735fed --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/codemining/LineEndCodeMining.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2022, Red Hat Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.jface.text.codemining; + +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.Position; + +/** + * A code mining that is positioned on end of a line. + * + * @since 3.20 + */ +public abstract class LineEndCodeMining extends LineContentCodeMining { + + protected LineEndCodeMining(IDocument document, int line, ICodeMiningProvider provider) throws BadLocationException { + super(getLineEndPosition(document, line), provider); + } + + private static Position getLineEndPosition(IDocument document, int line) throws BadLocationException { + int lastCharOffset= document.getLineOffset(line) + document.getLineLength(line); + if (lastCharOffset < document.getLength()) { + lastCharOffset--; // place on the newline \n char, not on 1st char of next line + } + return new Position(lastCharOffset); + } + +} 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 index e86801b1a35..409b1e80bd8 100644 --- 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 @@ -126,13 +126,31 @@ class InlinedAnnotationDrawingStrategy implements IDrawingStrategy { */ private static void draw(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) { - if (annotation.drawRightToPreviousChar(widgetOffset)) { + if (annotation.isEndOfLine(widgetOffset)) { + drawAfterLine(annotation, gc, textWidget, widgetOffset, length, color); + } else if (annotation.drawRightToPreviousChar(widgetOffset)) { drawAsRightOfPreviousCharacter(annotation, gc, textWidget, widgetOffset, length, color); } else { drawAsLeftOf1stCharacter(annotation, gc, textWidget, widgetOffset, length, color); } } + private static void drawAfterLine(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) { + if (gc == null) { + return; + } + if (textWidget.getCharCount() == 0) { + annotation.draw(gc, textWidget, widgetOffset, length, color, 0, 0); + } else { + int line= textWidget.getLineAtOffset(widgetOffset); + int lineEndOffset= widgetOffset < textWidget.getCharCount() ? widgetOffset : textWidget.getCharCount() - 1; + Rectangle bounds= textWidget.getTextBounds(lineEndOffset, lineEndOffset); + int lineEndX= bounds.x + bounds.width + gc.stringExtent(" ").x; //$NON-NLS-1$ + annotation.setLocation(lineEndX, textWidget.getLinePixel(line) + textWidget.getLineVerticalIndent(line)); + annotation.draw(gc, textWidget, widgetOffset, length, color, lineEndX, textWidget.getLinePixel(line) + textWidget.getLineVerticalIndent(line)); + } + } + protected static void drawAsLeftOf1stCharacter(LineContentAnnotation annotation, GC gc, StyledText textWidget, int widgetOffset, int length, Color color) { StyleRange style= null; try { 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 index 0e5df9419c6..62a17529b33 100644 --- 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 @@ -158,4 +158,9 @@ public class LineContentAnnotation extends AbstractInlinedAnnotation { getTextWidget().getLineAtOffset(widgetOffset) == getTextWidget().getLineAtOffset(widgetOffset - 1); } + boolean isEndOfLine(int widgetOffset) { + return getTextWidget().getCharCount() == 0 || getTextWidget().getCharCount() <= widgetOffset || + "\n".equals(getTextWidget().getText(widgetOffset, widgetOffset)); //$NON-NLS-1$ + } + } |