Skip to content

Commit

Permalink
Use SourceFigure for ScrollableThumbnail handling
Browse files Browse the repository at this point in the history
The SourceFigure in the ScrollableThumbnail may be different then the
viewport's content used. In that cases the size and position of the
Selector was not handled correctly.

If the SourceFigure is the content of the viewport then it behaves as
before.
  • Loading branch information
azoitl committed Aug 1, 2023
1 parent 10deeed commit 11205ed
Showing 1 changed file with 51 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.draw2d.parts;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import org.eclipse.swt.SWT;
Expand All @@ -35,28 +34,29 @@
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;

/**
* A scaled image representation of a Figure. If the source Figure is not
* completely visible, a SelectorFigure is placed over the thumbnail
* representing the viewable area and can be dragged around to scroll the source
* figure.
*/
/** A scaled image representation of a Figure. If the source Figure is not completely visible, a SelectorFigure is
* placed over the thumbnail representing the viewable area and can be dragged around to scroll the source figure. */
public class ScrollableThumbnail extends Thumbnail {

private class ClickScrollerAndDragTransferrer extends MouseMotionListener.Stub implements MouseListener {
private boolean dragTransfer;

@Override
public void mouseDoubleClicked(MouseEvent me) {
}

@Override
public void mouseDragged(MouseEvent me) {
if (dragTransfer)
if (dragTransfer) {
syncher.mouseDragged(me);
}
}

@Override
public void mousePressed(MouseEvent me) {
if (!(ScrollableThumbnail.this.getClientArea().contains(me.getLocation())))
if (!(ScrollableThumbnail.this.getClientArea().contains(me.getLocation()))) {
return;
}
Dimension selectorCenter = selector.getBounds().getSize().scale(0.5f);
Point scrollPoint = me.getLocation().getTranslated(getLocation().getNegated())
.translate(selectorCenter.negate()).scale(1.0f / getViewportScaleX(), 1.0f / getViewportScaleY())
Expand All @@ -67,6 +67,7 @@ public void mousePressed(MouseEvent me) {
dragTransfer = true;
}

@Override
public void mouseReleased(MouseEvent me) {
syncher.mouseReleased(me);
dragTransfer = false;
Expand All @@ -77,9 +78,11 @@ private class ScrollSynchronizer extends MouseMotionListener.Stub implements Mou
private Point startLocation;
private Point viewLocation;

@Override
public void mouseDoubleClicked(MouseEvent me) {
}

@Override
public void mouseDragged(MouseEvent me) {
if (startLocation != null) {
Dimension d = me.getLocation().getDifference(startLocation);
Expand All @@ -89,21 +92,23 @@ public void mouseDragged(MouseEvent me) {
}
}

@Override
public void mousePressed(MouseEvent me) {
startLocation = me.getLocation();
viewLocation = viewport.getViewLocation();
me.consume();
}

@Override
public void mouseReleased(MouseEvent me) {
}
}

private class SelectorFigure extends Figure {

private Rectangle iBounds;
private final Rectangle iBounds;

private ImageData iData;
private final ImageData iData;

public SelectorFigure() {
PaletteData pData = new PaletteData(0xFF, 0xFF00, 0xFF0000);
Expand All @@ -115,19 +120,22 @@ public SelectorFigure() {
iBounds = new Rectangle(0, 0, 1, 1);
}

@Override
public void paintFigure(Graphics g) {
Rectangle bounds = getBounds().getCopy();

// Avoid drawing images that are 0 in dimension
if (bounds.width < 5 || bounds.height < 5)
if (bounds.width < 5 || bounds.height < 5) {
return;
}

// Don't paint the selector figure if the entire source is visible.
Dimension thumbnailSize = new Dimension(getThumbnailImage());
// expand to compensate for rounding errors in calculating bounds
Dimension size = getSize().getExpanded(1, 1);
if (size.contains(thumbnailSize))
if (size.contains(thumbnailSize)) {
return;
}

bounds.height--;
bounds.width--;
Expand All @@ -141,71 +149,59 @@ public void paintFigure(Graphics g) {
}
}

private FigureListener figureListener = new FigureListener() {
public void figureMoved(IFigure source) {
reconfigureSelectorBounds();
}
};
private KeyListener keyListener = new KeyListener.Stub() {
private final FigureListener figureListener = source -> reconfigureSelectorBounds();
private final KeyListener keyListener = new KeyListener.Stub() {
@Override
public void keyPressed(KeyEvent ke) {
int moveX = viewport.getClientArea().width / 4;
int moveY = viewport.getClientArea().height / 4;
if (ke.keycode == SWT.HOME || (isMirrored() ? ke.keycode == SWT.ARROW_RIGHT : ke.keycode == SWT.ARROW_LEFT))
if (ke.keycode == SWT.HOME
|| (isMirrored() ? ke.keycode == SWT.ARROW_RIGHT : ke.keycode == SWT.ARROW_LEFT)) {
viewport.setViewLocation(viewport.getViewLocation().translate(-moveX, 0));
else if (ke.keycode == SWT.END
|| (isMirrored() ? ke.keycode == SWT.ARROW_LEFT : ke.keycode == SWT.ARROW_RIGHT))
} else if (ke.keycode == SWT.END
|| (isMirrored() ? ke.keycode == SWT.ARROW_LEFT : ke.keycode == SWT.ARROW_RIGHT)) {
viewport.setViewLocation(viewport.getViewLocation().translate(moveX, 0));
else if (ke.keycode == SWT.ARROW_UP || ke.keycode == SWT.PAGE_UP)
} else if (ke.keycode == SWT.ARROW_UP || ke.keycode == SWT.PAGE_UP) {
viewport.setViewLocation(viewport.getViewLocation().translate(0, -moveY));
else if (ke.keycode == SWT.ARROW_DOWN || ke.keycode == SWT.PAGE_DOWN)
} else if (ke.keycode == SWT.ARROW_DOWN || ke.keycode == SWT.PAGE_DOWN) {
viewport.setViewLocation(viewport.getViewLocation().translate(0, moveY));
}
}
};

private PropertyChangeListener propListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
reconfigureSelectorBounds();
}
};
private final PropertyChangeListener propListener = evt -> reconfigureSelectorBounds();

private ScrollSynchronizer syncher;
private IFigure selector;
private Viewport viewport;

/**
* Creates a new ScrollableThumbnail.
*/
/** Creates a new ScrollableThumbnail. */
public ScrollableThumbnail() {
super();
initialize();
}

/**
* Creates a new ScrollableThumbnail that synchs with the given Viewport.
*
* @param port The Viewport
*/
/** Creates a new ScrollableThumbnail that synchs with the given Viewport.
*
* @param port The Viewport */
public ScrollableThumbnail(Viewport port) {
super();
setViewport(port);
initialize();
}

/**
* @see Thumbnail#deactivate()
*/
/** @see Thumbnail#deactivate() */
@Override
public void deactivate() {
unhookViewport();
unhookSelector();
super.deactivate();
}

private double getViewportScaleX() {
return (double) targetSize.width / viewport.getContents().getBounds().width;
return (double) targetSize.width / getSourceRectangle().width();
}

private double getViewportScaleY() {
return (double) targetSize.height / viewport.getContents().getBounds().height;
return (double) targetSize.height / getSourceRectangle().height;
}

private void hookSelector() {
Expand All @@ -232,35 +228,33 @@ private void initialize() {
private void reconfigureSelectorBounds() {
Rectangle rect = new Rectangle();
Point offset = viewport.getViewLocation();
offset.x -= viewport.getHorizontalRangeModel().getMinimum();
offset.y -= viewport.getVerticalRangeModel().getMinimum();
offset.x -= getSourceRectangle().x;
offset.y -= getSourceRectangle().y;
rect.setLocation(offset);
rect.setSize(viewport.getClientArea().getSize());
rect.scale(getViewportScaleX(), getViewportScaleY());
rect.translate(getClientArea().getLocation());
selector.setBounds(rect);
}

/**
* Reconfigures the SelectorFigure's bounds if the scales have changed.
*
/** Reconfigures the SelectorFigure's bounds if the scales have changed.
*
* @param scaleX The X scale
* @param scaleY The Y scale
* @see org.eclipse.draw2d.parts.Thumbnail#setScales(float, float)
*/
* @see org.eclipse.draw2d.parts.Thumbnail#setScales(float, float) */
@Override
protected void setScales(float scaleX, float scaleY) {
if (scaleX == getScaleX() && scaleY == getScaleY())
if (scaleX == getScaleX() && scaleY == getScaleY()) {
return;
}

super.setScales(scaleX, scaleY);
reconfigureSelectorBounds();
}

/**
* Sets the Viewport that this ScrollableThumbnail will synch with.
*
* @param port The Viewport
*/
/** Sets the Viewport that this ScrollableThumbnail will synch with.
*
* @param port The Viewport */
public void setViewport(Viewport port) {
viewport = port;
hookViewport();
Expand Down

0 comments on commit 11205ed

Please sign in to comment.