blob: 26f2411dc5802dc1b9326924f5fd158963151552 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1997-1998 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/*
33 */
34
35import javax.swing.tree.DefaultMutableTreeNode;
36import java.awt.Color;
37import java.awt.Font;
38import java.awt.Toolkit;
39import java.util.Random;
40
41/**
42 * DynamicTreeNode illustrates one of the possible ways in which dynamic
43 * loading can be used in tree. The basic premise behind this is that
44 * getChildCount() will be messaged from JTreeModel before any children
45 * are asked for. So, the first time getChildCount() is issued the
46 * children are loaded.<p>
47 * It should be noted that isLeaf will also be messaged from the model.
48 * The default behavior of TreeNode is to message getChildCount to
49 * determine this. As such, isLeaf is subclassed to always return false.<p>
50 * There are others ways this could be accomplished as well. Instead of
51 * subclassing TreeNode you could subclass JTreeModel and do the same
52 * thing in getChildCount(). Or, if you aren't using TreeNode you could
53 * write your own TreeModel implementation.
54 * Another solution would be to listen for TreeNodeExpansion events and
55 * the first time a node has been expanded post the appropriate insertion
56 * events. I would not recommend this approach though, the other two
57 * are much simpler and cleaner (and are faster from the perspective of
58 * how tree deals with it).
59 *
60 * NOTE: getAllowsChildren() can be messaged before getChildCount().
61 * For this example the nodes always allow children, so it isn't
62 * a problem, but if you do support true leaf nodes you may want
63 * to check for loading in getAllowsChildren too.
64 *
65 * @author Scott Violet
66 */
67
68public class DynamicTreeNode extends DefaultMutableTreeNode
69{
70 // Class stuff.
71 /** Number of names. */
72 static protected float nameCount;
73
74 /** Names to use for children. */
75 static protected String[] names;
76
77 /** Potential fonts used to draw with. */
78 static protected Font[] fonts;
79
80 /** Used to generate the names. */
81 static protected Random nameGen;
82
83 /** Number of children to create for each node. */
84 static protected final int DefaultChildrenCount = 7;
85
86 static {
87 String[] fontNames;
88
89 try {
90 fontNames = Toolkit.getDefaultToolkit().getFontList();
91 } catch (Exception e) {
92 fontNames = null;
93 }
94 if(fontNames == null || fontNames.length == 0) {
95 names = new String[] {"Mark Andrews", "Tom Ball", "Alan Chung",
96 "Rob Davis", "Jeff Dinkins",
97 "Amy Fowler", "James Gosling",
98 "David Karlton", "Dave Kloba",
99 "Dave Moore", "Hans Muller",
100 "Rick Levenson", "Tim Prinzing",
101 "Chester Rose", "Ray Ryan",
102 "Georges Saab", "Scott Violet",
103 "Kathy Walrath", "Arnaud Weber" };
104 }
105 else {
106 /* Create the Fonts, creating fonts is slow, much better to
107 do it once. */
108 int fontSize = 12;
109
110 names = fontNames;
111 fonts = new Font[names.length];
112 for(int counter = 0, maxCounter = names.length;
113 counter < maxCounter; counter++) {
114 try {
115 fonts[counter] = new Font(fontNames[counter], 0, fontSize);
116 }
117 catch (Exception e) {
118 fonts[counter] = null;
119 }
120 fontSize = ((fontSize + 2 - 12) % 12) + 12;
121 }
122 }
123 nameCount = (float)names.length;
124 nameGen = new Random(System.currentTimeMillis());
125 }
126
127
128 /** Have the children of this node been loaded yet? */
129 protected boolean hasLoaded;
130
131 /**
132 * Constructs a new DynamicTreeNode instance with o as the user
133 * object.
134 */
135 public DynamicTreeNode(Object o) {
136 super(o);
137 }
138
139 public boolean isLeaf() {
140 return false;
141 }
142
143 /**
144 * If hasLoaded is false, meaning the children have not yet been
145 * loaded, loadChildren is messaged and super is messaged for
146 * the return value.
147 */
148 public int getChildCount() {
149 if(!hasLoaded) {
150 loadChildren();
151 }
152 return super.getChildCount();
153 }
154
155 /**
156 * Messaged the first time getChildCount is messaged. Creates
157 * children with random names from names.
158 */
159 protected void loadChildren() {
160 DynamicTreeNode newNode;
161 Font font;
162 int randomIndex;
163 SampleData data;
164
165 for(int counter = 0; counter < DynamicTreeNode.DefaultChildrenCount;
166 counter++) {
167 randomIndex = (int)(nameGen.nextFloat() * nameCount);
168 if(fonts != null)
169 font = fonts[randomIndex];
170 else
171 font = null;
172 if(counter % 2 == 0)
173 data = new SampleData(font, Color.red, names[randomIndex]);
174 else
175 data = new SampleData(font, Color.blue, names[randomIndex]);
176 newNode = new DynamicTreeNode(data);
177 /* Don't use add() here, add calls insert(newNode, getChildCount())
178 so if you want to use add, just be sure to set hasLoaded = true
179 first. */
180 insert(newNode, counter);
181 }
182 /* This node has now been loaded, mark it so. */
183 hasLoaded = true;
184 }
185}