package org.eclipse.gmf.tooling.runtime.linklf; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.PrecisionRectangle; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalEditPart; import org.eclipse.gef.SnapToGrid; /** * Utility class to compute active grid specification for given edit part viewer. * <p/> * Clients may call static methods to compute grid spec once, or may setup listeners * that will automatically update the active spec when it changed */ public class DiagramGridSpec { private final EditPartViewer myViewer; private PrecisionRectangle myRelativeGridSpec; private PrecisionRectangle myAbsoluteGridSpec; private final GridSpecListener myGridListener; public DiagramGridSpec(EditPartViewer viewer) { myViewer = viewer; myGridListener = new GridSpecListener() { @Override public void gridSpecChanged() { myRelativeGridSpec = null; myAbsoluteGridSpec = null; } }; myViewer.addPropertyChangeListener(myGridListener); } public void dispose() { myViewer.removePropertyChangeListener(myGridListener); myRelativeGridSpec = null; myAbsoluteGridSpec = null; } /** * Always returns the same instance to avoid endless creation * @return active grid specification in absolute coordinates or <code>null</code> if not enabled */ public PrecisionRectangle getAbsoluteGridSpec() { PrecisionRectangle result = getRelativeGridSpec(); if (result == null) { return null; } if (myAbsoluteGridSpec == null) { myAbsoluteGridSpec = new PrecisionRectangle(); } myAbsoluteGridSpec.setPreciseBounds(result.preciseX(), result.preciseY(), result.preciseWidth(), result.preciseHeight()); GraphicalEditPart diagramEP = (GraphicalEditPart) myViewer.getContents(); diagramEP.getContentPane().translateToAbsolute(myAbsoluteGridSpec); return myAbsoluteGridSpec; } private PrecisionRectangle getRelativeGridSpec() { if (myRelativeGridSpec == null) { myRelativeGridSpec = getRelativeGridSpec(myViewer); } return myRelativeGridSpec; } public EditPartViewer getViewer() { return myViewer; } /** * Computes actual grid specification (origin + single cell width and height) in the absolute coordinate system. * Note, in contrast to {@link #getRelativeGridSpec(EditPartViewer)} this specification depends on the active zoom or scroll * and can't be cached by clients. * @param viewer * @return absolute grid specification, or <code>null</code> if grid is not enabled */ public static PrecisionRectangle getAbsoluteGridSpec(EditPartViewer viewer) { PrecisionRectangle spec = getRelativeGridSpec(viewer); if (spec != null) { GraphicalEditPart diagramEP = (GraphicalEditPart) viewer.getContents(); diagramEP.getContentPane().translateToAbsolute(spec); } return spec; } /** * Computes actual grid specification (origin + single cell width and height) in the coordinates relative * to the diagram content pane. * <p/> * This specification depends only on the grid-relative properties stored in * the {@link EditPartViewer}, so client may cache it and rely on {@link EditPartViewer#addPropertyChangeListener(PropertyChangeListener)} * @param viewer * @return grid specification in the coordinate system relative to diagram content pane, or <code>null</code> if grid is not enabled */ private static PrecisionRectangle getRelativeGridSpec(EditPartViewer viewer) { Boolean enabled = (Boolean) viewer.getProperty(SnapToGrid.PROPERTY_GRID_ENABLED); if (enabled == null || !enabled) { return null; } double gridX = 0; double gridY = 0; Dimension spacing = (Dimension) viewer.getProperty(SnapToGrid.PROPERTY_GRID_SPACING); if (spacing != null) { gridX = spacing.preciseWidth(); gridY = spacing.preciseHeight(); } if (gridX <= 0) { gridX = SnapToGrid.DEFAULT_GRID_SIZE; } if (gridY <= 0) { gridY = SnapToGrid.DEFAULT_GRID_SIZE; } Point origin = (Point) viewer.getProperty(SnapToGrid.PROPERTY_GRID_ORIGIN); PrecisionRectangle result = new PrecisionRectangle(// origin == null ? 0 : origin.preciseX(), origin == null ? 0 : origin.preciseY(), gridX, gridY); return result; } public static abstract class GridSpecListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent evt) { String propertyName = evt.getPropertyName(); if (SnapToGrid.PROPERTY_GRID_ORIGIN.equals(propertyName) || // SnapToGrid.PROPERTY_GRID_ENABLED.equals(propertyName) || // SnapToGrid.PROPERTY_GRID_SPACING.equals(propertyName)) { gridSpecChanged(); } } public abstract void gridSpecChanged(); }; }