Why do it?
Snapping is a function whereby a user creates or edits an object, and part of the shape automatically connects with another object in its proximity. As a result, the edited object is instantly positioned correctly in relation to the other object. Snapping is a useful way to combine interactive editing with exact precision.
However, you might have several kinds of objects, and you only want to enable snapping for some objects with some others. For example, when you are defining a flight plan, you only want to snap to waypoints.
How does it work?
Snapping between objects is a negotiation process between the object you’re creating or editing, the flight plan for instance, and the object you’re trying to snap to, a waypoint for instance. The object you’re trying to snap to is called a snappable. The controller holds a reference to a list of these snappables.
When you’re dragging around an object handle, the controller asks the painter of a snappable if it supports snapping and if
it can return a geometry to snap to.
This geometry called a snap target. For a waypoint, this would typically be an ILcdPoint
.
Next, the controller asks the editor of the object you’re editing if it can snap to the offered target. If the editor responds positively, snapping takes place.
What happens next?
The controller seals the deal by visualizing and executing the snap operation:
-
The painter of the object you’re trying to snap to is asked to highlight the snap target. Most painters draw a small rectangle around the object.
-
The editor of the object that’s being edited is asked to perform the snap operation. This is done by calling the
edit()
method. The passedILcdGXYContext
will have a reference to the snap target.
To learn more about editing and snapping in a GXY view, see interacting with the GXY view
Customizing the behavior to restrict snap targets
Typically you want your editor to decide whether or not it accepts a certain snap target. For example, your flight plan editor could require that any offered snap target originates from a waypoint model:
TLcdGXYShapePainter flightPlanPainterEditor = new TLcdGXYShapePainter() {
@Override
public boolean acceptSnapTarget(Graphics aGraphics, ILcdGXYContext aGXYContext) {
// only accept snap targets from waypoint layers
return isWaypointLayer(aGXYContext.getSnapTargetLayer()) && super.acceptSnapTarget(aGraphics, aGXYContext);
}
};
Troubleshooting
Because snapping is a negotiation process, it’s sometimes hard to figure out what’s going wrong.
Here are some tips to help you determine the cause of snapping problems:
-
Check if your controller’s list of snappables actually contains the object you’re trying to snap to.
If you don’t want to do the bookkeeping of this list yourself, you can use |
-
Check that the painter of the snappable supports snapping and returns a snap target.
-
Finally, check if your editor’s
acceptSnapTarget()
method makes the right decision.