diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d2fb68b1..edb7fcc4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# GEF Classic 3.20.0 (Eclipse 2024-06) + +## Draw2d + - Overlay scrolling is disabled by default for FigureCanvas. Clients can + restore the original behavior by calling FigureCanvas.setScrollbarsMode() + prior to creating the object. + # GEF Classic 3.19.0 (Eclipse 2024-03) ## Draw2d diff --git a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java index 6d4e51ca8..72ed38f52 100644 --- a/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java +++ b/org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java @@ -13,6 +13,9 @@ package org.eclipse.draw2d; import java.beans.PropertyChangeListener; +import java.lang.reflect.Method; +import java.util.logging.Level; +import java.util.logging.Logger; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -21,6 +24,7 @@ import org.eclipse.swt.widgets.Canvas; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Scrollable; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; @@ -49,6 +53,7 @@ */ public class FigureCanvas extends Canvas { + private static final Logger LOGGER = Logger.getLogger(FigureCanvas.class.getSimpleName()); private static final int ACCEPTED_STYLES = SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT | SWT.V_SCROLL | SWT.H_SCROLL | SWT.NO_BACKGROUND | SWT.NO_REDRAW_RESIZE | SWT.DOUBLE_BUFFERED | SWT.BORDER; @@ -73,6 +78,16 @@ public class FigureCanvas extends Canvas { /** Always show scrollbar */ public static int ALWAYS = 2; + /** + * Static property specifying whether new instances of this class should be + * created with overlay scrolling enabled. Possible values are {@link SWT#NONE} + * or {@link SWT#SCROLLBAR_OVERLAY}. This value is set to {@link SWT#NONE} by + * default, due to performance issues on Linux/GTK3. + * + * @see here + */ + private static int SCROLLBARS_MODE = SWT.NONE; + private int vBarVisibility = AUTOMATIC; private int hBarVisibility = AUTOMATIC; private Viewport viewport; @@ -155,6 +170,7 @@ public FigureCanvas(Composite parent, LightweightSystem lws) { */ public FigureCanvas(int style, Composite parent, LightweightSystem lws) { super(parent, checkStyle(style)); + adjustScrollbarsMode(); getHorizontalBar().setVisible(false); getVerticalBar().setVisible(false); this.lws = lws; @@ -255,6 +271,25 @@ public Viewport getViewport() { return viewport; } + /** + * Calls {@link Scrollable#setScrollbarsMode(int)} if executed with SWT 3.126. + * + * @since 3.2 + */ + private void adjustScrollbarsMode() { + // TODO Check version of SWT binary after PR has been merged: + // https://github.com/eclipse-platform/eclipse.platform.swt/pull/1188 + if (SWT.getVersion() >= 4965 && getScrollbarsMode() != SCROLLBARS_MODE) { + try { + // Invoke method via reflection to remain compatible with older SWT versions + Method setScrollbarsMode = Scrollable.class.getMethod("setScrollbarsMode", Integer.class); //$NON-NLS-1$ + setScrollbarsMode.invoke(this, SCROLLBARS_MODE); + } catch (ReflectiveOperationException e) { + LOGGER.log(Level.SEVERE, e.getMessage(), e); + } + } + } + /** * Adds listeners for scrolling. */ @@ -552,6 +587,29 @@ public void setViewport(Viewport vp) { hookViewport(); } + /** + * Global property to enable overlay scrolling for all figure canvas when + * {@link SWT#SCROLLBAR_OVERLAY} and to disable overlay scrolling when + * {@link SWT#NONE} is given. The default value is {@link SWT#NONE}.
+ * Calling this method has no effect on already created instances of this + * class.
+ * Calling this method has no effect if overlay scrolling is not supported by + * the operating system. + * + * @param mode One of {@link SWT#NONE}, {@link SWT#SCROLLBAR_OVERLAY}. + * @since 3.16 + * @throws IllegalArgumentException if the given {@code mode} isn't one of + * {@link SWT#NONE} + * {@link SWT#SCROLLBAR_OVERLAY}. + * @see #SCROLLBARS_MODE + */ + public static void setScrollbarsMode(int mode) throws IllegalArgumentException { + if (mode != SWT.NONE && mode != SWT.SCROLLBAR_OVERLAY) { + throw new IllegalArgumentException("Scrollbars mode must be either SWT.SCROLLBAR_OVERLAY or SWT.NONE"); //$NON-NLS-1$ + } + SCROLLBARS_MODE = mode; + } + private static int verifyScrollBarOffset(RangeModel model, int value) { value = Math.max(model.getMinimum(), value); return Math.min(model.getMaximum() - model.getExtent(), value);