1 package jde.debugger.gui;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.Enumeration;
9 import java.util.Iterator;
10 import java.util.List;
11 import java.util.TreeSet;
12 import javax.swing.tree.DefaultMutableTreeNode;
13 import javax.swing.tree.DefaultTreeModel;
14 import javax.swing.tree.MutableTreeNode;
15 import javax.swing.tree.TreeNode;
17 import com.sun.jdi.ArrayReference;
18 import com.sun.jdi.ClassNotLoadedException;
19 import com.sun.jdi.Field;
20 import com.sun.jdi.ObjectCollectedException;
21 import com.sun.jdi.ObjectReference;
22 import com.sun.jdi.ReferenceType;
23 import com.sun.jdi.StringReference;
24 import com.sun.jdi.Value;
25 import jde.debugger.JDE;
26 import jde.debugger.JDEException;
27 import jde.debugger.Protocol;
35 /** A TreeNode for object references.
36 * @author <a href="mailto:udalrich@carolingia.org">Troy Daniels</a>
38 * @version $Revision: 1.2 $
40 class ReferenceTreeNode extends LVTreeNode implements Protocol {
42 * @param name The name of the variable
43 * @param type The Type of the variable
44 * @param val The value of the variable.
45 * @param model The tree model
47 protected ReferenceTreeNode(String name,
50 DefaultTreeModel model) throws JDEException {
51 super(name, typeName, val, model);
52 if (!((m_type instanceof ReferenceType) ||
54 throw new JDEException("ReferenceTreeNode received non-object reference Type " +
57 !(val instanceof ObjectReference)) {
58 JDE.debug(GUI, "Incorrect Value type in ReferenceTreeNode constructor");
59 JDE.debug(GUI, "val=" + val);
60 JDE.debug(GUI, "val.type()=" + val.type());
61 throw new JDEException("ReferenceTreeNode received non-object reference value " +
66 /** Called when the value has changed. Updates the object which
67 * actually implements the public methods.
68 * @param oldValue The old value
69 * @param newValue THe new value
71 protected void valueChanged(Value newValue) {
72 // Create the new model for displaying the value
74 m_model = new NullModel();
75 else if (newValue instanceof ArrayReference)
76 m_model = new ArrayModel((ArrayReference) newValue, getModel());
78 m_model = new ObjectModel((ObjectReference) newValue, getModel());
80 // If we have children, update the values in them and resize the
82 if (getAllowsChildren()) {
83 if (null == m_children)
84 m_children = new MutableTreeNode[m_model.getChildCount()];
86 // Ensure that the child array is the correct size
87 if (m_children.length != m_model.getChildCount()) {
88 MutableTreeNode[] newChildren = new MutableTreeNode[m_model.getChildCount()];
89 System.arraycopy(m_children, 0,
91 Math.min(m_children.length,
93 m_children = newChildren;
99 m_model.updateChildren(m_children);
103 /** Get the number of children.
104 * @return The number of fields that we should be displaying.
106 public int getChildCount() {
107 if (null == m_children)
110 return m_children.length;
113 /** Returns if the node allows children
114 * @return true if the value is not null. */
115 public boolean getAllowsChildren() {
116 return m_model.getAllowsChildren();
120 /** Get a string to represent the value of the variable */
122 return m_model.getValue();
129 * Returns the index of node in the receivers children.
131 * @param treeNode a <code>TreeNode</code> value
132 * @return the index of node in the receivers children. Returns -1
133 * if <code>treeNode</code> is not a child of this node.
135 public int getIndex(TreeNode treeNode) {
136 for (int index = 0; index < m_children.length; ++index)
137 if (m_children[index] == treeNode)
143 * Returns the children of the reciever as an Enumeration.
145 * @return the children of the reciever as an Enumeration.
147 public Enumeration children() {
148 return Collections.enumeration(Arrays.asList(m_children));
152 * Returns the child TreeNode at index childIndex. The child is
153 * created if it doesn't exist.
155 * @param childIndex the index of the child
156 * @return the child TreeNode at index childIndex.
158 public TreeNode getChildAt(int childIndex) {
160 if (null == m_children[childIndex]) {
161 m_children[childIndex] = m_model.createChildAt(childIndex);
162 m_children[childIndex].setParent(this);
164 } catch (JDEException exc) {
165 m_children[childIndex] =
166 new DefaultMutableTreeNode("Error displaying data: " + exc.getMessage());
168 return m_children[childIndex];
172 * Returns true if the receiver is a leaf.
174 * @return true if the receiver is a leaf.
176 public boolean isLeaf() {
177 return (null == m_children) ||
178 (m_children.length == 0);
184 * Returns the child TreeNode at index childIndex. The child is
185 * <b>not</b> created if it doesn't exist.
187 * @param childIndex the index of the child
188 * @return the child TreeNode at index childIndex or null if there
189 * is no child at that index yet, or the child is not an LVTreeNode.
191 protected LVTreeNode getExistingChildAt(int childIndex) {
192 if ((null == m_children[childIndex]) ||
193 (!(m_children[childIndex] instanceof LVTreeNode)))
195 return (LVTreeNode) m_children[childIndex];
198 /** Get the current length of the children array. For use when updating values. */
199 protected int getExistingChildLength() {
200 return m_children.length;
203 protected String paramString() {
204 return super.paramString() +
205 ",m_model=" + m_model +
206 ",m_children=" + m_children +
207 ((null == m_children)? "": ("[" + m_children.length + "]"));
210 private ReferenceModel m_model;
211 private MutableTreeNode[] m_children;