/******************************************************************************* * Copyright (c) 2000, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. 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: * IBM Corporation - initial API and implementation * Gerhardt Informatics Kft. - GEFGWT port *******************************************************************************/ package org.eclipse.gef.editparts; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.eclipse.draw2d.ConnectionLayer; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Layer; import org.eclipse.draw2d.LayeredPane; import org.eclipse.draw2d.ScalableLayeredPane; import org.eclipse.draw2d.StackLayout; import org.eclipse.draw2d.Viewport; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Point; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.gef.AutoexposeHelper; import org.eclipse.gef.DragTracker; import org.eclipse.gef.LayerConstants; import org.eclipse.gef.Request; import org.eclipse.gef.SnapToGrid; import org.eclipse.gef.tools.MarqueeDragTracker; /** * A graphical root composed of regular {@link org.eclipse.draw2d.Layer Layers}. * The layers are added to {@link org.eclipse.draw2d.LayeredPane} or * {@link org.eclipse.draw2d.ScalableLayeredPane}. All layers are positioned by * {@link org.eclipse.draw2d.StackLayout}s, which means that the diagrams * preferred size is the union of the preferred size of each layer, and all * layers will be positioned to fill the entire diagram. * <P> * <EM>IMPORTANT</EM>ScalableRootEditPart uses a <code>Viewport</code> as its * primary figure. It must be used with a * {@link org.eclipse.gef.ui.parts.ScrollingGraphicalViewer}. The viewport gets * installed into that viewer's {@link org.eclipse.draw2d.FigureCanvas}, which * provides native scrollbars for scrolling the viewport. * <P> * The layer structure (top-to-bottom) for this root is: * <table cellspacing="0" cellpadding="0"> * <tr> * <td colspan="4">Root Layered Pane</td> * </tr> * <tr> * <td>├</td> * <td colspan="3"> Guide Layer</td> * </tr> * <tr> * <td>├</td> * <td colspan="3"> Feedback Layer</td> * </tr> * <tr> * <td>├</td> * <td colspan="3"> Handle Layer</td> * </tr> * <tr> * <td>└</td> * <td colspan="2"> <b>Scalable Layers</b></td> * <td>({@link ScalableLayeredPane})</td> * </tr> * <tr> * <td> </td> * <td>├</td> * <td colspan="2"> Scaled Feedback Layer</td> * </tr> * <tr> * <td> </td> * <td>├</td> * <td colspan="2"> Printable Layers</td> * </tr> * <tr> * <td> </td> * <td> </td> * <td>├ Connection Layer</td> * </tr> * <tr> * <td> </td> * <td> </td> * <td>└ Primary Layer</td> * <td> </td> * </tr> * <tr> * <td> </td> * <td>└</td> * <td colspan="2"> Grid Layer</td> * </tr> * </table> * * @author Eric Bordeau * @since 2.1.1 */ public class ScalableRootEditPart extends SimpleRootEditPart implements LayerConstants, LayerManager { class FeedbackLayer extends Layer { FeedbackLayer() { setEnabled(false); } /** * @see org.eclipse.draw2d.Figure#getPreferredSize(int, int) */ public Dimension getPreferredSize(int wHint, int hHint) { Rectangle rect = new Rectangle(); for (int i = 0; i < getChildren().size(); i++) rect.union(((IFigure) getChildren().get(i)).getBounds()); return rect.getSize(); } } private LayeredPane innerLayers; private LayeredPane printableLayers; private ScalableLayeredPane scaledLayers; private PropertyChangeListener gridListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { String property = evt.getPropertyName(); if (property.equals(SnapToGrid.PROPERTY_GRID_ORIGIN) || property.equals(SnapToGrid.PROPERTY_GRID_SPACING) || property.equals(SnapToGrid.PROPERTY_GRID_VISIBLE)) refreshGridLayer(); } }; private ZoomManager zoomManager; /** * Constructor for ScalableFreeformRootEditPart */ public ScalableRootEditPart() { zoomManager = new ZoomManager((ScalableLayeredPane) getScaledLayers(), ((Viewport) getFigure())); } /** * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() */ protected IFigure createFigure() { Viewport viewport = createViewport(); innerLayers = new LayeredPane(); createLayers(innerLayers); viewport.setContents(innerLayers); return viewport; } /** * Creates a {@link GridLayer grid}. Sub-classes can override this method to * customize the appearance of the grid. The grid layer should be the first * layer (i.e., beneath the primary layer) if it is not to cover up parts on * the primary layer. In that case, the primary layer should be transparent * so that the grid is visible. * * @return the newly created GridLayer */ protected GridLayer createGridLayer() { return new GridLayer(); } /** * Creates the top-most set of layers on the given layered pane * * @param layeredPane * the parent for the created layers */ protected void createLayers(LayeredPane layeredPane) { layeredPane.add(getScaledLayers(), SCALABLE_LAYERS); layeredPane.add(new Layer() { public Dimension getPreferredSize(int wHint, int hHint) { return new Dimension(); } }, HANDLE_LAYER); layeredPane.add(new FeedbackLayer(), FEEDBACK_LAYER); layeredPane.add(new GuideLayer(), GUIDE_LAYER); } /** * Creates a layered pane and the layers that should be printed. * * @see org.eclipse.gef.print.PrintGraphicalViewerOperation * @return a new LayeredPane containing the printable layers */ protected LayeredPane createPrintableLayers() { LayeredPane pane = new LayeredPane(); Layer layer = new Layer(); layer.setLayoutManager(new StackLayout()); pane.add(layer, PRIMARY_LAYER); layer = new ConnectionLayer(); layer.setPreferredSize(new Dimension(5, 5)); pane.add(layer, CONNECTION_LAYER); return pane; } /** * Creates a scalable layered pane and the layers that should be scaled. * * @return a new <code>ScalableLayeredPane</code> containing the scalable * layers */ protected ScalableLayeredPane createScaledLayers() { ScalableLayeredPane layers = new ScalableLayeredPane(); layers.add(createGridLayer(), GRID_LAYER); layers.add(getPrintableLayers(), PRINTABLE_LAYERS); layers.add(new FeedbackLayer(), SCALED_FEEDBACK_LAYER); return layers; } /** * Constructs the viewport that will be used to contain all of the layers. * * @return a new Viewport */ protected Viewport createViewport() { return new Viewport(true); } /** * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ public Object getAdapter(Class key) { if (key == AutoexposeHelper.class) return new ViewportAutoexposeHelper(this); return super.getAdapter(key); } /** * The contents' Figure will be added to the PRIMARY_LAYER. * * @see org.eclipse.gef.GraphicalEditPart#getContentPane() */ public IFigure getContentPane() { return getLayer(PRIMARY_LAYER); } /** * Should not be called, but returns a MarqeeDragTracker for good measure. * * @see org.eclipse.gef.EditPart#getDragTracker(org.eclipse.gef.Request) */ public DragTracker getDragTracker(Request req) { /* * The root will only be asked for a drag tracker if for some reason the * contents EditPart is not selectable or has a non-opaque figure. */ return new MarqueeDragTracker(); } /** * Returns the layer indicated by the key. Searches all layered panes. * * @see LayerManager#getLayer(Object) */ public IFigure getLayer(Object key) { if (innerLayers == null) return null; IFigure layer = scaledLayers.getLayer(key); if (layer != null) return layer; layer = printableLayers.getLayer(key); if (layer != null) return layer; return innerLayers.getLayer(key); } /** * The root editpart does not have a real model. The LayerManager ID is * returned so that this editpart gets registered using that key. * * @see org.eclipse.gef.EditPart#getModel() */ public Object getModel() { return LayerManager.ID; } /** * Returns the LayeredPane that should be used during printing. This layer * will be identified using {@link LayerConstants#PRINTABLE_LAYERS}. * * @return the layered pane containing all printable content */ protected LayeredPane getPrintableLayers() { if (printableLayers == null) printableLayers = createPrintableLayers(); return printableLayers; } /** * Returns the scalable layers of this EditPart * * @return LayeredPane */ protected LayeredPane getScaledLayers() { if (scaledLayers == null) scaledLayers = createScaledLayers(); return scaledLayers; } /** * Returns the zoomManager. * * @return ZoomManager */ public ZoomManager getZoomManager() { return zoomManager; } /** * Updates the {@link GridLayer grid} based on properties set on the * {@link #getViewer() graphical viewer}: * {@link SnapToGrid#PROPERTY_GRID_VISIBLE}, * {@link SnapToGrid#PROPERTY_GRID_SPACING}, and * {@link SnapToGrid#PROPERTY_GRID_ORIGIN}. * <p> * This method is invoked initially when the GridLayer is created, and when * any of the above-mentioned properties are changed on the viewer. */ protected void refreshGridLayer() { boolean visible = false; GridLayer grid = (GridLayer) getLayer(GRID_LAYER); Boolean val = (Boolean) getViewer().getProperty( SnapToGrid.PROPERTY_GRID_VISIBLE); if (val != null) visible = val.booleanValue(); grid.setOrigin((Point) getViewer().getProperty( SnapToGrid.PROPERTY_GRID_ORIGIN)); grid.setSpacing((Dimension) getViewer().getProperty( SnapToGrid.PROPERTY_GRID_SPACING)); grid.setVisible(visible); } /** * @see org.eclipse.gef.editparts.AbstractEditPart#register() */ protected void register() { super.register(); getViewer().setProperty(ZoomManager.class.toString(), getZoomManager()); if (getLayer(GRID_LAYER) != null) { getViewer().addPropertyChangeListener(gridListener); refreshGridLayer(); } } /** * @see org.eclipse.gef.editparts.AbstractEditPart#unregister() */ protected void unregister() { getViewer().removePropertyChangeListener(gridListener); super.unregister(); getViewer().setProperty(ZoomManager.class.toString(), null); } }