/******************************************************************************* * Copyright (c) 2008 * The code, documentation and other materials contained herein have been * licensed under the Eclipse Public License - v 1.0 by the individual * copyright holders listed below, as Initial Contributors under such license. * The text of such license is available at * http://www.eclipse.org/legal/epl-v10.html. * * Contributors: * Henrik Lindberg *******************************************************************************/ package org.eclipse.buckminster.generic.model.tree; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * A Tree Parent Data Node that is useful as the top node in a data tree. This * class supports listening to TreeData events (see ITreeRootNode). When a * childNodeChange() has bubbled to this root, a TreeRootNode event is fired. * * This enables a view to register a listener for this top node only, and still * be notified about any change in the tree. * * @author Henrik Lindberg * */ public abstract class AbstractTreeRootDataNode extends BasicTreeParentDataNode implements ITreeRootNode { private final List<ITreeDataListener> listeners; public AbstractTreeRootDataNode(Object data) { super(data); listeners = new LinkedList<ITreeDataListener>(); } /** * Adds a tree data listener to the set of listeners. A listener is only * added once. */ @Override public void addTreeDataListener(ITreeDataListener listener) { if (!listeners.contains(listener)) listeners.add(listener); } /** * Whenever a child node has changed, a TreeDataEvent is sent to registered * listeners. Also, if this root has a parent, the event bubbles further up * the chain. */ @Override public void childNodeChanged(ITreeDataNode child) { fireTreeDataChanged(child); ITreeParentDataNode parent = getParent(); if (parent != null) parent.childNodeChanged(child); } /** * Removes a tree data listener from the set of listeners. Does nothing if * the listener is not a registered listener. */ @Override public void removeTreeDataListener(ITreeDataListener listener) { listeners.remove(listener); } /** * Fires a tree data change event to register listeners that the changedNode * has changed. The listeners are notified in a UI thread. * * @param changedNode */ protected void fireTreeDataChanged(ITreeDataNode changedNode) { triggerListeners(TreeDataEvent.changed(this, changedNode)); } /** * Calls listeners in the current thread. A derived class should call this * method from its triggerListener where a suitable runnable for the * environment should have been created. * * @param e */ protected void inProcTriggerListeners(final TreeDataEvent e) { // copy the listener list or face consequences of event listeners adding // or removing // listeners when processing events ArrayList<ITreeDataListener> listenersCopy = new ArrayList<ITreeDataListener>(listeners); for (ITreeDataListener a : listenersCopy) a.treeNodeChanged(e); } /** * Called to trigger listeners - a derived class should create a suitable * thread to update listeners. A non UI implementation that does not need * asynch handling could call the inProcTriggerListeners method directly. An * implementation to use with the UI should perform an asynch exec in the UI * thread and call the inProcTriggerListeners from that thread. * * @param e */ abstract protected void triggerListeners(final TreeDataEvent e); }