diff options
author | angelozerr | 2018-03-14 23:47:03 +0000 |
---|---|---|
committer | Mickael Istria | 2018-03-19 12:18:37 +0000 |
commit | 13d6b5f4f99bd86e86b52c31f3311f4c10e41efa (patch) | |
tree | b390ec6acddc5d3609810697b0629f36748e6181 /org.eclipse.jface.text/src/org/eclipse/jface/text/source | |
parent | d8d5eb7180eb317897b89b3d200329830ad5256a (diff) | |
download | eclipse.platform.text-13d6b5f4f99bd86e86b52c31f3311f4c10e41efa.tar.gz eclipse.platform.text-13d6b5f4f99bd86e86b52c31f3311f4c10e41efa.tar.xz eclipse.platform.text-13d6b5f4f99bd86e86b52c31f3311f4c10e41efa.zip |
Bug 529617 - [CodeMining] Line number in vertical ruler can be not
synchronized with line header annotation
Change-Id: Idfb97cefe20d3fbdde0f8793f159d6c3cff2937b
Signed-off-by: angelozerr <angelo.zerr@gmail.com>
Also-By: Mickael Istria <mistria@redhat.com>
Diffstat (limited to 'org.eclipse.jface.text/src/org/eclipse/jface/text/source')
3 files changed, 175 insertions, 72 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java index 2b4ca76392b..8f8b58c24d8 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/AnnotationRulerColumn.java @@ -20,6 +20,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Consumer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; @@ -47,13 +48,10 @@ import org.eclipse.swt.widgets.Display; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension5; -import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.JFaceTextUtil; import org.eclipse.jface.text.Position; -import org.eclipse.jface.text.TextEvent; /** @@ -70,24 +68,11 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul /** * Internal listener class. */ - class InternalListener implements IViewportListener, IAnnotationModelListener, ITextListener { - - @Override - public void viewportChanged(int verticalPosition) { - if (verticalPosition != fScrollPos) - redraw(); - } - + class AnnotationsListener implements IAnnotationModelListener { @Override public void modelChanged(IAnnotationModel model) { postRedraw(); } - - @Override - public void textChanged(TextEvent e) { - if (e.getViewerRedrawState()) - postRedraw(); - } } /** @@ -139,7 +124,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul /** The buffer for double buffering */ private Image fBuffer; /** The internal listener */ - private InternalListener fInternalListener= new InternalListener(); + private AnnotationsListener fAnnotationListener= new AnnotationsListener(); /** The width of this vertical ruler */ private int fWidth; /** Switch for enabling/disabling the setModel method. */ @@ -192,6 +177,8 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul */ private MouseListener fMouseListener; + private Consumer<StyledText> lineHeightChangeHandler= (t) -> postRedraw(); + /** * Constructs this column with the given arguments. * @@ -204,7 +191,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul this(width, annotationAccess); fAllowSetModel= false; fModel= model; - fModel.addAnnotationModelListener(fInternalListener); + fModel.addAnnotationModelListener(fAnnotationListener); } /** @@ -230,7 +217,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul fWidth= width; fAllowSetModel= false; fModel= model; - fModel.addAnnotationModelListener(fInternalListener); + fModel.addAnnotationModelListener(fAnnotationListener); } /** @@ -337,8 +324,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul }); if (fCachedTextViewer != null) { - fCachedTextViewer.addViewportListener(fInternalListener); - fCachedTextViewer.addTextListener(fInternalListener); + VisibleLinesTracker.track(fCachedTextViewer, lineHeightChangeHandler); // on word wrap toggle a "resized" ControlEvent is fired: suggest a redraw of the ruler fCachedTextWidget.addControlListener(new ControlAdapter() { @Override @@ -506,12 +492,11 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul private void handleDispose() { if (fCachedTextViewer != null) { - fCachedTextViewer.removeViewportListener(fInternalListener); - fCachedTextViewer.removeTextListener(fInternalListener); + VisibleLinesTracker.untrack(fCachedTextViewer, lineHeightChangeHandler); } if (fModel != null) - fModel.removeAnnotationModelListener(fInternalListener); + fModel.removeAnnotationModelListener(fAnnotationListener); if (fBuffer != null) { fBuffer.dispose(); @@ -521,6 +506,7 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul fConfiguredAnnotationTypes.clear(); fAllowedAnnotationTypes.clear(); fAnnotationAccessExtension= null; + } /** @@ -867,12 +853,12 @@ public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRul if (fAllowSetModel && model != fModel) { if (fModel != null) - fModel.removeAnnotationModelListener(fInternalListener); + fModel.removeAnnotationModelListener(fAnnotationListener); fModel= model; if (fModel != null) - fModel.addAnnotationModelListener(fInternalListener); + fModel.addAnnotationModelListener(fAnnotationListener); postRedraw(); } diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java index 96c48b2dc1a..b1e24aaa5b9 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java @@ -17,6 +17,7 @@ package org.eclipse.jface.text.source; import java.lang.ref.WeakReference; import java.util.Arrays; +import java.util.function.Consumer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyledText; @@ -51,13 +52,10 @@ import org.eclipse.jface.util.Util; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; -import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.ITextViewerExtension; import org.eclipse.jface.text.ITextViewerExtension5; -import org.eclipse.jface.text.IViewportListener; import org.eclipse.jface.text.JFaceTextUtil; -import org.eclipse.jface.text.TextEvent; /** @@ -79,41 +77,6 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { && !"false".equals(System.getProperty("LineNumberRulerColumn.retina.workaround")) //$NON-NLS-1$ //$NON-NLS-2$ && internalSupportsZoomedPaint(); - /** - * Internal listener class. - */ - class InternalListener implements IViewportListener, ITextListener { - - /** - * @since 3.1 - */ - private boolean fCachedRedrawState= true; - - @Override - public void viewportChanged(int verticalPosition) { - if (fCachedRedrawState && verticalPosition != fScrollPos) - redraw(); - } - - @Override - public void textChanged(TextEvent event) { - - fCachedRedrawState= event.getViewerRedrawState(); - if (!fCachedRedrawState) - return; - - if (updateNumberOfDigits()) { - computeIndentations(); - layout(event.getViewerRedrawState()); - return; - } - - boolean viewerCompletelyShown= isViewerCompletelyShown(); - if (viewerCompletelyShown || fSensitiveToTextChanges || event.getDocumentEvent() == null) - postRedraw(); - fSensitiveToTextChanges= viewerCompletelyShown; - } - } /** * Handles all the mouse interaction in this line number ruler column. @@ -398,8 +361,6 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { private int fScrollPos; /** The drawable for double buffering */ private Image fBuffer; - /** The internal listener */ - private InternalListener fInternalListener= new InternalListener(); /** The font of this column */ private Font fFont; /** The indentation cache */ @@ -447,6 +408,12 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { private WeakReference<Font> fLastFont; private Font fLastZoomedFont; + /** + * Redraw the ruler handler called when a line height change. + * + * @since 3.13 + */ + private Consumer<StyledText> lineHeightChangeHandler= (t) -> postRedraw(); /** * Constructs a new vertical ruler column. @@ -620,6 +587,10 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { } }); + // track when StyledText is redrawn to check if some line height changed. In this case, the ruler must be redrawn + // to draw line number with well height. + VisibleLinesTracker.track(fCachedTextViewer, lineHeightChangeHandler); + fCanvas= new Canvas(parentControl, SWT.NO_FOCUS ) { @Override public void addMouseListener(MouseListener listener) { @@ -660,9 +631,7 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { fCanvas.addMouseWheelListener(fMouseHandler); if (fCachedTextViewer != null) { - - fCachedTextViewer.addViewportListener(fInternalListener); - fCachedTextViewer.addTextListener(fInternalListener); + VisibleLinesTracker.track(fCachedTextViewer, lineHeightChangeHandler); if (fFont == null) { if (fCachedTextWidget != null && !fCachedTextWidget.isDisposed()) @@ -684,8 +653,7 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { protected void handleDispose() { if (fCachedTextViewer != null) { - fCachedTextViewer.removeViewportListener(fInternalListener); - fCachedTextViewer.removeTextListener(fInternalListener); + VisibleLinesTracker.untrack(fCachedTextViewer, lineHeightChangeHandler); } if (fBuffer != null) { diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisibleLinesTracker.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisibleLinesTracker.java new file mode 100644 index 00000000000..14d966f8eef --- /dev/null +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/VisibleLinesTracker.java @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2018 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> - Bug 527720 - [CodeMining] Line number in vertical ruler can be not synchronized with line header annotation + */ +package org.eclipse.jface.text.source; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.Consumer; + +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.events.PaintEvent; +import org.eclipse.swt.events.PaintListener; + +import org.eclipse.jface.text.ITextViewer; +import org.eclipse.jface.text.JFaceTextUtil; + +/** + * Class to track line height change of visible lines of a given {@link StyledText}. + * + */ +class VisibleLinesTracker implements PaintListener { + + private static final String DATA_KEY= VisibleLinesTracker.class.getName(); + + /** + * The viewer to track. + */ + private final ITextViewer viewer; + + /** + * The previous bottom line index. + */ + private int oldBottom= -1; + + /** + * The previous bottom line pixel. + */ + private int oldBottomPixel; + + /** + * + * List of handler to call when a visible line height change. + */ + private final Collection<Consumer<StyledText>> handlers; + + /** + * Constructor to track line height change of visible lines of the {@link StyledText} of the + * given viewer. + * + * @param viewer the viewer to track + */ + private VisibleLinesTracker(ITextViewer viewer) { + this.viewer= viewer; + this.handlers= new ArrayList<>(); + } + + @Override + public void paintControl(PaintEvent e) { + StyledText textWidget= viewer.getTextWidget(); + // track if bottom line index or bottom line pixel changed. + if (oldBottom == -1) { + oldBottom= JFaceTextUtil.getPartialBottomIndex(viewer); + oldBottomPixel= JFaceTextUtil.getLinePixel(textWidget, oldBottom); + return; + } + int newBottom= JFaceTextUtil.getPartialBottomIndex(viewer); + if (newBottom != oldBottom) { + oldBottom= newBottom; + oldBottomPixel= JFaceTextUtil.getLinePixel(textWidget, oldBottom); + handlers.forEach(handler -> handler.accept(textWidget)); + return; + } + int newBottomPixel= JFaceTextUtil.getLinePixel(textWidget, newBottom); + if (newBottomPixel != oldBottomPixel) { + oldBottomPixel= newBottomPixel; + handlers.forEach(handler -> handler.accept(textWidget)); + return; + } + } + + /** + * Track the line height change of the {@link StyledText} of the given handler an call the given + * handler. + * + * @param viewer the viewer to track + * @param handler the handler to call when line height change. + */ + static void track(ITextViewer viewer, Consumer<StyledText> handler) { + StyledText textWidget= viewer != null ? viewer.getTextWidget() : null; + if (textWidget == null) { + return; + } + VisibleLinesTracker tracker= (VisibleLinesTracker) textWidget.getData(DATA_KEY); + if (tracker == null) { + tracker= new VisibleLinesTracker(viewer); + textWidget.setData(DATA_KEY, tracker); + } + tracker.addHandler(handler); + } + + /** + * Untrack the line height change of the {@link StyledText} of the given handler an call the + * given handler. + * + * @param viewer the viewer to track + * @param handler the handler to call when line height change. + */ + static void untrack(ITextViewer viewer, Consumer<StyledText> handler) { + StyledText textWidget= viewer != null ? viewer.getTextWidget() : null; + if (textWidget == null) { + return; + } + VisibleLinesTracker tracker= (VisibleLinesTracker) textWidget.getData(DATA_KEY); + if (tracker != null) { + tracker.removeHandler(handler); + } + } + + /** + * Add the given handler. + * + * @param handler the handler to call when a visible line height change. + */ + private void addHandler(Consumer<StyledText> handler) { + if (handlers.isEmpty()) { + viewer.getTextWidget().addPaintListener(this); + } + handlers.add(handler); + } + + /** + * Remove the given handler. + * + * @param handler the handler to call when a visible line height change. + */ + private void removeHandler(Consumer<StyledText> handler) { + handlers.remove(handler); + if (handlers.isEmpty()) { + viewer.getTextWidget().removePaintListener(this); + } + } +} |