/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info: http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2004, by :
* Corporate:
* Astrium SAS
* Individual:
* Claude Cazenave
*
* $Id: SceneGraphModel.java,v 1.7 2005/09/02 11:57:30 ogor Exp $
*
* Changes
* -------
* 14-Dec-2003 : Creation date (CC);
*
*/
package syn3d.ui;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import simtools.ui.MenuResourceBundle;
import simtools.ui.ResourceFinder;
import syn3d.base.ActiveNode;
import syn3d.nodes.*;
/**
* Class description ...
*
* @author Claude CAZENAVE
*
*/
public abstract class SceneGraphModel implements TreeModel {
/** Resources */
protected static MenuResourceBundle resources=ResourceFinder.getMenu(SceneGraphModel.class);
protected RootNode rootNode = new RootNode();
/** Listeners. */
protected EventListenerList listenerList = new EventListenerList();
public void setRootNode(RootNode rootNode) {
// TODO effacer l'ancienne arborescence !!!
this.rootNode = rootNode;
}
// Developper-friendly API
public RootNode getRootNode() {
return rootNode;
}
public Object getRoot(){
return rootNode;
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#addTreeModelListener(javax.swing.event.TreeModelListener)
*/
public void addTreeModelListener(TreeModelListener l) {
listenerList.add(TreeModelListener.class, l);
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#removeTreeModelListener(javax.swing.event.TreeModelListener)
*/
public void removeTreeModelListener(TreeModelListener l) {
listenerList.remove(TreeModelListener.class, l);
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#valueForPathChanged(javax.swing.tree.TreePath, java.lang.Object)
*/
public void valueForPathChanged(TreePath path, Object newValue) {
// TODO
}
/**
* Builds the parents of object up to and including the root object,
* where the original object is the last element in the returned array.
* The length of the returned array gives the object's depth in the
* tree.
*
* @param o the Object to get the path for
* @return an array of Object giving the path from the root to the
* specified object
*/
public ActiveNode[] getPathToRoot(ActiveNode o) {
return getPathToRoot(o, 0);
}
/**
* Builds the parents of object up to and including the root object,
* where the original object is the last element in the returned array.
* The length of the returned array gives the object's depth in the
* tree.
*
* @param o the Object to get the path for
* @param depth an int giving the number of steps already taken towards
* the root (on recursive calls), used to size the returned array
* @return an array of Object giving the path from the root to the
* specified object
*/
public ActiveNode[] getPathToRoot(ActiveNode o, int depth) {
ActiveNode[] ret;
// This method recurses, traversing towards the root in order
// size the array. On the way back, it fills in the nodes,
// starting from the root and working back to the original node.
/* Check for null, in case someone passed in a null node, or
they passed in an element that isn't rooted at root. */
if (o == null) {
if (depth == 0)
return null;
else
ret = new ActiveNode[depth];
} else {
depth++;
if (o == getRoot())
ret = new ActiveNode[depth];
else
ret = getPathToRoot(o.getParent(), depth);
ret[ret.length - depth] = o;
}
return ret;
}
/**
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is lazily created using the parameters passed into
* the fire method.
*
* @param source the node where the tree model has changed
* @param path the path to the root node
* @param childIndices the indices of the affected elements
* @param children the affected elements
* @see EventListenerList
*/
public void fireTreeChanged(ActiveNode source, Object[] path,
int[] childIndices,
ActiveNode[] children) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
TreeModelEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==TreeModelListener.class) {
// Lazily create the event:
if (e == null)
e = new TreeModelEvent(source, path,
childIndices, children);
((TreeModelListener)listeners[i+1]).treeStructureChanged(e);
}
}
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#getChildCount(java.lang.Object)
*/
public int getChildCount(Object parent) {
if (!(parent instanceof ActiveNode)) return 0;
ActiveNode node = (ActiveNode)parent;
return node.getChildren().size();
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#getChild(java.lang.Object, int)
*/
public Object getChild(Object parent, int index) {
if (!(parent instanceof ActiveNode)) return null;
ActiveNode node = (ActiveNode)parent;
return node.getChildren().get(index);
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#getIndexOfChild(java.lang.Object, java.lang.Object)
*/
public int getIndexOfChild(Object parent, Object child) {
if (!(parent instanceof ActiveNode)) return 0;
if (!(child instanceof ActiveNode)) return 0;
ActiveNode node = (ActiveNode)parent;
return node.getChildren().indexOf(child);
}
/* (non-Javadoc)
* @see javax.swing.tree.TreeModel#isLeaf(java.lang.Object)
*/
public boolean isLeaf(Object node) {
if (!(node instanceof ActiveNode)) return false;
if (node == rootNode) return false;
ActiveNode anode = (ActiveNode)node;
return isLeaf3D(anode.get3DObject());
}
protected abstract boolean isLeaf3D(Object o);
// TODO : serialization routines
}