1 package net.sf.openrocket.gui.main;
3 import java.util.ArrayList;
4 import java.util.Enumeration;
5 import java.util.Iterator;
7 import javax.swing.JTree;
8 import javax.swing.event.TreeModelEvent;
9 import javax.swing.event.TreeModelListener;
10 import javax.swing.tree.TreeModel;
11 import javax.swing.tree.TreePath;
13 import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
14 import net.sf.openrocket.rocketcomponent.ComponentChangeListener;
15 import net.sf.openrocket.rocketcomponent.RocketComponent;
19 * A TreeModel that implements viewing of the rocket tree structure.
20 * This class shows the internal structure of the tree, as opposed to the regular
23 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
26 public class BareComponentTreeModel implements TreeModel, ComponentChangeListener {
27 ArrayList<TreeModelListener> listeners = new ArrayList<TreeModelListener>();
29 private final RocketComponent root;
30 private final JTree tree;
32 public BareComponentTreeModel(RocketComponent root, JTree tree) {
35 root.addComponentChangeListener(this);
39 public Object getChild(Object parent, int index) {
40 RocketComponent component = (RocketComponent)parent;
42 return component.getChild(index);
43 } catch (IndexOutOfBoundsException e) {
48 public int getChildCount(Object parent) {
49 return ((RocketComponent)parent).getChildCount();
52 public int getIndexOfChild(Object parent, Object child) {
53 RocketComponent p = (RocketComponent)parent;
54 RocketComponent c = (RocketComponent)child;
55 return p.getChildPosition(c);
58 public Object getRoot() {
62 public boolean isLeaf(Object node) {
63 RocketComponent c = (RocketComponent)node;
64 return (c.getChildCount()==0);
67 public void addTreeModelListener(TreeModelListener l) {
71 public void removeTreeModelListener(TreeModelListener l) {
75 private void fireTreeNodesChanged() {
76 Object[] path = { root };
77 TreeModelEvent e = new TreeModelEvent(this,path);
78 Object[] l = listeners.toArray();
79 for (int i=0; i<l.length; i++)
80 ((TreeModelListener)l[i]).treeNodesChanged(e);
84 private void printStructure(TreePath p, int level) {
86 for (int i=0; i<level; i++)
88 System.out.println(indent+p+
89 ": isVisible:"+tree.isVisible(p)+
90 " isCollapsed:"+tree.isCollapsed(p)+
91 " isExpanded:"+tree.isExpanded(p));
92 Object parent = p.getLastPathComponent();
93 for (int i=0; i<getChildCount(parent); i++) {
94 Object child = getChild(parent,i);
95 TreePath path = makeTreePath((RocketComponent)child);
96 printStructure(path,level+1);
101 private void fireTreeStructureChanged(RocketComponent source) {
102 Object[] path = { root };
105 // Get currently expanded path IDs
106 Enumeration<TreePath> enumer = tree.getExpandedDescendants(new TreePath(path));
107 ArrayList<String> expanded = new ArrayList<String>();
108 if (enumer != null) {
109 while (enumer.hasMoreElements()) {
110 TreePath p = enumer.nextElement();
111 expanded.add(((RocketComponent)p.getLastPathComponent()).getID());
115 // Send structure change event
116 TreeModelEvent e = new TreeModelEvent(this,path);
117 Object[] l = listeners.toArray();
118 for (int i=0; i<l.length; i++)
119 ((TreeModelListener)l[i]).treeStructureChanged(e);
121 // Re-expand the paths
122 Iterator<String> iter = expanded.iterator();
123 while (iter.hasNext()) {
124 RocketComponent c = root.findComponent(iter.next());
127 tree.expandPath(makeTreePath(c));
129 if (source != null) {
130 TreePath p = makeTreePath(source);
136 public void valueForPathChanged(TreePath path, Object newValue) {
137 System.err.println("ERROR: valueForPathChanged called?!");
141 public void componentChanged(ComponentChangeEvent e) {
142 if (e.isTreeChange() || e.isUndoChange()) {
143 // Tree must be fully updated also in case of an undo change
144 fireTreeStructureChanged((RocketComponent)e.getSource());
145 if (e.isTreeChange() && e.isUndoChange()) {
146 // If the undo has changed the tree structure, some elements may be hidden unnecessarily
147 // TODO: LOW: Could this be performed better?
150 } else if (e.isOtherChange()) {
151 fireTreeNodesChanged();
155 public void expandAll() {
156 Iterator<RocketComponent> iterator = root.deepIterator();
157 while (iterator.hasNext()) {
158 tree.makeVisible(makeTreePath(iterator.next()));
162 public static TreePath makeTreePath(RocketComponent component) {
164 RocketComponent c = component;
171 Object[] list = new Object[count];
181 return new TreePath(list);