/******************************************************************************* * Copyright (c) 2009 the CHISEL group and contributors. * 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: * Del Myers -- initial API and implementation *******************************************************************************/ package org.eclipse.zest.custom.sequence.figures.internal; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import org.eclipse.draw2d.AncestorListener; import org.eclipse.draw2d.FigureListener; import org.eclipse.draw2d.IFigure; /** * 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$ } } }