001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.webapp.admin;
019:
020: import java.io.Serializable;
021: import java.util.ArrayList;
022:
023: /**
024: * <p>An individual node of a tree control represented by an instance of
025: * <code>TreeControl</code>, and rendered by an instance of
026: * <code>TreeControlTag</code>.</p>
027: *
028: * @author Jazmin Jonson
029: * @author Craig R. McClanahan
030: * @version $Revision: 516448 $ $Date: 2007-03-09 17:25:47 +0100 (Fri, 09 Mar 2007) $
031: */
032:
033: public class TreeControlNode implements Serializable {
034: private static final long serialVersionUID = 1;
035:
036: // ----------------------------------------------------------- Constructors
037:
038: /**
039: * Construct a new TreeControlNode with the specified parameters.
040: *
041: * @param name Internal name of this node (must be unique within
042: * the entire tree)
043: * @param icon Pathname of the image file for the icon to be displayed
044: * when this node is visible, relative to the image directory
045: * for our images
046: * @param label The label that will be displayed to the user if
047: * this node is visible
048: * @param action The hyperlink to be selected if the user
049: * selects this node, or <code>null</code> if this node's label should
050: * not be a hyperlink
051: * @param target The window target in which the <code>action</code>
052: * hyperlink's results will be displayed, or <code>null</code> for
053: * the current window
054: * @param expanded Should this node be expanded?
055: * @param domain Identifier for the kind of node.
056: */
057: public TreeControlNode(String name, String icon, String label,
058: String action, String target, boolean expanded,
059: String domain) {
060: this (name, icon, label, action, target, expanded, domain, null,
061: false);
062: }
063:
064: /**
065: * Construct a new TreeControlNode with the specified parameters.
066: *
067: * @param name Internal name of this node (must be unique within
068: * the entire tree)
069: * @param icon Pathname of the image file for the icon to be displayed
070: * when this node is visible, relative to the image directory
071: * for our images
072: * @param label The label that will be displayed to the user if
073: * this node is visible
074: * @param action The hyperlink to be selected if the user
075: * selects this node, or <code>null</code> if this node's label should
076: * not be a hyperlink
077: * @param target The window target in which the <code>action</code>
078: * hyperlink's results will be displayed, or <code>null</code> for
079: * the current window
080: * @param expanded Should this node be expanded?
081: * @param domain Identifier for the kind of node.
082: * @param CSSClass The css class to apply to the node
083: */
084: public TreeControlNode(String name, String icon, String label,
085: String action, String target, boolean expanded,
086: String domain, String CSSClass) {
087: this (name, icon, label, action, target, expanded, domain,
088: CSSClass, false);
089: }
090:
091: /**
092: * Construct a new TreeControlNode with the specified parameters.
093: *
094: * @param name Internal name of this node (must be unique within
095: * the entire tree)
096: * @param icon Pathname of the image file for the icon to be displayed
097: * when this node is visible, relative to the image directory
098: * for our images
099: * @param label The label that will be displayed to the user if
100: * this node is visible
101: * @param action The hyperlink to be selected if the user
102: * selects this node, or <code>null</code> if this node's label should
103: * not be a hyperlink
104: * @param target The window target in which the <code>action</code>
105: * hyperlink's results will be displayed, or <code>null</code> for
106: * the current window
107: * @param expanded Should this node be expanded?
108: * @param domain Identifier for the kind of node.
109: * @param CSSClass The css class to apply to the node
110: * @param lazy Is this node's children lazy loaded?
111: */
112: public TreeControlNode(String name, String icon, String label,
113: String action, String target, boolean expanded,
114: String domain, String CSSClass, boolean lazy) {
115:
116: super ();
117: this .name = name;
118: this .icon = icon;
119: this .label = label;
120: this .action = action;
121: this .target = target;
122: this .expanded = expanded;
123: this .domain = domain;
124: this .CSSClass = CSSClass;
125: this .lazy = lazy;
126: this .loaded = false;
127: }
128:
129: // ----------------------------------------------------- Instance Variables
130:
131: /**
132: * The set of child <code>TreeControlNodes</code> for this node, in the
133: * order that they should be displayed.
134: */
135: protected ArrayList children = new ArrayList();
136:
137: // ------------------------------------------------------------- Properties
138:
139: /**
140: * The hyperlink to which control will be directed if this node
141: * is selected by the user.
142: */
143: protected String action = null;
144:
145: public String getAction() {
146: return (this .action);
147: }
148:
149: /**
150: * The domain of this node.
151: */
152: protected String domain = null;
153:
154: public String getDomain() {
155: return (this .domain);
156: }
157:
158: /**
159: * Is this node currently expanded?
160: */
161: protected boolean expanded = false;
162:
163: public boolean isExpanded() {
164: return (this .expanded);
165: }
166:
167: public void setExpanded(boolean expanded) {
168: this .expanded = expanded;
169: }
170:
171: /**
172: * The pathname to the icon file displayed when this node is visible,
173: * relative to the image directory for our images.
174: */
175: protected String icon = null;
176:
177: public String getIcon() {
178: return (this .icon);
179: }
180:
181: /**
182: * The label that will be displayed when this node is visible.
183: */
184: protected String label = null;
185:
186: public String getLabel() {
187: return (this .label);
188: }
189:
190: /**
191: * The label that will be displayed when this node is visible.
192: */
193: protected String title = null;
194:
195: public String getTitle() {
196: return (this .title);
197: }
198:
199: public void setTitle(String title) {
200: this .title = title;
201: }
202:
203: public void setLabel(String label) {
204: this .label = label;
205: }
206:
207: /**
208: * Is this the last node in the set of children for our parent node?
209: */
210: protected boolean last = false;
211:
212: public boolean isLast() {
213: return (this .last);
214: }
215:
216: void setLast(boolean last) {
217: this .last = last;
218: }
219:
220: protected boolean lazy = false;
221:
222: public boolean isLazy() {
223: return (this .lazy);
224: }
225:
226: /**
227: * Is this a "leaf" node (i.e. one with no children)?
228: */
229: protected boolean leaf = true;
230:
231: public boolean isLeaf() {
232: if (lazy) {
233: return leaf;
234: } else {
235: synchronized (children) {
236: return (children.size() < 1);
237: }
238: }
239: }
240:
241: public void setLeaf(boolean leaf) {
242: this .leaf = leaf;
243: }
244:
245: protected boolean loaded = false;
246:
247: public boolean isLoaded() {
248: return (this .loaded);
249: }
250:
251: public void setLoaded(boolean loaded) {
252: this .loaded = loaded;
253: }
254:
255: /**
256: * The unique (within the entire tree) name of this node.
257: */
258: protected String name = null;
259:
260: public String getName() {
261: return (this .name);
262: }
263:
264: /**
265: * The parent node of this node, or <code>null</code> if this
266: * is the root node.
267: */
268: protected TreeControlNode parent = null;
269:
270: public TreeControlNode getParent() {
271: return (this .parent);
272: }
273:
274: void setParent(TreeControlNode parent) {
275: this .parent = parent;
276: if (parent == null)
277: width = 1;
278: else
279: width = parent.getWidth() + 1;
280: }
281:
282: /**
283: * Is this node currently selected?
284: */
285: protected boolean selected = false;
286:
287: public boolean isSelected() {
288: return (this .selected);
289: }
290:
291: public void setSelected(boolean selected) {
292: this .selected = selected;
293: }
294:
295: /**
296: * The window target for the hyperlink identified by the
297: * <code>action</code> property, if this node is selected
298: * by the user.
299: */
300: protected String target = null;
301:
302: public String getTarget() {
303: return (this .target);
304: }
305:
306: /**
307: * The <code>TreeControl</code> instance representing the
308: * entire tree.
309: */
310: protected TreeControl tree = null;
311:
312: public TreeControl getTree() {
313: return (this .tree);
314: }
315:
316: void setTree(TreeControl tree) {
317: this .tree = tree;
318: }
319:
320: /**
321: * The display width necessary to display this item (if it is visible).
322: * If this item is not visible, the calculated width will be that of our
323: * most immediately visible parent.
324: */
325: protected int width = 0;
326:
327: public int getWidth() {
328: return (this .width);
329: }
330:
331: protected String CSSClass;
332:
333: /**
334: * @return Returns the cSSClass.
335: */
336: public String getCSSClass() {
337: return CSSClass;
338: }
339:
340: /**
341: * @param class1 The cSSClass to set.
342: */
343: public void setCSSClass(String CSSClass) {
344: this .CSSClass = CSSClass;
345: }
346:
347: protected boolean expandWhenClicked = false;
348:
349: public boolean isExpandWhenClicked() {
350: return expandWhenClicked;
351: }
352:
353: public void setExpandWhenClicked(boolean expandWhenClicked) {
354: this .expandWhenClicked = expandWhenClicked;
355: }
356:
357: // --------------------------------------------------------- Public Methods
358:
359: /**
360: * Add a new child node to the end of the list.
361: *
362: * @param child The new child node
363: *
364: * @exception IllegalArgumentException if the name of the new child
365: * node is not unique
366: */
367: public void addChild(TreeControlNode child)
368: throws IllegalArgumentException {
369:
370: tree.addNode(child);
371: child.setParent(this );
372: synchronized (children) {
373: int n = children.size();
374: if (n > 0) {
375: TreeControlNode node = (TreeControlNode) children
376: .get(n - 1);
377: node.setLast(false);
378: }
379: child.setLast(true);
380: children.add(child);
381: }
382:
383: }
384:
385: /**
386: * Add a new child node at the specified position in the child list.
387: *
388: * @param offset Zero-relative offset at which the new node
389: * should be inserted
390: * @param child The new child node
391: *
392: * @exception IllegalArgumentException if the name of the new child
393: * node is not unique
394: */
395: public void addChild(int offset, TreeControlNode child)
396: throws IllegalArgumentException {
397:
398: tree.addNode(child);
399: child.setParent(this );
400: synchronized (children) {
401: children.add(offset, child);
402: }
403:
404: }
405:
406: /**
407: * Return the set of child nodes for this node.
408: */
409: public TreeControlNode[] findChildren() {
410:
411: synchronized (children) {
412: TreeControlNode results[] = new TreeControlNode[children
413: .size()];
414: return ((TreeControlNode[]) children.toArray(results));
415: }
416:
417: }
418:
419: /**
420: * Remove this node from the tree.
421: */
422: public void remove() {
423:
424: if (tree != null) {
425: tree.removeNode(this );
426: }
427:
428: }
429:
430: /**
431: * Remove the child node (and all children of that child) at the
432: * specified position in the child list.
433: *
434: * @param offset Zero-relative offset at which the existing
435: * node should be removed
436: */
437: public void removeChild(int offset) {
438:
439: synchronized (children) {
440: TreeControlNode child = (TreeControlNode) children
441: .get(offset);
442: tree.removeNode(child);
443: child.setParent(null);
444: children.remove(offset);
445: }
446:
447: }
448:
449: // -------------------------------------------------------- Package Methods
450:
451: /**
452: * Remove the specified child node. It is assumed that all of the
453: * children of this child node have already been removed.
454: *
455: * @param child Child node to be removed
456: */
457: void removeChild(TreeControlNode child) {
458:
459: if (child == null) {
460: return;
461: }
462: synchronized (children) {
463: int n = children.size();
464: for (int i = 0; i < n; i++) {
465: if (child == (TreeControlNode) children.get(i)) {
466: children.remove(i);
467: return;
468: }
469: }
470: }
471:
472: }
473: }
|