KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > google > gwt > user > client > ui > TreeItem


1 /*
2  * Copyright 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package com.google.gwt.user.client.ui;
17
18 import com.google.gwt.user.client.DOM;
19 import com.google.gwt.user.client.Element;
20
21 import java.util.ArrayList JavaDoc;
22 import java.util.List JavaDoc;
23
24 /**
25  * An item that can be contained within a
26  * {@link com.google.gwt.user.client.ui.Tree}.
27  * <p>
28  * <h3>Example</h3>
29  * {@example com.google.gwt.examples.TreeExample}
30  * </p>
31  */

32 public class TreeItem extends UIObject implements HasHTML {
33
34   /**
35    * <code>Panel</code> containing the <code>Widget</code> associated with
36    * the current tree item.
37    */

38   class ContentPanel extends SimplePanel {
39     private ContentPanel(Element e) {
40       super(e);
41     }
42
43     /**
44      * Gets the <code>TreeItem</code> associated with this
45      * <code>ContentPanel</code> for testing purposes.
46      *
47      * @return the tree item
48      */

49     TreeItem getTreeItem() {
50       return TreeItem.this;
51     }
52
53     /**
54      * Prevent anyone from stealing a tree item's content pane.
55      *
56      * @see com.google.gwt.user.client.ui.Widget#setParent(com.google.gwt.user.client.ui.Widget)
57      */

58     void setParent(Widget widget) {
59       throw new UnsupportedOperationException JavaDoc(
60         "Cannot directly setParent on a WidgetTreeItem's ContentPanel");
61     }
62
63     void treeSetParent(Widget widget) {
64       super.setParent(widget);
65     }
66   }
67
68   private ArrayList JavaDoc children = new ArrayList JavaDoc();
69   private ContentPanel contentPanel;
70   private Element itemTable, contentElem, childSpanElem;
71   private final Image statusImage = new Image();
72   private boolean open;
73   private TreeItem parent;
74   private boolean selected;
75   private Object JavaDoc userObject;
76   private Tree tree;
77
78   /**
79    * Creates an empty tree item.
80    */

81   public TreeItem() {
82     setElement(DOM.createDiv());
83     itemTable = DOM.createTable();
84     contentElem = DOM.createSpan();
85     childSpanElem = DOM.createSpan();
86
87     // Uses the following Element hierarchy:
88
// <div (handle)>
89
// <table (itemElem)>
90
// <tr>
91
// <td><img (imgElem)/></td>
92
// <td><span (contents)/></td>
93
// </tr>
94
// </table>
95
// <span (childSpanElem)> children </span>
96
// </div>
97

98     Element tbody = DOM.createTBody(), tr = DOM.createTR();
99     Element tdImg = DOM.createTD(), tdContent = DOM.createTD();
100     DOM.appendChild(itemTable, tbody);
101     DOM.appendChild(tbody, tr);
102     DOM.appendChild(tr, tdImg);
103     DOM.appendChild(tr, tdContent);
104     DOM.setStyleAttribute(tdImg, "verticalAlign", "middle");
105     DOM.setStyleAttribute(tdContent, "verticalAlign", "middle");
106
107     DOM.appendChild(getElement(), itemTable);
108     DOM.appendChild(getElement(), childSpanElem);
109     DOM.appendChild(tdImg, statusImage.getElement());
110     DOM.appendChild(tdContent, contentElem);
111
112     DOM.setStyleAttribute(contentElem, "display", "inline");
113     DOM.setStyleAttribute(getElement(), "whiteSpace", "nowrap");
114     DOM.setStyleAttribute(childSpanElem, "whiteSpace", "nowrap");
115     setStyleName(contentElem, "gwt-TreeItem", true);
116   }
117
118   /**
119    * Constructs a tree item with the given HTML.
120    *
121    * @param html the item's HTML
122    */

123   public TreeItem(String JavaDoc html) {
124     this();
125     setHTML(html);
126   }
127
128   /**
129    * Constructs a tree item with the given <code>Widget</code>.
130    *
131    * @param widget the item's widget
132    */

133   public TreeItem(Widget widget) {
134     this();
135     setWidget(widget);
136   }
137
138   /**
139    * Adds a child tree item containing the specified text.
140    *
141    * @param itemText the text to be added
142    * @return the item that was added
143    */

144   public TreeItem addItem(String JavaDoc itemText) {
145     TreeItem ret = new TreeItem(itemText);
146     addItem(ret);
147     return ret;
148   }
149
150   /**
151    * Adds another item as a child to this one.
152    *
153    * @param item the item to be added
154    */

155
156   public void addItem(TreeItem item) {
157     // If this element already belongs to a tree or tree item, it should be
158
// removed.
159
if ((item.getParentItem() != null) || (item.getTree() != null)) {
160       item.remove();
161     }
162     item.setTree(tree);
163     item.setParentItem(this);
164     children.add(item);
165     DOM.setStyleAttribute(item.getElement(), "marginLeft", "16px");
166     DOM.appendChild(childSpanElem, item.getElement());
167     if (children.size() == 1) {
168       updateState();
169     }
170   }
171
172   /**
173    * Adds a child tree item containing the specified widget.
174    *
175    * @param widget the widget to be added
176    * @return the item that was added
177    */

178   public TreeItem addItem(Widget widget) {
179     TreeItem ret = new TreeItem(widget);
180     addItem(ret);
181     return ret;
182   }
183
184   /**
185    * Gets the child at the specified index.
186    *
187    * @param index the index to be retrieved
188    * @return the item at that index
189    */

190
191   public TreeItem getChild(int index) {
192     if ((index < 0) || (index >= children.size())) {
193       return null;
194     }
195
196     return (TreeItem) children.get(index);
197   }
198
199   /**
200    * Gets the number of children contained in this item.
201    *
202    * @return this item's child count.
203    */

204
205   public int getChildCount() {
206     return children.size();
207   }
208
209   /**
210    * Gets the index of the specified child item.
211    *
212    * @param child the child item to be found
213    * @return the child's index, or <code>-1</code> if none is found
214    */

215
216   public int getChildIndex(TreeItem child) {
217     return children.indexOf(child);
218   }
219
220   public String JavaDoc getHTML() {
221     return DOM.getInnerHTML(contentElem);
222   }
223
224   /**
225    * Gets this item's parent.
226    *
227    * @return the parent item
228    */

229   public TreeItem getParentItem() {
230     return parent;
231   }
232
233   /**
234    * Gets whether this item's children are displayed.
235    *
236    * @return <code>true</code> if the item is open
237    */

238   public boolean getState() {
239     return open;
240   }
241
242   public String JavaDoc getText() {
243     return DOM.getInnerText(contentElem);
244   }
245
246   /**
247    * Gets the tree that contains this item.
248    *
249    * @return the containing tree
250    */

251   public final Tree getTree() {
252     return tree;
253   }
254
255   /**
256    * Gets the user-defined object associated with this item.
257    *
258    * @return the item's user-defined object
259    */

260   public Object JavaDoc getUserObject() {
261     return userObject;
262   }
263
264   /**
265    * Gets the <code>Widget</code> associated with this tree item.
266    *
267    * @return the widget
268    */

269   public Widget getWidget() {
270     if (contentPanel == null) {
271       return null;
272     }
273     return contentPanel.getWidget();
274   }
275
276   /**
277    * Determines whether this item is currently selected.
278    *
279    * @return <code>true</code> if it is selected
280    */

281   public boolean isSelected() {
282     return selected;
283   }
284
285   /**
286    * Removes this item from its tree.
287    */

288   public void remove() {
289     if (parent != null) {
290       // If this item has a parent, remove self from it.
291
parent.removeItem(this);
292     } else if (tree != null) {
293       // If the item has no parent, but is in the Tree, it must be a top-level
294
// element.
295
tree.removeItem(this);
296     }
297   }
298
299   /**
300    * Removes one of this item's children.
301    *
302    * @param item the item to be removed
303    */

304
305   public void removeItem(TreeItem item) {
306     if (!children.contains(item)) {
307       return;
308     }
309     // Update Item state.
310
item.setTree(null);
311     item.setParentItem(null);
312     
313     children.remove(item);
314     DOM.removeChild(childSpanElem, item.getElement());
315
316     if (children.size() == 0) {
317       updateState();
318     }
319   }
320
321   /**
322    * Removes all of this item's children.
323    */

324   public void removeItems() {
325     while (getChildCount() > 0) {
326       removeItem(getChild(0));
327     }
328   }
329
330   public void setHTML(String JavaDoc html) {
331     clearContentPanel();
332     DOM.setInnerHTML(contentElem, html);
333   }
334
335   /**
336    * Selects or deselects this item.
337    *
338    * @param selected <code>true</code> to select the item, <code>false</code>
339    * to deselect it
340    */

341   public void setSelected(boolean selected) {
342     if (this.selected == selected) {
343       return;
344     }
345     this.selected = selected;
346     setStyleName(contentElem, "gwt-TreeItem-selected", selected);
347   }
348
349   /**
350    * Sets whether this item's children are displayed.
351    *
352    * @param open whether the item is open
353    */

354   public void setState(boolean open) {
355     setState(open, true);
356   }
357
358   /**
359    * Sets whether this item's children are displayed.
360    *
361    * @param open whether the item is open
362    * @param fireEvents <code>true</code> to allow open/close events to be
363    * fired
364    */

365   public void setState(boolean open, boolean fireEvents) {
366     if (open && children.size() == 0) {
367       return;
368     }
369
370     this.open = open;
371     updateState();
372
373     if (fireEvents && tree != null) {
374       tree.fireStateChanged(this);
375     }
376   }
377
378   public void setText(String JavaDoc text) {
379     clearContentPanel();
380     DOM.setInnerText(contentElem, text);
381   }
382
383   /**
384    * Sets the user-defined object associated with this item.
385    *
386    * @param userObj the item's user-defined object
387    */

388   public void setUserObject(Object JavaDoc userObj) {
389     userObject = userObj;
390   }
391
392   /**
393    * Sets the current widget. Any existing child widget will be removed.
394    * @param widget Widget to set
395    */

396   public void setWidget(Widget widget) {
397     ensureContentPanel();
398     contentPanel.setWidget(widget);
399   }
400
401   /**
402    * Returns the widget, if any, that should be focused on if this TreeItem is
403    * selected.
404    *
405    * @return widget to be focused.
406    */

407   protected HasFocus getFocusableWidget() {
408     Widget widget = getWidget();
409     if (widget instanceof HasFocus) {
410       return (HasFocus) widget;
411     } else {
412       return null;
413     }
414   }
415
416   void addTreeItems(List JavaDoc accum) {
417     for (int i = 0; i < children.size(); i++) {
418       TreeItem item = (TreeItem) children.get(i);
419       accum.add(item);
420       item.addTreeItems(accum);
421     }
422   }
423
424   ArrayList JavaDoc getChildren() {
425     return children;
426   }
427
428   Element getContentElem() {
429     return contentElem;
430   }
431
432   int getContentHeight() {
433     return DOM.getElementPropertyInt(itemTable, "offsetHeight");
434   }
435
436   Element getImageElement() {
437     return statusImage.getElement();
438   }
439
440   int getTreeTop() {
441     TreeItem item = this;
442     int ret = 0;
443
444     while (item != null) {
445       ret += DOM.getElementPropertyInt(item.getElement(), "offsetTop");
446       item = item.getParentItem();
447     }
448
449     return ret;
450   }
451
452   void setParentItem(TreeItem parent) {
453     this.parent = parent;
454   }
455
456   void setTree(Tree tree) {
457     if (this.tree == tree) {
458       return;
459     }
460
461     if (this.tree != null) {
462       if (this.tree.getSelectedItem() == this) {
463         this.tree.setSelectedItem(null);
464       }
465
466       // Detach contentPanel from old tree.
467
if (contentPanel != null) {
468         this.tree.disown(contentPanel);
469       }
470     }
471     this.tree = tree;
472     for (int i = 0, n = children.size(); i < n; ++i) {
473       ((TreeItem) children.get(i)).setTree(tree);
474     }
475     updateState();
476     if (tree != null) {
477       if (contentPanel != null) {
478         tree.adopt(contentPanel);
479       }
480     }
481   }
482
483   void updateState() {
484     // If the tree hasn't been set, there is no visual state to update.
485
if (tree == null) {
486       return;
487     }
488     
489     TreeImages images = tree.getImages();
490     
491     if (children.size() == 0) {
492       UIObject.setVisible(childSpanElem, false);
493       images.treeLeaf().applyTo(statusImage);
494       return;
495     }
496
497     // We must use 'display' rather than 'visibility' here,
498
// or the children will always take up space.
499
if (open) {
500       UIObject.setVisible(childSpanElem, true);
501       images.treeOpen().applyTo(statusImage);
502     } else {
503       UIObject.setVisible(childSpanElem, false);
504       images.treeClosed().applyTo(statusImage);
505     }
506   }
507
508   void updateStateRecursive() {
509     updateState();
510     for (int i = 0, n = children.size(); i < n; ++i) {
511       ((TreeItem) children.get(i)).updateStateRecursive();
512     }
513   }
514
515   private void clearContentPanel() {
516     if (contentPanel != null) {
517       // Child should not be owned by anyone anymore.
518
Widget child = contentPanel.getWidget();
519       if (contentPanel.getWidget() != null) {
520         contentPanel.remove(child);
521       }
522
523       // Tree should no longer own contentPanel.
524
if (tree != null) {
525         tree.disown(contentPanel);
526         contentPanel = null;
527       }
528     }
529   }
530
531   private void ensureContentPanel() {
532     if (contentPanel == null) {
533       // Ensure contentElem is empty.
534
DOM.setInnerHTML(contentElem, "");
535       contentPanel = new ContentPanel(contentElem);
536       if (tree != null) {
537         tree.adopt(contentPanel);
538       }
539     }
540   }
541
542 }
543
Popular Tags