blob: c6d91b8e461eb2074ffe7dc39eb19209c8b64cd2 [file] [log] [blame]
/*****************************************************************************
* Copyright (c) 2014-15 CEA LIST, Montages AG and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Golubev (Montages) - Initial API and implementation
*
*****************************************************************************/
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
*
* @since 3.3
*/
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();
};
}