Skip to content

Commit

Permalink
Add static method to configure overlay scrolling for FigureCanvas
Browse files Browse the repository at this point in the history
This allows the user to specify whether new instances of FigureCanvas
should use overlay scrolling on not. This is disabled by default, due to
performance issues on Linux/GTK3.

As a result, the scrollbar is shown as a separate entity and no longer
part of the client area. This setting only affects operating systems
supporting overlay scrolling. This method requires SWT 3.126 or newer.

eclipse#430
  • Loading branch information
ptziegler committed Apr 20, 2024
1 parent 7ca38b7 commit 0b69921
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
58 changes: 58 additions & 0 deletions org.eclipse.draw2d/src/org/eclipse/draw2d/FigureCanvas.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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 <a href="https://github.com/eclipse/gef-classic/issues/430">here</a>
*/
private static int SCROLLBARS_MODE = SWT.NONE;

private int vBarVisibility = AUTOMATIC;
private int hBarVisibility = AUTOMATIC;
private Viewport viewport;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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}.<br>
* Calling this method has no effect on already created instances of this
* class.<br>
* 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);
Expand Down

0 comments on commit 0b69921

Please sign in to comment.