| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation 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 |
| *******************************************************************************/ |
| package org.eclipse.draw2d; |
| |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| |
| /** |
| * A helper object which tracks the parent chain hierarchy. |
| * |
| * @since 2.1 |
| */ |
| class AncestorHelper implements PropertyChangeListener, FigureListener { |
| |
| /** |
| * The base figure whose ancestor chain is being observed. |
| */ |
| protected final IFigure base; |
| /** |
| * The array of ancestor listeners. |
| */ |
| protected AncestorListener[] listeners; |
| |
| /** |
| * Constructs a new helper on the given base figure and starts listening to |
| * figure and property changes on the base figure's parent chain. When no |
| * longer needed, the helper should be disposed. |
| * |
| * @since 2.1 |
| * @param baseFigure |
| */ |
| public AncestorHelper(IFigure baseFigure) { |
| this.base = baseFigure; |
| addAncestors(baseFigure); |
| } |
| |
| /** |
| * Appends a new listener to the list of listeners. |
| * |
| * @param listener |
| * the listener |
| */ |
| public void addAncestorListener(AncestorListener listener) { |
| if (listeners == null) { |
| listeners = new AncestorListener[1]; |
| listeners[0] = listener; |
| } else { |
| int oldSize = listeners.length; |
| AncestorListener newListeners[] = new AncestorListener[oldSize + 1]; |
| System.arraycopy(listeners, 0, newListeners, 0, oldSize); |
| newListeners[oldSize] = listener; |
| listeners = newListeners; |
| } |
| } |
| |
| /** |
| * Hooks up internal listeners used for maintaining the proper figure |
| * listeners. |
| * |
| * @param rootFigure |
| * the root figure |
| */ |
| protected void addAncestors(IFigure rootFigure) { |
| for (IFigure ancestor = rootFigure; ancestor != null; ancestor = ancestor |
| .getParent()) { |
| ancestor.addFigureListener(this); |
| ancestor.addPropertyChangeListener("parent", this); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * Removes all internal listeners. |
| */ |
| public void dispose() { |
| removeAncestors(base); |
| listeners = null; |
| } |
| |
| /** |
| * @see org.eclipse.draw2d.FigureListener#figureMoved(org.eclipse.draw2d.IFigure) |
| */ |
| public void figureMoved(IFigure ancestor) { |
| fireAncestorMoved(ancestor); |
| } |
| |
| /** |
| * Fires notification to the listener list |
| * |
| * @param ancestor |
| * the figure which moved |
| */ |
| protected void fireAncestorMoved(IFigure ancestor) { |
| if (listeners == null) |
| return; |
| for (int i = 0; i < listeners.length; i++) |
| listeners[i].ancestorMoved(ancestor); |
| } |
| |
| /** |
| * Fires notification to the listener list |
| * |
| * @param ancestor |
| * the figure which moved |
| */ |
| protected void fireAncestorAdded(IFigure ancestor) { |
| if (listeners == null) |
| return; |
| for (int i = 0; i < listeners.length; i++) |
| listeners[i].ancestorAdded(ancestor); |
| } |
| |
| /** |
| * Fires notification to the listener list |
| * |
| * @param ancestor |
| * the figure which moved |
| */ |
| protected void fireAncestorRemoved(IFigure ancestor) { |
| if (listeners == null) |
| return; |
| for (int i = 0; i < listeners.length; i++) |
| listeners[i].ancestorRemoved(ancestor); |
| } |
| |
| /** |
| * Returns the total number of listeners. |
| * |
| * @return the number of listeners |
| */ |
| public boolean isEmpty() { |
| return listeners == null; |
| } |
| |
| /** |
| * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) |
| */ |
| public void propertyChange(PropertyChangeEvent event) { |
| if (event.getPropertyName().equals("parent")) { //$NON-NLS-1$ |
| IFigure oldParent = (IFigure) event.getOldValue(); |
| IFigure newParent = (IFigure) event.getNewValue(); |
| if (oldParent != null) { |
| removeAncestors(oldParent); |
| fireAncestorRemoved(oldParent); |
| } |
| if (newParent != null) { |
| addAncestors(newParent); |
| fireAncestorAdded(newParent); |
| } |
| } |
| } |
| |
| /** |
| * Removes the first occurence of the given listener |
| * |
| * @param listener |
| * the listener to remove |
| */ |
| public void removeAncestorListener(AncestorListener listener) { |
| if (listeners == null) |
| return; |
| for (int index = 0; index < listeners.length; index++) |
| if (listeners[index] == listener) { |
| int newSize = listeners.length - 1; |
| AncestorListener newListeners[] = null; |
| if (newSize != 0) { |
| newListeners = new AncestorListener[newSize]; |
| System.arraycopy(listeners, 0, newListeners, 0, index); |
| System.arraycopy(listeners, index + 1, newListeners, index, |
| newSize - index); |
| } |
| listeners = newListeners; |
| return; |
| } |
| } |
| |
| /** |
| * Unhooks listeners starting at the given figure |
| * |
| * @param rootFigure |
| */ |
| protected void removeAncestors(IFigure rootFigure) { |
| for (IFigure ancestor = rootFigure; ancestor != null; ancestor = ancestor |
| .getParent()) { |
| ancestor.removeFigureListener(this); |
| ancestor.removePropertyChangeListener("parent", this); //$NON-NLS-1$ |
| } |
| } |
| |
| } |