KickJava   Java API By Example, From Geeks To Geeks.

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


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.core.client.GWT;
19 import com.google.gwt.user.client.DOM;
20 import com.google.gwt.user.client.Element;
21 import com.google.gwt.user.client.Event;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.HashSet JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Set JavaDoc;
28
29 /**
30  * A standard hierarchical tree widget. The tree contains a hierarchy of
31  * {@link com.google.gwt.user.client.ui.TreeItem TreeItems} that the user can
32  * open, close, and select.
33  * <p>
34  * <img class='gallery' SRC='Tree.png'/>
35  * </p>
36  * <h3>CSS Style Rules</h3>
37  * <ul class='css'>
38  * <li>.gwt-Tree { the tree itself }</li>
39  * <li>.gwt-Tree .gwt-TreeItem { a tree item }</li>
40  * <li>.gwt-Tree .gwt-TreeItem-selected { a selected tree item }</li>
41  * </ul>
42  * <p>
43  * <h3>Example</h3>
44  * {@example com.google.gwt.examples.TreeExample}
45  * </p>
46  */

47 public class Tree extends Widget implements HasWidgets, SourcesTreeEvents,
48     HasFocus {
49
50   /**
51    * Provides images to support the the deprecated case where a url prefix is
52    * passed in through {@link Tree#setImageBase(String)}. This class is used
53    * in such a way that it will be completely removed by the compiler if the
54    * deprecated methods, {@link Tree#setImageBase(String)} and
55    * {@link Tree#getImageBase()}, are not called.
56    */

57   private static class ImagesFromImageBase implements TreeImages {
58     /**
59      * A convience image prototype that implements
60      * {@link AbstractImagePrototype#applyTo(Image)} for a specified image
61      * name.
62      */

63     private class Prototype extends AbstractImagePrototype {
64       private final String JavaDoc imageUrl;
65
66       Prototype(String JavaDoc url) {
67         imageUrl = url;
68       }
69
70       public void applyTo(Image image) {
71         image.setUrl(baseUrl + imageUrl);
72       }
73
74       public Image createImage() {
75         // NOTE: This class is only used internally and, therefore only needs
76
// to support applyTo(Image).
77
throw new UnsupportedOperationException JavaDoc("createImage is unsupported.");
78       }
79
80       public String JavaDoc getHTML() {
81         // NOTE: This class is only used internally and, therefore only needs
82
// to support applyTo(Image).
83
throw new UnsupportedOperationException JavaDoc("getHTML is unsupported.");
84       }
85     }
86
87     private final String JavaDoc baseUrl;
88
89     ImagesFromImageBase(String JavaDoc baseUrl) {
90       this.baseUrl = baseUrl;
91     }
92
93     public AbstractImagePrototype treeClosed() {
94       return new Prototype("tree_closed.gif");
95     }
96     
97     public AbstractImagePrototype treeLeaf() {
98       return new Prototype("tree_white.gif");
99     }
100
101     public AbstractImagePrototype treeOpen() {
102       return new Prototype("tree_open.gif");
103     }
104
105     String JavaDoc getBaseUrl() {
106       return baseUrl;
107     }
108   }
109
110   /**
111    * Map of TreeItem.ContentPanel --> Tree Items.
112    */

113   private final Set JavaDoc childWidgets = new HashSet JavaDoc();
114   private TreeItem curSelection;
115   private final Element focusable;
116   private FocusListenerCollection focusListeners;
117   private TreeImages images;
118   private KeyboardListenerCollection keyboardListeners;
119   private TreeListenerCollection listeners;
120   private MouseListenerCollection mouseListeners = null;
121   private final TreeItem root;
122
123   /**
124    * Keeps track of the last event type seen. We do this to determine if we have
125    * a duplicate key down.
126    */

127   private int lastEventType;
128
129   /**
130    * Constructs an empty tree.
131    */

132   public Tree() {
133     this((TreeImages) GWT.create(TreeImages.class));
134   }
135
136   /**
137    * Constructs a tree that uses the specified image bundle for images.
138    *
139    * @param images a bundle that provides tree specific images
140    */

141   public Tree(TreeImages images) {
142     this.images = images;
143     setElement(DOM.createDiv());
144     DOM.setStyleAttribute(getElement(), "position", "relative");
145     focusable = FocusPanel.impl.createFocusable();
146     DOM.setStyleAttribute(focusable, "fontSize", "0");
147     DOM.setStyleAttribute(focusable, "position", "absolute");
148     DOM.setIntStyleAttribute(focusable, "zIndex", -1);
149     DOM.appendChild(getElement(), focusable);
150
151     sinkEvents(Event.MOUSEEVENTS | Event.ONCLICK | Event.KEYEVENTS);
152     DOM.sinkEvents(focusable, Event.FOCUSEVENTS);
153
154     // The 'root' item is invisible and serves only as a container
155
// for all top-level items.
156
root = new TreeItem() {
157       public void addItem(TreeItem item) {
158         // If this element already belongs to a tree or tree item, remove it.
159
if ((item.getParentItem() != null) || (item.getTree() != null)) {
160           item.remove();
161         }
162         item.setTree(this.getTree());
163
164         // Explicitly set top-level items' parents to null.
165
item.setParentItem(null);
166         getChildren().add(item);
167
168         // Use no margin on top-most items.
169
DOM.setIntStyleAttribute(item.getElement(), "marginLeft", 0);
170       }
171
172       public void removeItem(TreeItem item) {
173         if (!getChildren().contains(item)) {
174           return;
175         }
176         // Update Item state.
177
item.setTree(null);
178         item.setParentItem(null);
179         getChildren().remove(item);
180       }
181     };
182     root.setTree(this);
183     setStyleName("gwt-Tree");
184   }
185
186   /**
187    * Adds the widget as a root tree item.
188    *
189    * @see com.google.gwt.user.client.ui.HasWidgets#add(com.google.gwt.user.client.ui.Widget)
190    * @param widget widget to add.
191    */

192   public void add(Widget widget) {
193     addItem(widget);
194   }
195
196   public void addFocusListener(FocusListener listener) {
197     if (focusListeners == null) {
198       focusListeners = new FocusListenerCollection();
199     }
200     focusListeners.add(listener);
201   }
202
203   /**
204    * Adds a simple tree item containing the specified text.
205    *
206    * @param itemText the text of the item to be added
207    * @return the item that was added
208    */

209   public TreeItem addItem(String JavaDoc itemText) {
210     TreeItem ret = new TreeItem(itemText);
211     addItem(ret);
212
213     return ret;
214   }
215
216   /**
217    * Adds an item to the root level of this tree.
218    *
219    * @param item the item to be added
220    */

221   public void addItem(TreeItem item) {
222     root.addItem(item);
223     DOM.appendChild(getElement(), item.getElement());
224   }
225
226   /**
227    * Adds a new tree item containing the specified widget.
228    *
229    * @param widget the widget to be added
230    */

231   public TreeItem addItem(Widget widget) {
232     TreeItem item = root.addItem(widget);
233     DOM.appendChild(getElement(), item.getElement());
234     return item;
235   }
236
237   public void addKeyboardListener(KeyboardListener listener) {
238     if (keyboardListeners == null) {
239       keyboardListeners = new KeyboardListenerCollection();
240     }
241     keyboardListeners.add(listener);
242   }
243
244   public void addMouseListener(MouseListener listener) {
245     if (mouseListeners == null) {
246       mouseListeners = new MouseListenerCollection();
247     }
248     mouseListeners.add(listener);
249   }
250
251   public void addTreeListener(TreeListener listener) {
252     if (listeners == null) {
253       listeners = new TreeListenerCollection();
254     }
255     listeners.add(listener);
256   }
257
258   /**
259    * Clears all tree items from the current tree.
260    */

261   public void clear() {
262     int size = root.getChildCount();
263     for (int i = size - 1; i >= 0; i--) {
264       root.getChild(i).remove();
265     }
266   }
267
268   /**
269    * Ensures that the currently-selected item is visible, opening its parents
270    * and scrolling the tree as necessary.
271    */

272   public void ensureSelectedItemVisible() {
273     if (curSelection == null) {
274       return;
275     }
276
277     TreeItem parent = curSelection.getParentItem();
278     while (parent != null) {
279       parent.setState(true);
280       parent = parent.getParentItem();
281     }
282   }
283
284   /**
285    * Gets this tree's default image package.
286    *
287    * @return the tree's image package
288    * @see #setImageBase
289    * @deprecated Use {@link #Tree(TreeImages)} as it provides a more efficent
290    * and manageable way to supply a set of images to be used within
291    * a tree.
292    */

293   public String JavaDoc getImageBase() {
294     return (images instanceof ImagesFromImageBase)
295         ? ((ImagesFromImageBase) images).getBaseUrl() : GWT.getModuleBaseURL();
296   }
297
298   /**
299    * Gets the top-level tree item at the specified index.
300    *
301    * @param index the index to be retrieved
302    * @return the item at that index
303    */

304   public TreeItem getItem(int index) {
305     return root.getChild(index);
306   }
307
308   /**
309    * Gets the number of items contained at the root of this tree.
310    *
311    * @return this tree's item count
312    */

313   public int getItemCount() {
314     return root.getChildCount();
315   }
316
317   /**
318    * Gets the currently selected item.
319    *
320    * @return the selected item
321    */

322   public TreeItem getSelectedItem() {
323     return curSelection;
324   }
325
326   public int getTabIndex() {
327     return FocusPanel.impl.getTabIndex(focusable);
328   }
329
330   /**
331    * Returns all <code>TreeItem.ContentPanel</code> elements contained within
332    * this tree. The existence of the <code>TreeItem.ContentPanel</code> class
333    * is an implementation detail that may or may not be preserved in future
334    * versions of Tree.
335    */

336   public Iterator JavaDoc iterator() {
337     return getChildWidgets().iterator();
338   }
339
340   public void onBrowserEvent(Event event) {
341     int eventType = DOM.eventGetType(event);
342     switch (eventType) {
343       case Event.ONCLICK: {
344         Element e = DOM.eventGetTarget(event);
345         if (shouldTreeDelegateFocusToElement(e)) {
346           // The click event should have given focus to this element already.
347
// Avoid moving focus back up to the tree (so that focusable widgets
348
// attached to TreeItems can receive keyboard events).
349
} else {
350           setFocus(true);
351         }
352         break;
353       }
354       case Event.ONMOUSEDOWN: {
355         if (mouseListeners != null) {
356           mouseListeners.fireMouseEvent(this, event);
357         }
358         elementClicked(root, DOM.eventGetTarget(event));
359         break;
360       }
361
362       case Event.ONMOUSEUP: {
363         if (mouseListeners != null) {
364           mouseListeners.fireMouseEvent(this, event);
365         }
366         break;
367       }
368
369       case Event.ONMOUSEMOVE: {
370         if (mouseListeners != null) {
371           mouseListeners.fireMouseEvent(this, event);
372         }
373         break;
374       }
375
376       case Event.ONMOUSEOVER: {
377         if (mouseListeners != null) {
378           mouseListeners.fireMouseEvent(this, event);
379         }
380         break;
381       }
382
383       case Event.ONMOUSEOUT: {
384         if (mouseListeners != null) {
385           mouseListeners.fireMouseEvent(this, event);
386         }
387         break;
388       }
389
390       case Event.ONFOCUS:
391         // If we already have focus, ignore the focus event.
392
if (focusListeners != null) {
393           focusListeners.fireFocusEvent(this, event);
394         }
395         break;
396
397       case Event.ONBLUR: {
398         if (focusListeners != null) {
399           focusListeners.fireFocusEvent(this, event);
400         }
401
402         break;
403       }
404
405       case Event.ONKEYDOWN:
406         // If nothing's selected, select the first item.
407
if (curSelection == null) {
408           if (root.getChildCount() > 0) {
409             onSelection(root.getChild(0), true, true);
410           }
411           super.onBrowserEvent(event);
412           return;
413         }
414
415         if (lastEventType == Event.ONKEYDOWN) {
416           // Two key downs in a row signal a duplicate event. Multiple key
417
// downs can be triggered in the current configuration independent
418
// of the browser.
419
return;
420         }
421
422         // Handle keyboard events if keyboard navigation is enabled
423
if (isKeyboardNavigationEnabled(curSelection)) {
424           switch (DOM.eventGetKeyCode(event)) {
425             case KeyboardListener.KEY_UP: {
426               moveSelectionUp(curSelection);
427               DOM.eventPreventDefault(event);
428               break;
429             }
430             case KeyboardListener.KEY_DOWN: {
431               moveSelectionDown(curSelection, true);
432               DOM.eventPreventDefault(event);
433               break;
434             }
435             case KeyboardListener.KEY_LEFT: {
436               if (curSelection.getState()) {
437                 curSelection.setState(false);
438               } else {
439                 TreeItem parent = curSelection.getParentItem();
440                 if (parent != null) {
441                   setSelectedItem(parent);
442                 }
443               }
444               DOM.eventPreventDefault(event);
445               break;
446             }
447             case KeyboardListener.KEY_RIGHT: {
448               if (!curSelection.getState()) {
449                 curSelection.setState(true);
450               } else if (curSelection.getChildCount() > 0) {
451                 setSelectedItem(curSelection.getChild(0));
452               }
453               DOM.eventPreventDefault(event);
454               break;
455             }
456           }
457         }
458
459         // Intentional fallthrough.
460
case Event.ONKEYUP:
461         if (eventType == Event.ONKEYUP) {
462           // If we got here because of a key tab, then we need to make sure the
463
// current tree item is selected.
464
if (DOM.eventGetKeyCode(event) == KeyboardListener.KEY_TAB) {
465             ArrayList JavaDoc chain = new ArrayList JavaDoc();
466             collectElementChain(chain, getElement(), DOM.eventGetTarget(event));
467             TreeItem item = findItemByChain(chain, 0, root);
468             if (item != getSelectedItem()) {
469               setSelectedItem(item, true);
470             }
471           }
472         }
473
474         // Intentional fallthrough.
475
case Event.ONKEYPRESS: {
476         if (keyboardListeners != null) {
477           keyboardListeners.fireKeyboardEvent(this, event);
478         }
479         break;
480       }
481     }
482
483     // We must call SynthesizedWidget's implementation for all other events.
484
super.onBrowserEvent(event);
485     lastEventType = eventType;
486   }
487
488   public boolean remove(Widget w) {
489     throw new UnsupportedOperationException JavaDoc(
490         "Widgets should never be directly removed from a tree");
491   }
492
493   public void removeFocusListener(FocusListener listener) {
494     if (focusListeners != null) {
495       focusListeners.remove(listener);
496     }
497   }
498
499   /**
500    * Removes an item from the root level of this tree.
501    *
502    * @param item the item to be removed
503    */

504   public void removeItem(TreeItem item) {
505     root.removeItem(item);
506     DOM.removeChild(getElement(), item.getElement());
507   }
508
509   /**
510    * Removes all items from the root level of this tree.
511    */

512   public void removeItems() {
513     while (getItemCount() > 0) {
514       removeItem(getItem(0));
515     }
516   }
517
518   public void removeKeyboardListener(KeyboardListener listener) {
519     if (keyboardListeners != null) {
520       keyboardListeners.remove(listener);
521     }
522   }
523
524   public void removeTreeListener(TreeListener listener) {
525     if (listeners != null) {
526       listeners.remove(listener);
527     }
528   }
529
530   public void setAccessKey(char key) {
531     FocusPanel.impl.setAccessKey(focusable, key);
532   }
533
534   public void setFocus(boolean focus) {
535     if (focus) {
536       FocusPanel.impl.focus(focusable);
537     } else {
538       FocusPanel.impl.blur(focusable);
539     }
540   }
541
542   /**
543    * Sets the base URL under which this tree will find its default images. These
544    * images must be named "tree_white.gif", "tree_open.gif", and
545    * "tree_closed.gif".
546    *
547    * @param baseUrl
548    * @deprecated Use {@link #Tree(TreeImages)} as it provides a more efficent
549    * and manageable way to supply a set of images to be used within
550    * a tree.
551    */

552   public void setImageBase(String JavaDoc baseUrl) {
553     images = new ImagesFromImageBase(baseUrl);
554     root.updateStateRecursive();
555   }
556
557   /**
558    * Selects a specified item.
559    *
560    * @param item the item to be selected, or <code>null</code> to deselect all
561    * items
562    */

563   public void setSelectedItem(TreeItem item) {
564     setSelectedItem(item, true);
565   }
566
567   /**
568    * Selects a specified item.
569    *
570    * @param item the item to be selected, or <code>null</code> to deselect all
571    * items
572    * @param fireEvents <code>true</code> to allow selection events to be fired
573    */

574   public void setSelectedItem(TreeItem item, boolean fireEvents) {
575     if (item == null) {
576       if (curSelection == null) {
577         return;
578       }
579       curSelection.setSelected(false);
580       curSelection = null;
581       return;
582     }
583
584     onSelection(item, fireEvents, true);
585   }
586
587   public void setTabIndex(int index) {
588     FocusPanel.impl.setTabIndex(focusable, index);
589   }
590
591   /**
592    * Iterator of tree items.
593    */

594   public Iterator JavaDoc treeItemIterator() {
595     List JavaDoc accum = new ArrayList JavaDoc();
596     root.addTreeItems(accum);
597     return accum.iterator();
598   }
599
600   /**
601    * Indicates if keyboard navigation is enabled for the Tree and for a given
602    * TreeItem. Subclasses of Tree can override this function to selectively
603    * enable or disable keyboard navigation.
604    *
605    * @param currentItem the currently selected TreeItem
606    * @return <code>true</code> if the Tree will response to arrow keys by
607    * changing the currently selected item
608    */

609   protected boolean isKeyboardNavigationEnabled(TreeItem currentItem) {
610     return true;
611   }
612
613   protected void onAttach() {
614     super.onAttach();
615
616     // Ensure that all child widgets are attached.
617
for (Iterator JavaDoc it = iterator(); it.hasNext();) {
618       Widget child = (Widget) it.next();
619       child.onAttach();
620     }
621     DOM.setEventListener(focusable, this);
622   }
623
624   protected void onDetach() {
625     super.onDetach();
626
627     // Ensure that all child widgets are detached.
628
for (Iterator JavaDoc it = iterator(); it.hasNext();) {
629       Widget child = (Widget) it.next();
630       child.onDetach();
631     }
632     DOM.setEventListener(focusable, null);
633   }
634
635   protected void onLoad() {
636     root.updateStateRecursive();
637   }
638
639   void adopt(TreeItem.ContentPanel content) {
640     getChildWidgets().add(content);
641     content.treeSetParent(this);
642   }
643
644   void disown(TreeItem.ContentPanel item) {
645     getChildWidgets().remove(item);
646     item.treeSetParent(null);
647   }
648
649   void fireStateChanged(TreeItem item) {
650     if (listeners != null) {
651       listeners.fireItemStateChanged(item);
652     }
653   }
654
655   /**
656    * Get the Set of child widgets. Exposed only to allow unit tests to validate
657    * tree.
658    *
659    * @return the children
660    */

661   Set JavaDoc getChildWidgets() {
662     return childWidgets;
663   }
664
665   TreeImages getImages() {
666     return images;
667   }
668
669   /**
670    * Collects parents going up the element tree, terminated at the tree root.
671    */

672   private void collectElementChain(ArrayList JavaDoc chain, Element hRoot, Element hElem) {
673     if ((hElem == null) || DOM.compare(hElem, hRoot)) {
674       return;
675     }
676
677     collectElementChain(chain, hRoot, DOM.getParent(hElem));
678     chain.add(hElem);
679   }
680
681   private boolean elementClicked(TreeItem root, Element hElem) {
682     ArrayList JavaDoc chain = new ArrayList JavaDoc();
683     collectElementChain(chain, getElement(), hElem);
684
685     TreeItem item = findItemByChain(chain, 0, root);
686     if (item != null) {
687       if (DOM.isOrHasChild(item.getImageElement(), hElem)) {
688         item.setState(!item.getState(), true);
689         return true;
690       } else if (DOM.isOrHasChild(item.getElement(), hElem)) {
691         onSelection(item, true, !shouldTreeDelegateFocusToElement(hElem));
692         return true;
693       }
694     }
695
696     return false;
697   }
698
699   private TreeItem findDeepestOpenChild(TreeItem item) {
700     if (!item.getState()) {
701       return item;
702     }
703     return findDeepestOpenChild(item.getChild(item.getChildCount() - 1));
704   }
705
706   private TreeItem findItemByChain(ArrayList JavaDoc chain, int idx, TreeItem root) {
707     if (idx == chain.size()) {
708       return root;
709     }
710
711     Element hCurElem = (Element) chain.get(idx);
712     for (int i = 0, n = root.getChildCount(); i < n; ++i) {
713       TreeItem child = root.getChild(i);
714       if (DOM.compare(child.getElement(), hCurElem)) {
715         TreeItem retItem = findItemByChain(chain, idx + 1, root.getChild(i));
716         if (retItem == null) {
717           return child;
718         }
719         return retItem;
720       }
721     }
722
723     return findItemByChain(chain, idx + 1, root);
724   }
725
726   /**
727    * Move the tree focus to the specified selected item.
728    *
729    * @param selection
730    */

731   private void moveFocus(TreeItem selection) {
732     HasFocus focusableWidget = selection.getFocusableWidget();
733     if (focusableWidget != null) {
734       focusableWidget.setFocus(true);
735       DOM.scrollIntoView(((Widget) focusableWidget).getElement());
736     } else {
737       // Get the location and size of the given item's content element relative
738
// to the tree.
739
Element selectedElem = selection.getContentElem();
740       int containerLeft = getAbsoluteLeft();
741       int containerTop = getAbsoluteTop();
742
743       int left = DOM.getAbsoluteLeft(selectedElem) - containerLeft;
744       int top = DOM.getAbsoluteTop(selectedElem) - containerTop;
745       int width = DOM.getElementPropertyInt(selectedElem, "offsetWidth");
746       int height = DOM.getElementPropertyInt(selectedElem, "offsetHeight");
747
748       // Set the focusable element's position and size to exactly underlap the
749
// item's content element.
750
DOM.setIntStyleAttribute(focusable, "left", left);
751       DOM.setIntStyleAttribute(focusable, "top", top);
752       DOM.setIntStyleAttribute(focusable, "width", width);
753       DOM.setIntStyleAttribute(focusable, "height", height);
754
755       // Scroll it into view.
756
DOM.scrollIntoView(focusable);
757
758       // Ensure Focus is set, as focus may have been previously delegated by
759
// tree.
760
FocusPanel.impl.focus(focusable);
761     }
762   }
763
764   /**
765    * Moves to the next item, going into children as if dig is enabled.
766    */

767   private void moveSelectionDown(TreeItem sel, boolean dig) {
768     if (sel == root) {
769       return;
770     }
771
772     TreeItem parent = sel.getParentItem();
773     if (parent == null) {
774       parent = root;
775     }
776     int idx = parent.getChildIndex(sel);
777
778     if (!dig || !sel.getState()) {
779       if (idx < parent.getChildCount() - 1) {
780         onSelection(parent.getChild(idx + 1), true, true);
781       } else {
782         moveSelectionDown(parent, false);
783       }
784     } else if (sel.getChildCount() > 0) {
785       onSelection(sel.getChild(0), true, true);
786     }
787   }
788
789   /**
790    * Moves the selected item up one.
791    */

792   private void moveSelectionUp(TreeItem sel) {
793     TreeItem parent = sel.getParentItem();
794     if (parent == null) {
795       parent = root;
796     }
797     int idx = parent.getChildIndex(sel);
798
799     if (idx > 0) {
800       TreeItem sibling = parent.getChild(idx - 1);
801       onSelection(findDeepestOpenChild(sibling), true, true);
802     } else {
803       onSelection(parent, true, true);
804     }
805   }
806
807   private void onSelection(TreeItem item, boolean fireEvents, boolean moveFocus) {
808
809     // 'root' isn't a real item, so don't let it be selected
810
// (some cases in the keyboard handler will try to do this)
811
if (item == root) {
812       return;
813     }
814
815     if (curSelection != null) {
816       curSelection.setSelected(false);
817     }
818
819     curSelection = item;
820
821     if (moveFocus && curSelection != null) {
822       moveFocus(curSelection);
823
824       // Select the item and fire the selection event.
825
curSelection.setSelected(true);
826       if (fireEvents && (listeners != null)) {
827         listeners.fireItemSelected(curSelection);
828       }
829     }
830   }
831
832   private native boolean shouldTreeDelegateFocusToElement(Element elem) /*-{
833     var name = elem.nodeName;
834     return ((name == "SELECT") ||
835         (name == "INPUT") ||
836         (name == "TEXTAREA") ||
837         (name == "OPTION") ||
838         (name == "BUTTON") ||
839         (name == "LABEL"));
840   }-*/
;
841 }
842
Popular Tags