source: trunk/gli/src/org/greenstone/gatherer/util/TreeModelTest.java@ 8213

Last change on this file since 8213 was 6318, checked in by jmt12, 21 years ago

Changed JButtons for GLIButtons, which know whether they should paint their background depending on what platform they are run on, and finished keyboard shortcuts

  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37package org.greenstone.gatherer.util;
38
39import java.awt.*;
40import java.awt.event.*;
41import java.io.*;
42import java.util.*;
43import javax.swing.*;
44import javax.swing.tree.*;
45import org.greenstone.gatherer.gui.GLIButton;
46import org.greenstone.gatherer.util.DefaultSynchronizedTreeNode;
47import org.greenstone.gatherer.util.SynchronizedTreeModel;
48import org.greenstone.gatherer.util.SynchronizedTreeNode;
49
50public class TreeModelTest
51 extends JFrame {
52
53 /** Testing - test frame size. */
54 static final private Dimension SIZE = new Dimension(400,400);
55
56 /** Testing - should a debug file be written. */
57 static private boolean debug = false;
58
59 /** Testing - debug output stream. */
60 static private FileOutputStream output = null;
61
62 /** Testing - write a message to the debug file. */
63 static void debug(String message) {
64 if(debug) {
65 try {
66 if(output == null) {
67 output = new FileOutputStream(new File("debug.txt"));
68 }
69 output.write(message.getBytes());
70 output.flush();
71 }
72 catch (Exception error) {
73 error.printStackTrace();
74 }
75 }
76 }
77
78 /** Testing - usage message. */
79 static void printUsage() {
80 System.out.println("Usage: java Test3 [-safe] [-debug]");
81 System.out.println(" safe - use SynchronizedTreeModel");
82 System.out.println(" debug - write debug messages to debug.txt file\n");
83 System.out.println("Actions:");
84 System.out.println(" 'Add Node' - Adds a new node to the selected node. Since this happens on the AWTEvent Thread it should always be safe.");
85 System.out.println(" 'Remove Node' - Removes the selected node. Since this happens on the AWTEvent Thread it should always be safe.");
86 System.out.println(" 'Preset Structure' - Generates a small preset structure on a seperate (dangerous) thread.");
87 System.out.println(" 'Dangerous' - The ultimate test. Hammers the model with incessant random mutations from a separate thread.");
88 System.exit(0);
89 }
90 /** Testing - creates a frame containing a JTree backed by either a normal DefaultTreeModel or a SynchronizedTreeModel depending on arguments. There are also several actions you can perform by clicking on buttons. */
91 static public void main(String[] args) {
92 boolean safe = false;
93 if(args.length <= 2) {
94 for(int i = 0; i < args.length; i++) {
95 String arg = args[i];
96 if(arg.equalsIgnoreCase("-safe")) {
97 safe = true;
98 }
99 else if(arg.equalsIgnoreCase("-debug")) {
100 debug = true;
101 }
102 else {
103 printUsage();
104 }
105 }
106 }
107 else {
108 printUsage();
109 }
110 new TreeModelTest(safe);
111 }
112
113 /** Testing - a dangerous thread which hammers the mutable tree model. */
114 private DangerousTask task;
115
116 /** Testing - a dangerous thread which builds a preset structure. */
117 private DangerousTask preset_task;
118
119 /** Testing - the tree model, which may be a SynchronizedTreeModel. */
120 private DefaultTreeModel model;
121
122 /** Testing - a button for toggling the dangerous thread on and off. */
123 private JToggleButton dangerous_button;
124
125 /** Testing - the tree used during testing. */
126 private JTree tree;
127
128 TreeModelTest(boolean safe) {
129 super("Testing");
130 setDefaultCloseOperation(EXIT_ON_CLOSE);
131 setSize(SIZE);
132 JPanel content_panel = (JPanel) getContentPane();
133
134 // Creation
135 task = new DangerousTask(false);
136 preset_task = new DangerousTask(true);
137
138 if(safe) {
139 model = new SynchronizedTreeModel(new DefaultSynchronizedTreeNode("Root"));
140 }
141 else {
142 model = new DefaultTreeModel(new DefaultMutableTreeNode("Root"));
143 }
144
145 tree = new JTree(model);
146
147 JPanel button_panel = new JPanel();
148 JButton add_button = new GLIButton("Add Node");
149 add_button.setMnemonic(KeyEvent.VK_A);
150 dangerous_button = new JToggleButton("Dangerous!");
151 dangerous_button.setSelected(false);
152 JButton remove_button = new GLIButton("Remove Node");
153 remove_button.setMnemonic(KeyEvent.VK_R);
154 JButton preset_button = new GLIButton("Preset Structure");
155 preset_button.setMnemonic(KeyEvent.VK_P);
156
157 // Connection
158 add_button.addActionListener(new AddListener());
159 dangerous_button.addActionListener(new ActionListener() {
160 public void actionPerformed(ActionEvent event) {
161 if(dangerous_button.isSelected()) {
162 task.start();
163 }
164 else {
165 task.exit = true;
166 }
167 }
168 });
169 remove_button.addActionListener(new ActionListener() {
170 public void actionPerformed(ActionEvent event) {
171 ///ystem.err.println("*** Start Remove ***");
172 // Get the selected node
173 TreePath selected_path = tree.getSelectionPath();
174 if(selected_path != null) {
175 DefaultMutableTreeNode old_child = (DefaultMutableTreeNode) selected_path.getLastPathComponent();
176 if(!old_child.isRoot()) {
177 // Remove node.
178 model.removeNodeFromParent(old_child);
179 }
180 }
181 ///ystem.err.println("*** End Remove ***\n");
182 }
183 });
184 preset_button.addActionListener(new ActionListener() {
185 public void actionPerformed(ActionEvent event) {
186 preset_task.start();
187 }
188 });
189
190 // Layout
191 button_panel.setLayout(new GridLayout(2,2));
192 button_panel.add(add_button);
193 button_panel.add(remove_button);
194 button_panel.add(preset_button);
195 button_panel.add(dangerous_button);
196
197 content_panel.setLayout(new BorderLayout());
198 content_panel.add(new JScrollPane(tree), BorderLayout.CENTER);
199 content_panel.add(button_panel, BorderLayout.SOUTH);
200
201 // Display
202 Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize();
203 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
204 show();
205 }
206
207 private class AddListener
208 implements ActionListener {
209 public void actionPerformed(ActionEvent event) {
210 ///ystem.err.println("*** Start Add ***");
211 // Get the selected node
212 TreePath selected_path = tree.getSelectionPath();
213 if(selected_path != null) {
214 DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selected_path.getLastPathComponent();
215 // Create a new node
216 MutableTreeNode new_child = new DefaultSynchronizedTreeNode( String.valueOf(System.currentTimeMillis()));
217 // Insert node.
218 model.insertNodeInto(new_child, parent, parent.getChildCount());
219 }
220 ///ystem.err.println("*** End Add ***\n");
221 }
222 }
223
224 private class DangerousTask
225 extends Thread {
226
227 private boolean exit = false;
228 private boolean preset = false;
229
230 DangerousTask(boolean preset) {
231 this.preset = preset;
232 }
233
234 public void run() {
235 if(preset) {
236 DefaultMutableTreeNode root = (DefaultMutableTreeNode) model.getRoot();
237 MutableTreeNode alpha = new DefaultSynchronizedTreeNode("Alpha");
238 MutableTreeNode beta = new DefaultSynchronizedTreeNode("Beta");
239 MutableTreeNode delta = new DefaultSynchronizedTreeNode("Delta");
240 MutableTreeNode gamma = new DefaultSynchronizedTreeNode("Gamma");
241 MutableTreeNode epsilon = new DefaultSynchronizedTreeNode("Epsilon");
242 MutableTreeNode rho = new DefaultSynchronizedTreeNode("Rho");
243 MutableTreeNode pi = new DefaultSynchronizedTreeNode("Pi");
244 MutableTreeNode xhi = new DefaultSynchronizedTreeNode("Xhi");
245 MutableTreeNode kappa = new DefaultSynchronizedTreeNode("Kappa");
246 MutableTreeNode lambda = new DefaultSynchronizedTreeNode("Lambda");
247 MutableTreeNode omega = new DefaultSynchronizedTreeNode("Omega");MutableTreeNode tau = new DefaultSynchronizedTreeNode("Tau");
248
249 model.insertNodeInto(alpha, root, 0);
250 model.insertNodeInto(omega, root, 1);
251 model.insertNodeInto(pi, root, 1);
252
253 model.insertNodeInto(beta, alpha, 0);
254 model.insertNodeInto(delta, beta, 0);
255 model.insertNodeInto(epsilon, delta, 0);
256 model.insertNodeInto(gamma, delta, 0);
257 model.insertNodeInto(rho, pi, 0);
258 model.insertNodeInto(xhi, alpha, 0);
259 model.insertNodeInto(kappa, root, 1);
260
261 debug("Root has: " + model.getChildCount(model.getRoot()));
262 }
263 else {
264 exit = false;
265 while(!exit) {
266 // Find a random node
267 DefaultMutableTreeNode current = (DefaultMutableTreeNode) model.getRoot();
268 while(Math.random() > 0.3 && model.getChildCount(current) > 0) {
269 int index = (int)(Math.random() * (model.getChildCount(current) - 1));
270 current = (DefaultMutableTreeNode) model.getChild(current, index);
271 }
272 // Either add or remove a random node.
273 if(Math.random() > 0.9) {
274 ///ystem.err.println("<< Expand >>");
275 TreePath path = new TreePath(model.getPathToRoot(current));
276 tree.expandPath(path);
277 }
278 else if(Math.random() > 0.4 || current.isRoot()) {
279 if(model.getChildCount(current) < 25) {
280 ///ystem.err.println("<<< Add >>>");
281 // Add a new node
282 MutableTreeNode new_child = new DefaultSynchronizedTreeNode(String.valueOf(System.currentTimeMillis()));
283 // Insert node.
284 model.insertNodeInto(new_child, current, model. getChildCount(current));
285 ///ystem.err.println("<<< >>>\n");
286 }
287 }
288 else {
289 ///ystem.err.println("<<< Remove >>>");
290 // Remove node.
291 model.removeNodeFromParent(current);
292 ///ystem.err.println("<<< >>>\n");
293 }
294
295 // Wait some random minute amount of time
296 try {
297 synchronized(this) {
298 wait((int)(5 * Math.random()) + 1);
299 }
300 } catch (Exception exception) {
301 exception.printStackTrace();
302 }
303 }
304 }
305 }
306 }
307}
Note: See TracBrowser for help on using the repository browser.