/* ****************************************************************************** * Copyright (c) 2006-2012 XMind Ltd. and others. * * This file is a part of XMind 3. XMind releases 3 and * above are dual-licensed under the Eclipse Public License (EPL), * which is available at http://www.eclipse.org/legal/epl-v10.html * and the GNU Lesser General Public License (LGPL), * which is available at http://www.gnu.org/licenses/lgpl.html * See http://www.xmind.net/license.html for details. * * Contributors: * XMind Ltd. - initial API and implementation *******************************************************************************/ package org.xmind.gef.draw2d; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.draw2d.FigureListener; import org.eclipse.draw2d.FreeformFigure; import org.eclipse.draw2d.FreeformListener; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.PositionConstants; import org.eclipse.draw2d.geometry.Rectangle; import org.xmind.gef.draw2d.geometry.PrecisionPoint; public abstract class AbstractAnchor implements IAnchor, FigureListener, FreeformListener, PropertyChangeListener { private List<IAnchorListener> listeners = null; private IFigure owner; private Set<String> propertiesToMove = null; protected AbstractAnchor() { } public AbstractAnchor(IFigure owner) { setOwner(owner); } protected void setOwner(IFigure owner) { if (owner == this.owner) return; if (getOwner() != null && hasAnchorListener()) { unhookOwner(getOwner()); } this.owner = owner; if (getOwner() != null && hasAnchorListener()) { hookOwner(getOwner()); } } protected void hookOwner(IFigure owner) { owner.addFigureListener(this); if (owner instanceof FreeformFigure) { ((FreeformFigure) owner).addFreeformListener(this); } if (propertiesToMove != null) { for (String property : propertiesToMove) { owner.addPropertyChangeListener(property, this); } } } protected void unhookOwner(IFigure owner) { owner.removeFigureListener(this); if (owner instanceof FreeformFigure) { ((FreeformFigure) owner).removeFreeformListener(this); } if (propertiesToMove != null) { for (String property : propertiesToMove) { owner.removePropertyChangeListener(property, this); } } } public PrecisionPoint getLocation(int orientation, double expansion) { switch (orientation) { case PositionConstants.WEST: return getWest(expansion); case PositionConstants.SOUTH: return getSouth(expansion); case PositionConstants.NORTH: return getNorth(expansion); } return getEast(expansion); } protected PrecisionPoint getEast(double expansion) { PrecisionPoint ref = getReferencePoint(); return getLocation(ref.x + 100, ref.y, expansion); } protected PrecisionPoint getNorth(double expansion) { PrecisionPoint ref = getReferencePoint(); return getLocation(ref.x, ref.y - 100, expansion); } protected PrecisionPoint getSouth(double expansion) { PrecisionPoint ref = getReferencePoint(); return getLocation(ref.x, ref.y + 100, expansion); } protected PrecisionPoint getWest(double expansion) { PrecisionPoint ref = getReferencePoint(); return getLocation(ref.x - 100, ref.y, expansion); } public PrecisionPoint getLocation(PrecisionPoint reference, double expansion) { return getLocation(reference.x, reference.y, expansion); } public void addAnchorListener(IAnchorListener listener) { boolean hadListener = hasAnchorListener(); if (listeners == null) listeners = new ArrayList<IAnchorListener>(); listeners.add(listener); if (!hadListener && hasAnchorListener() && getOwner() != null) { hookOwner(getOwner()); } } public IFigure getOwner() { return owner; } public PrecisionPoint getReferencePoint() { if (getOwner() == null) return new PrecisionPoint(); if (getOwner() instanceof IReferencedFigure) { return new PrecisionPoint(((IReferencedFigure) getOwner()) .getReference()); } Rectangle r = getOwner().getBounds(); return new PrecisionPoint(r.x + r.width * 0.5, r.y + r.height * 0.5); } public void removeAnchorListener(IAnchorListener listener) { if (listeners == null) return; boolean hadListener = hasAnchorListener(); listeners.remove(listener); if (hadListener && !hasAnchorListener() && getOwner() != null) { unhookOwner(getOwner()); } } public void figureMoved(IFigure source) { fireAnchorMoved(); } public void notifyFreeformExtentChanged() { fireAnchorMoved(); } protected void fireAnchorMoved() { if (listeners == null) return; for (Object listener : listeners.toArray()) { ((IAnchorListener) listener).anchorMoved(this); } } protected boolean hasAnchorListener() { return listeners != null && !listeners.isEmpty(); } public void addAnchorMoveProperty(String... properties) { for (String property : properties) { addMoveProperty(property); } fireAnchorMoved(); } /** * @param property */ private void addMoveProperty(String property) { if (propertiesToMove == null) { propertiesToMove = new HashSet<String>(); } if (!propertiesToMove.contains(property)) { if (getOwner() != null && hasAnchorListener()) { getOwner().addPropertyChangeListener(property, this); } propertiesToMove.add(property); } } public void removeAnchorMoveProperty(String... properties) { if (propertiesToMove == null) return; for (String property : properties) { removeMoveProperty(property); } fireAnchorMoved(); } /** * @param property */ private void removeMoveProperty(String property) { if (getOwner() != null) { getOwner().removePropertyChangeListener(property, this); } propertiesToMove.remove(property); } /* * (non-Javadoc) * * @seejava.beans.PropertyChangeListener#propertyChange(java.beans. * PropertyChangeEvent) */ public void propertyChange(PropertyChangeEvent evt) { fireAnchorMoved(); } }