Skip to content

Commit 181f377

Browse files
committed
[GEF] Calculate target handle using findFigureAt()
This replaces the TargetFigureFindVisitor used in the findTargetHandle() method with call to findFigureAt(), which is provided by Draw2D. A custom filter is used to restrict the search to only accept Handles and to only look in the specified layer.
1 parent 7a98f88 commit 181f377

2 files changed

Lines changed: 92 additions & 13 deletions

File tree

org.eclipse.wb.core/src-gef/org/eclipse/wb/internal/gef/graphical/GraphicalViewer.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
import org.eclipse.wb.internal.draw2d.FigureCanvas;
1919
import org.eclipse.wb.internal.draw2d.IRootFigure;
2020
import org.eclipse.wb.internal.draw2d.RootFigure;
21-
import org.eclipse.wb.internal.draw2d.TargetFigureFindVisitor;
2221
import org.eclipse.wb.internal.gef.core.AbstractEditPartViewer;
2322
import org.eclipse.wb.internal.gef.core.EditDomain;
2423
import org.eclipse.wb.internal.gef.core.TargetEditPartFindVisitor;
2524

2625
import org.eclipse.draw2d.IFigure;
26+
import org.eclipse.draw2d.TreeSearch;
2727
import org.eclipse.draw2d.geometry.Point;
2828
import org.eclipse.gef.Handle;
2929
import org.eclipse.swt.SWT;
@@ -221,9 +221,17 @@ public Handle findHandleAt(Point p) {
221221
* given location <code>(x, y)</code>.
222222
*/
223223
private Handle findTargetHandle(String layer, Point p) {
224-
TargetFigureFindVisitor visitor = new TargetFigureFindVisitor(m_canvas, p.x, p.y);
225-
((Layer) m_rootEditPart.getLayer(layer)).accept(visitor, false);
226-
Figure targetFigure = visitor.getTargetFigure();
227-
return targetFigure instanceof Handle ? (Handle) targetFigure : null;
224+
return (Handle) m_canvas.getLightweightSystem().getRootFigure().findFigureAt(p.x, p.y,
225+
new TreeSearch() {
226+
@Override
227+
public boolean accept(IFigure figure) {
228+
return figure instanceof Handle;
229+
}
230+
231+
@Override
232+
public boolean prune(IFigure figure) {
233+
return figure instanceof Layer layerFigure && !layer.equals(layerFigure.getName());
234+
}
235+
});
228236
}
229237
}

org.eclipse.wb.tests/src/org/eclipse/wb/tests/gef/GraphicalRobot.java

Lines changed: 79 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@
2424
import org.eclipse.wb.gef.graphical.tools.ResizeTracker;
2525
import org.eclipse.wb.gef.graphical.tools.SelectionTool;
2626
import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
27+
import org.eclipse.wb.internal.draw2d.FigureCanvas;
28+
import org.eclipse.wb.internal.gef.core.EditDomain;
2729
import org.eclipse.wb.internal.gef.graphical.GraphicalViewer;
2830

2931
import org.eclipse.draw2d.IFigure;
3032
import org.eclipse.draw2d.PositionConstants;
33+
import org.eclipse.draw2d.RangeModel;
34+
import org.eclipse.draw2d.Viewport;
3135
import org.eclipse.draw2d.geometry.Dimension;
3236
import org.eclipse.draw2d.geometry.Point;
3337
import org.eclipse.draw2d.geometry.PointList;
@@ -50,6 +54,7 @@
5054
import org.assertj.core.api.Assertions;
5155
import org.assertj.core.description.Description;
5256

57+
import java.io.Closeable;
5358
import java.util.HashSet;
5459
import java.util.Iterator;
5560
import java.util.List;
@@ -65,6 +70,9 @@ public final class GraphicalRobot {
6570
// viewer
6671
private final GraphicalViewer m_viewer;
6772
private final EventSender m_sender;
73+
private final FigureCanvas m_canvas;
74+
private final RangeModel m_horizontalRange;
75+
private final RangeModel m_verticalRange;
6876
// source
6977
private boolean sourceSideMode = false;
7078
private int sourceWidth;
@@ -91,6 +99,12 @@ public final class GraphicalRobot {
9199
public GraphicalRobot(GraphicalViewer viewer) {
92100
m_viewer = viewer;
93101
m_sender = new EventSender(viewer.getControl());
102+
m_canvas = m_viewer.getControl();
103+
Viewport viewport = m_canvas.getViewport();
104+
m_horizontalRange = viewport.getHorizontalRangeModel();
105+
m_verticalRange = viewport.getVerticalRangeModel();
106+
EditDomain editDomain = m_viewer.getEditDomain();
107+
editDomain.setActiveTool(new AbsoluteSelectionTool());
94108
}
95109

96110
////////////////////////////////////////////////////////////////////////////
@@ -188,7 +202,13 @@ public GraphicalRobot beginMove(Object object) {
188202
// find MoveHandle
189203
mouseX = bounds.x;
190204
mouseY = bounds.y;
191-
while (!(m_viewer.findHandleAt(new Point(mouseX, mouseY)) instanceof MoveHandle)) {
205+
Rectangle rootBounds = m_canvas.getRootFigure().getBounds();
206+
while (rootBounds.contains(mouseX, mouseY)) {
207+
try (AutoScroller scroller = new AutoScroller(mouseX, mouseY)) {
208+
if (m_viewer.findHandleAt(scroller.location) instanceof MoveHandle) {
209+
break;
210+
}
211+
}
192212
mouseX++;
193213
}
194214
mouseInSourceX = mouseX - bounds.x;
@@ -296,18 +316,69 @@ private Point findSideHandle(Predicate<Handle> predicate,
296316
int deltaY) {
297317
x += bounds.x;
298318
y += bounds.y;
299-
while (x < bounds.right() && y < bounds.bottom()) {
300-
Point p = new Point(x, y);
301-
Handle handle = (Handle) m_viewer.findHandleAt(p);
302-
if (predicate.test(handle)) {
303-
return handle.getBounds().getCenter();
319+
Rectangle rootBounds = m_canvas.getRootFigure().getBounds();
320+
while (x < bounds.right() && y < bounds.bottom() && rootBounds.contains(x, y)) {
321+
try (AutoScroller scroller = new AutoScroller(x, y)) {
322+
Handle handle = (Handle) m_viewer.findHandleAt(scroller.location);
323+
if (predicate.test(handle)) {
324+
return handle.getBounds().getCenter();
325+
}
326+
x += deltaX;
327+
y += deltaY;
304328
}
305-
x += deltaX;
306-
y += deltaY;
307329
}
308330
return null;
309331
}
310332

333+
/**
334+
* Subclass of the selection tool that also supports figures outside the visible
335+
* area. If necessary, the absolute coordinates that are passed to this tool are
336+
* converted to relative coordinates and the viewer scrolled by the offset. This
337+
* is necessary to have the {@link GraphicalViewer#findHandleAt(Point)} behave
338+
* correctly.
339+
*/
340+
private class AbsoluteSelectionTool extends SelectionTool {
341+
@Override
342+
protected boolean handleButtonDown(int button) {
343+
Point absoluteLocation = getLocation();
344+
try (AutoScroller scroller = new AutoScroller(absoluteLocation.x, absoluteLocation.y)) {
345+
getCurrentInput().setMouseLocation(scroller.location.x, scroller.location.y);
346+
return super.handleButtonDown(button);
347+
} finally {
348+
getCurrentInput().setMouseLocation(absoluteLocation.x, absoluteLocation.y);
349+
}
350+
}
351+
}
352+
353+
/**
354+
* This class scrolls the viewer so that the absolute coordinates that are
355+
* passed as constructor arguments are within the visible area. This is required
356+
* because GEF does not support selecting edit parts/figures that are currently
357+
* invisible. The relative coordinates can then be accessed via
358+
* {@link #scrolledX} and {@link #scrolledY}.
359+
*/
360+
private class AutoScroller implements Closeable {
361+
private final int offX;
362+
private final int offY;
363+
private final Point location;
364+
365+
public AutoScroller(int x, int y) {
366+
offX = Math.max(x - m_horizontalRange.getExtent() + 8, 0);
367+
offY = Math.max(y - m_verticalRange.getExtent() + 8, 0);
368+
m_horizontalRange.setValue(offX);
369+
m_verticalRange.setValue(offY);
370+
int scrolledX = x - m_horizontalRange.getValue();
371+
int scrolledY = y - m_verticalRange.getValue();
372+
location = new Point(scrolledX, scrolledY);
373+
}
374+
375+
@Override
376+
public void close() {
377+
m_horizontalRange.setValue(0);
378+
m_verticalRange.setValue(0);
379+
}
380+
}
381+
311382
////////////////////////////////////////////////////////////////////////////
312383
//
313384
// Side to set position

0 commit comments

Comments
 (0)