blob: 6ddb558c4f251fb3fb7ae3d7c190a4e5419549c2 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-1999 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.tools.example.debug.gui;
27
28import java.io.*;
29import java.util.*;
30
31import javax.swing.*;
32import javax.swing.tree.*;
33import javax.swing.event.*;
34import java.awt.*;
35import java.awt.event.*;
36
37import com.sun.jdi.*;
38import com.sun.tools.example.debug.event.*;
39import com.sun.tools.example.debug.bdi.*;
40
41public class ClassTreeTool extends JPanel {
42
43 private Environment env;
44
45 private ExecutionManager runtime;
46 private SourceManager sourceManager;
47 private ClassManager classManager;
48
49 private JTree tree;
50 private DefaultTreeModel treeModel;
51 private ClassTreeNode root;
52 private SearchPath sourcePath;
53
54 private CommandInterpreter interpreter;
55
56 private static String HEADING = "CLASSES";
57
58 public ClassTreeTool(Environment env) {
59
60 super(new BorderLayout());
61
62 this.env = env;
63 this.runtime = env.getExecutionManager();
64 this.sourceManager = env.getSourceManager();
65
66 this.interpreter = new CommandInterpreter(env);
67
68 root = createClassTree(HEADING);
69 treeModel = new DefaultTreeModel(root);
70
71 // Create a tree that allows one selection at a time.
72
73 tree = new JTree(treeModel);
74 tree.setSelectionModel(new SingleLeafTreeSelectionModel());
75
76 /******
77 // Listen for when the selection changes.
78 tree.addTreeSelectionListener(new TreeSelectionListener() {
79 public void valueChanged(TreeSelectionEvent e) {
80 ClassTreeNode node = (ClassTreeNode)
81 (e.getPath().getLastPathComponent());
82 if (node != null) {
83 interpreter.executeCommand("view " + node.getReferenceTypeName());
84 }
85 }
86 });
87 ******/
88
89 MouseListener ml = new MouseAdapter() {
90 public void mouseClicked(MouseEvent e) {
91 int selRow = tree.getRowForLocation(e.getX(), e.getY());
92 TreePath selPath = tree.getPathForLocation(e.getX(), e.getY());
93 if(selRow != -1) {
94 if(e.getClickCount() == 1) {
95 ClassTreeNode node =
96 (ClassTreeNode)selPath.getLastPathComponent();
97 // If user clicks on leaf, select it, and issue 'view' command.
98 if (node.isLeaf()) {
99 tree.setSelectionPath(selPath);
100 interpreter.executeCommand("view " + node.getReferenceTypeName());
101 }
102 }
103 }
104 }
105 };
106 tree.addMouseListener(ml);
107
108 JScrollPane treeView = new JScrollPane(tree);
109 add(treeView);
110
111 // Create listener.
112 ClassTreeToolListener listener = new ClassTreeToolListener();
113 runtime.addJDIListener(listener);
114 runtime.addSessionListener(listener);
115
116 //### remove listeners on exit!
117 }
118
119 private class ClassTreeToolListener extends JDIAdapter
120 implements JDIListener, SessionListener {
121
122 // SessionListener
123
124 public void sessionStart(EventObject e) {
125 // Get system classes and any others loaded before attaching.
126 try {
127 Iterator iter = runtime.allClasses().iterator();
128 while (iter.hasNext()) {
129 ReferenceType type = ((ReferenceType)iter.next());
130 root.addClass(type);
131 }
132 } catch (VMDisconnectedException ee) {
133 // VM terminated unexpectedly.
134 } catch (NoSessionException ee) {
135 // Ignore. Should not happen.
136 }
137 }
138
139 public void sessionInterrupt(EventObject e) {}
140 public void sessionContinue(EventObject e) {}
141
142 // JDIListener
143
144 public void classPrepare(ClassPrepareEventSet e) {
145 root.addClass(e.getReferenceType());
146 }
147
148 public void classUnload(ClassUnloadEventSet e) {
149 root.removeClass(e.getClassName());
150 }
151
152 public void vmDisconnect(VMDisconnectEventSet e) {
153 // Clear contents of this view.
154 root = createClassTree(HEADING);
155 treeModel = new DefaultTreeModel(root);
156 tree.setModel(treeModel);
157 }
158 }
159
160 ClassTreeNode createClassTree(String label) {
161 return new ClassTreeNode(label, null);
162 }
163
164 class ClassTreeNode extends DefaultMutableTreeNode {
165
166 private String name;
167 private ReferenceType refTy; // null for package
168
169 ClassTreeNode(String name, ReferenceType refTy) {
170 this.name = name;
171 this.refTy = refTy;
172 }
173
174 public String toString() {
175 return name;
176 }
177
178 public ReferenceType getReferenceType() {
179 return refTy;
180 }
181
182 public String getReferenceTypeName() {
183 return refTy.name();
184 }
185
186 private boolean isPackage() {
187 return (refTy == null);
188 }
189
190 public boolean isLeaf() {
191 return !isPackage();
192 }
193
194 public void addClass(ReferenceType refTy) {
195 addClass(refTy.name(), refTy);
196 }
197
198 private void addClass(String className, ReferenceType refTy) {
199 if (className.equals("")) {
200 return;
201 }
202 int pos = className.indexOf('.');
203 if (pos < 0) {
204 insertNode(className, refTy);
205 } else {
206 String head = className.substring(0, pos);
207 String tail = className.substring(pos + 1);
208 ClassTreeNode child = insertNode(head, null);
209 child.addClass(tail, refTy);
210 }
211 }
212
213 private ClassTreeNode insertNode(String name, ReferenceType refTy) {
214 for (int i = 0; i < getChildCount(); i++) {
215 ClassTreeNode child = (ClassTreeNode)getChildAt(i);
216 int cmp = name.compareTo(child.toString());
217 if (cmp == 0) {
218 // like-named node already exists
219 return child;
220 } else if (cmp < 0) {
221 // insert new node before the child
222 ClassTreeNode newChild = new ClassTreeNode(name, refTy);
223 treeModel.insertNodeInto(newChild, this, i);
224 return newChild;
225 }
226 }
227 // insert new node after last child
228 ClassTreeNode newChild = new ClassTreeNode(name, refTy);
229 treeModel.insertNodeInto(newChild, this, getChildCount());
230 return newChild;
231 }
232
233 public void removeClass(String className) {
234 if (className.equals("")) {
235 return;
236 }
237 int pos = className.indexOf('.');
238 if (pos < 0) {
239 ClassTreeNode child = findNode(className);
240 if (!isPackage()) {
241 treeModel.removeNodeFromParent(child);
242 }
243 } else {
244 String head = className.substring(0, pos);
245 String tail = className.substring(pos + 1);
246 ClassTreeNode child = findNode(head);
247 child.removeClass(tail);
248 if (isPackage() && child.getChildCount() < 1) {
249 // Prune non-leaf nodes with no children.
250 treeModel.removeNodeFromParent(child);
251 }
252 }
253 }
254
255 private ClassTreeNode findNode(String name) {
256 for (int i = 0; i < getChildCount(); i++) {
257 ClassTreeNode child = (ClassTreeNode)getChildAt(i);
258 int cmp = name.compareTo(child.toString());
259 if (cmp == 0) {
260 return child;
261 } else if (cmp > 0) {
262 // not found, since children are sorted
263 return null;
264 }
265 }
266 return null;
267 }
268
269 }
270
271}