All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.draw2d.PolylineConnection Maven / Gradle / Ivy

/*******************************************************************************
 * 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.draw2d;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;

/**
 * An implementation of {@link Connection} based on Polyline. PolylineConnection
 * adds the following additional features:
 * 
    *
  • * A {@link ConnectionRouter} may be provided which will be used to determine * the connections points. *
  • * Children may be added. The bounds calculation is extended such that the * bounds is the smallest Rectangle which is large enough to display the * Polyline and all of its children figures. *
  • * A {@link DelegatingLayout} is set as the default layout. A delegating layout * allows children to position themselves via {@link Locator Locators}. *
*

*/ public class PolylineConnection extends Polyline implements Connection, AnchorListener { private ConnectionAnchor startAnchor, endAnchor; private ConnectionRouter connectionRouter = ConnectionRouter.NULL; private RotatableDecoration startArrow, endArrow; { setLayoutManager(new DelegatingLayout()); addPoint(new Point(0, 0)); addPoint(new Point(100, 100)); } /** * Hooks the source and target anchors. * * @see Figure#addNotify() */ public void addNotify() { super.addNotify(); hookSourceAnchor(); hookTargetAnchor(); } /** * Appends the given routing listener to the list of listeners. * * @param listener * the routing listener * @since 3.2 */ public void addRoutingListener(RoutingListener listener) { if (connectionRouter instanceof RoutingNotifier) { RoutingNotifier notifier = (RoutingNotifier) connectionRouter; notifier.listeners.add(listener); } else connectionRouter = new RoutingNotifier(connectionRouter, listener); } /** * Called by the anchors of this connection when they have moved, * revalidating this polyline connection. * * @param anchor * the anchor that moved */ public void anchorMoved(ConnectionAnchor anchor) { revalidate(); } /** * Returns the bounds which holds all the points in this polyline * connection. Returns any previously existing bounds, else calculates by * unioning all the children's dimensions. * * @return the bounds */ public Rectangle getBounds() { if (bounds == null) { super.getBounds(); for (int i = 0; i < getChildren().size(); i++) { IFigure child = (IFigure) getChildren().get(i); bounds.union(child.getBounds()); } } return bounds; } /** * Returns the ConnectionRouter used to layout this connection. * Will not return null. * * @return this connection's router */ public ConnectionRouter getConnectionRouter() { if (connectionRouter instanceof RoutingNotifier) return ((RoutingNotifier) connectionRouter).realRouter; return connectionRouter; } /** * Returns this connection's routing constraint from its connection router. * May return null. * * @return the connection's routing constraint */ public Object getRoutingConstraint() { if (getConnectionRouter() != null) return getConnectionRouter().getConstraint(this); else return null; } /** * @return the anchor at the start of this polyline connection (may be null) */ public ConnectionAnchor getSourceAnchor() { return startAnchor; } /** * @return the source decoration (may be null) */ protected RotatableDecoration getSourceDecoration() { return startArrow; } /** * @return the anchor at the end of this polyline connection (may be null) */ public ConnectionAnchor getTargetAnchor() { return endAnchor; } /** * @return the target decoration (may be null) * * @since 2.0 */ protected RotatableDecoration getTargetDecoration() { return endArrow; } private void hookSourceAnchor() { if (getSourceAnchor() != null) getSourceAnchor().addAnchorListener(this); } private void hookTargetAnchor() { if (getTargetAnchor() != null) getTargetAnchor().addAnchorListener(this); } /** * Layouts this polyline. If the start and end anchors are present, the * connection router is used to route this, after which it is laid out. It * also fires a moved method. */ public void layout() { if (getSourceAnchor() != null && getTargetAnchor() != null) connectionRouter.route(this); Rectangle oldBounds = bounds; super.layout(); bounds = null; if (!getBounds().contains(oldBounds)) { getParent().translateToParent(oldBounds); getUpdateManager().addDirtyRegion(getParent(), oldBounds); } repaint(); fireFigureMoved(); } /** * Called just before the receiver is being removed from its parent. Results * in removing itself from the connection router. * * @since 2.0 */ public void removeNotify() { unhookSourceAnchor(); unhookTargetAnchor(); connectionRouter.remove(this); super.removeNotify(); } /** * Removes the first occurence of the given listener. * * @param listener * the listener being removed * @since 3.2 */ public void removeRoutingListener(RoutingListener listener) { if (connectionRouter instanceof RoutingNotifier) { RoutingNotifier notifier = (RoutingNotifier) connectionRouter; notifier.listeners.remove(listener); if (notifier.listeners.isEmpty()) connectionRouter = notifier.realRouter; } } /** * @see IFigure#revalidate() */ public void revalidate() { super.revalidate(); connectionRouter.invalidate(this); } /** * Sets the connection router which handles the layout of this polyline. * Generally set by the parent handling the polyline connection. * * @param cr * the connection router */ public void setConnectionRouter(ConnectionRouter cr) { if (cr == null) cr = ConnectionRouter.NULL; ConnectionRouter oldRouter = getConnectionRouter(); if (oldRouter != cr) { connectionRouter.remove(this); if (connectionRouter instanceof RoutingNotifier) ((RoutingNotifier) connectionRouter).realRouter = cr; else connectionRouter = cr; firePropertyChange(Connection.PROPERTY_CONNECTION_ROUTER, oldRouter, cr); revalidate(); } } /** * Sets the routing constraint for this connection. * * @param cons * the constraint */ public void setRoutingConstraint(Object cons) { if (connectionRouter != null) connectionRouter.setConstraint(this, cons); revalidate(); } /** * Sets the anchor to be used at the start of this polyline connection. * * @param anchor * the new source anchor */ public void setSourceAnchor(ConnectionAnchor anchor) { if (anchor == startAnchor) return; unhookSourceAnchor(); // No longer needed, revalidate does this. // getConnectionRouter().invalidate(this); startAnchor = anchor; if (getParent() != null) hookSourceAnchor(); revalidate(); } /** * Sets the decoration to be used at the start of the {@link Connection}. * * @param dec * the new source decoration * @since 2.0 */ public void setSourceDecoration(RotatableDecoration dec) { if (startArrow == dec) return; if (startArrow != null) remove(startArrow); startArrow = dec; if (startArrow != null) add(startArrow, new ArrowLocator(this, ConnectionLocator.SOURCE)); } /** * Sets the anchor to be used at the end of the polyline connection. Removes * this listener from the old anchor and adds it to the new anchor. * * @param anchor * the new target anchor */ public void setTargetAnchor(ConnectionAnchor anchor) { if (anchor == endAnchor) return; unhookTargetAnchor(); // No longer needed, revalidate does this. // getConnectionRouter().invalidate(this); endAnchor = anchor; if (getParent() != null) hookTargetAnchor(); revalidate(); } /** * Sets the decoration to be used at the end of the {@link Connection}. * * @param dec * the new target decoration */ public void setTargetDecoration(RotatableDecoration dec) { if (endArrow == dec) return; if (endArrow != null) remove(endArrow); endArrow = dec; if (endArrow != null) add(endArrow, new ArrowLocator(this, ConnectionLocator.TARGET)); } private void unhookSourceAnchor() { if (getSourceAnchor() != null) getSourceAnchor().removeAnchorListener(this); } private void unhookTargetAnchor() { if (getTargetAnchor() != null) getTargetAnchor().removeAnchorListener(this); } final class RoutingNotifier implements ConnectionRouter { ConnectionRouter realRouter; List listeners = new ArrayList(1); RoutingNotifier(ConnectionRouter router, RoutingListener listener) { realRouter = router; listeners.add(listener); } public Object getConstraint(Connection connection) { return realRouter.getConstraint(connection); } public void invalidate(Connection connection) { for (int i = 0; i < listeners.size(); i++) ((RoutingListener) listeners.get(i)).invalidate(connection); realRouter.invalidate(connection); } public void route(Connection connection) { boolean consumed = false; for (int i = 0; i < listeners.size(); i++) consumed |= ((RoutingListener) listeners.get(i)) .route(connection); if (!consumed) realRouter.route(connection); for (int i = 0; i < listeners.size(); i++) ((RoutingListener) listeners.get(i)).postRoute(connection); } public void remove(Connection connection) { for (int i = 0; i < listeners.size(); i++) ((RoutingListener) listeners.get(i)).remove(connection); realRouter.remove(connection); } public void setConstraint(Connection connection, Object constraint) { for (int i = 0; i < listeners.size(); i++) ((RoutingListener) listeners.get(i)).setConstraint(connection, constraint); realRouter.setConstraint(connection, constraint); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy