KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > myfaces > custom > tree > HtmlTree


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.myfaces.custom.tree;
17
18 import java.io.IOException JavaDoc;
19 import java.util.*;
20
21 import javax.faces.component.UIViewRoot;
22 import javax.faces.component.html.HtmlPanelGroup;
23 import javax.faces.context.FacesContext;
24 import javax.faces.el.ValueBinding;
25
26 import org.apache.myfaces.component.html.util.AddResource;
27 import org.apache.myfaces.custom.tree.event.TreeSelectionEvent;
28 import org.apache.myfaces.custom.tree.event.TreeSelectionListener;
29 import org.apache.myfaces.custom.tree.model.TreeModel;
30 import org.apache.myfaces.custom.tree.model.TreeModelEvent;
31 import org.apache.myfaces.custom.tree.model.TreeModelListener;
32 import org.apache.myfaces.custom.tree.model.TreePath;
33
34
35 /**
36  * <p/>
37  * Tree implementation based on javax.swing.JTree.
38  * </p>
39  * <p/>
40  * The tree model is assigned by using a value binding named <code>model</code>
41  * and is not stored in view state.
42  * </p>
43  * <p/>
44  * A hierarchy of {@link HtmlTreeNode}objects is used to represent the current
45  * expanded state of the tree. The root node is held as a faces named
46  * <code>rootNode</code>.
47  * </p>
48  *
49  * @author <a HREF="mailto:oliver@rossmueller.com">Oliver Rossmueller </a>
50  * @version $Revision: 1.31 $ $Date: 2005/03/30 07:41:58 $
51  * <p/>
52  * $Log: HtmlTree.java,v $
53  * Revision 1.31 2005/03/30 07:41:58 matzew
54  * closed MYFACES-139. Thanks to Mathias Broekelmann
55  *
56  * Revision 1.30 2005/02/11 00:54:02 svieujot
57  * Revert changes commited to the wrong branch.
58  *
59  * Revision 1.28 2004/12/24 14:13:16 svieujot
60  * Upgrade the tree component to use the Extensions filter.
61  *
62  * Revision 1.27 2004/11/26 12:46:38 oros
63  * cleanup: removed unused iconChild attribute
64  *
65  * Revision 1.26 2004/11/26 12:33:54 oros
66  * MYFACES-9: store iconChildMiddle in component state
67  *
68  * Revision 1.25 2004/11/26 12:14:10 oros
69  * MYFACES-8: applied tree table patch by David Le Strat
70  *
71  */

72 public class HtmlTree extends HtmlPanelGroup implements TreeModelListener
73 {
74
75     public static final int DEFAULT_EXPIRE_LISTENERS = 8 * 60 * 60 * 1000; // 8 hours
76
private static final String JavaDoc FACET_ROOTNODE = "rootNode";
77     private static final String JavaDoc PREVIOUS_VIEW_ROOT = HtmlTree.class.getName() + ".PREVIOUS_VIEW_ROOT";
78     private static final int EVENT_CHANGED = 0;
79     private static final int EVENT_INSERTED = 1;
80     private static final int EVENT_REMOVED = 2;
81     private static final int EVENT_STRUCTURE_CHANGED = 3;
82     private static int counter = 0;
83     
84     // Defaut images
85
private static final String JavaDoc DEFAULT_IMAGE_ICON_LINE = "images/line.gif";
86     private static final String JavaDoc DEFAULT_IMAGE_ICON_NOLINE = "images/noline.gif";
87     private static final String JavaDoc DEFAULT_IMAGE_ICON_CHILD_FIRST = "images/line_first.gif";
88     private static final String JavaDoc DEFAULT_IMAGE_ICON_CHILD_MIDDLE = "images/line_middle.gif";
89     private static final String JavaDoc DEFAULT_IMAGE_ICON_CHILD_LAST = "images/line_last.gif";
90     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_OPEN = "images/node_open.gif";
91     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST = "images/node_open_first.gif";
92     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE = "images/node_open_middle.gif";
93     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_OPEN_LAST = "images/node_open_last.gif";
94     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_CLOSE = "images/node_close.gif";
95     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST = "images/node_close_first.gif";
96     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE = "images/node_close_middle.gif";
97     private static final String JavaDoc DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST = "images/node_close_last.gif";
98     
99     private IconProvider iconProvider;
100     private boolean itemStatesRestored = false;
101     private String JavaDoc var;
102     private String JavaDoc styleClass;
103     private String JavaDoc nodeClass;
104     private String JavaDoc rowClasses;
105     private String JavaDoc columnClasses;
106     private String JavaDoc selectedNodeClass;
107     private String JavaDoc iconClass;
108     private String JavaDoc iconLine;
109     private String JavaDoc iconNoline;
110     private String JavaDoc iconChildFirst;
111     private String JavaDoc iconChildMiddle;
112     private String JavaDoc iconChildLast;
113     private String JavaDoc iconNodeOpen;
114     private String JavaDoc iconNodeOpenFirst;
115     private String JavaDoc iconNodeOpenMiddle;
116     private String JavaDoc iconNodeOpenLast;
117     private String JavaDoc iconNodeClose;
118     private String JavaDoc iconNodeCloseFirst;
119     private String JavaDoc iconNodeCloseMiddle;
120     private String JavaDoc iconNodeCloseLast;
121     private int uniqueIdCounter = 0;
122     private int[] selectedPath;
123     private int internalId;
124     private long expireListeners = DEFAULT_EXPIRE_LISTENERS;
125
126
127     /**
128      * <p/>
129      * Default constructor.
130      * </p>
131      */

132     public HtmlTree()
133     {
134         internalId = counter++;
135     }
136
137
138     public TreeModel getModel(FacesContext context)
139     {
140         ValueBinding binding = getValueBinding("model");
141
142         if (binding != null)
143         {
144             TreeModel model = (TreeModel) binding.getValue(context);
145             if (model != null)
146             {
147                 return model;
148             }
149         }
150         return null;
151     }
152
153
154     public String JavaDoc createUniqueId(FacesContext context)
155     {
156         return getClientId(context).replaceAll(":", "_") + "_node_" + uniqueIdCounter++;
157     }
158
159
160     public void addTreeSelectionListener(TreeSelectionListener listener)
161     {
162         addFacesListener(listener);
163     }
164
165
166     public IconProvider getIconProvider()
167     {
168         return iconProvider;
169     }
170
171
172     public void setIconProvider(IconProvider iconProvider)
173     {
174         this.iconProvider = iconProvider;
175     }
176
177
178     /**
179      * @return Returns the var.
180      */

181     public String JavaDoc getVar()
182     {
183         return var;
184     }
185
186
187     /**
188      * @param var The var to set.
189      */

190     public void setVar(String JavaDoc var)
191     {
192         this.var = var;
193     }
194
195
196     public String JavaDoc getIconLine()
197     {
198         if( iconLine != null )
199             return iconLine;
200         
201         return getDefaultImagePath( DEFAULT_IMAGE_ICON_LINE );
202     }
203
204
205     public void setIconLine(String JavaDoc iconLine)
206     {
207         this.iconLine = iconLine;
208     }
209
210
211     public String JavaDoc getIconNoline()
212     {
213         if( iconNoline != null )
214             return iconNoline;
215         
216         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NOLINE );
217     }
218
219
220     public void setIconNoline(String JavaDoc iconNoline)
221     {
222         this.iconNoline = iconNoline;
223     }
224
225
226     public String JavaDoc getIconChildFirst()
227     {
228         if( iconChildFirst != null )
229             return iconChildFirst;
230         
231         return getDefaultImagePath( DEFAULT_IMAGE_ICON_CHILD_FIRST );
232     }
233
234
235     public void setIconChildFirst(String JavaDoc iconChildFirst)
236     {
237         this.iconChildFirst = iconChildFirst;
238     }
239
240
241     public String JavaDoc getIconChildMiddle()
242     {
243         if( iconChildMiddle != null )
244             return iconChildMiddle;
245         
246         return getDefaultImagePath( DEFAULT_IMAGE_ICON_CHILD_MIDDLE );
247     }
248
249
250     public void setIconChildMiddle(String JavaDoc iconChildMiddle)
251     {
252         this.iconChildMiddle = iconChildMiddle;
253     }
254
255
256     public String JavaDoc getIconChildLast()
257     {
258         if( iconChildLast != null )
259             return iconChildLast;
260         
261         return getDefaultImagePath( DEFAULT_IMAGE_ICON_CHILD_LAST );
262     }
263
264
265     public void setIconChildLast(String JavaDoc iconChildLast)
266     {
267         this.iconChildLast = iconChildLast;
268     }
269
270
271     public String JavaDoc getIconNodeOpen()
272     {
273         if( iconNodeOpen != null )
274             return iconNodeOpen;
275         
276         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_OPEN );
277     }
278
279
280     public void setIconNodeOpen(String JavaDoc iconNodeOpen)
281     {
282         this.iconNodeOpen = iconNodeOpen;
283     }
284
285
286     public String JavaDoc getIconNodeOpenFirst()
287     {
288         if( iconNodeOpenFirst != null )
289         return iconNodeOpenFirst;
290         
291         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_OPEN_FIRST );
292     }
293
294
295     public void setIconNodeOpenFirst(String JavaDoc iconNodeOpenFirst)
296     {
297         this.iconNodeOpenFirst = iconNodeOpenFirst;
298     }
299
300
301     public String JavaDoc getIconNodeOpenMiddle()
302     {
303         if( iconNodeOpenMiddle != null )
304             return iconNodeOpenMiddle;
305         
306         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_OPEN_MIDDLE );
307     }
308
309
310     public void setIconNodeOpenMiddle(String JavaDoc iconNodeOpenMiddle)
311     {
312         this.iconNodeOpenMiddle = iconNodeOpenMiddle;
313     }
314
315
316     public String JavaDoc getIconNodeOpenLast()
317     {
318         if( iconNodeOpenLast != null )
319             return iconNodeOpenLast;
320         
321         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_OPEN_LAST );
322     }
323
324
325     public void setIconNodeOpenLast(String JavaDoc iconNodeOpenLast)
326     {
327         this.iconNodeOpenLast = iconNodeOpenLast;
328     }
329
330
331     public String JavaDoc getIconNodeClose()
332     {
333         if( iconNodeClose != null )
334             return iconNodeClose;
335         
336         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_CLOSE );
337     }
338
339
340     public void setIconNodeClose(String JavaDoc iconNodeClose)
341     {
342         this.iconNodeClose = iconNodeClose;
343     }
344
345
346     public String JavaDoc getIconNodeCloseFirst()
347     {
348         if( iconNodeCloseFirst != null )
349             return iconNodeCloseFirst;
350         
351         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_CLOSE_FIRST );
352     }
353
354
355     public void setIconNodeCloseFirst(String JavaDoc iconNodeCloseFirst)
356     {
357         this.iconNodeCloseFirst = iconNodeCloseFirst;
358     }
359
360
361     public String JavaDoc getIconNodeCloseMiddle()
362     {
363         if( iconNodeCloseMiddle != null )
364             return iconNodeCloseMiddle;
365         
366         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_CLOSE_MIDDLE );
367     }
368
369
370     public void setIconNodeCloseMiddle(String JavaDoc iconNodeCloseMiddle)
371     {
372         this.iconNodeCloseMiddle = iconNodeCloseMiddle;
373     }
374
375
376     public String JavaDoc getIconNodeCloseLast()
377     {
378         if( iconNodeCloseLast != null )
379             return iconNodeCloseLast;
380         
381         return getDefaultImagePath( DEFAULT_IMAGE_ICON_NODE_CLOSE_LAST );
382     }
383
384
385     public void setIconNodeCloseLast(String JavaDoc iconNodeCloseLast)
386     {
387         this.iconNodeCloseLast = iconNodeCloseLast;
388     }
389
390
391     public String JavaDoc getStyleClass()
392     {
393         return styleClass;
394     }
395
396
397     public void setStyleClass(String JavaDoc styleClass)
398     {
399         this.styleClass = styleClass;
400     }
401
402
403     public String JavaDoc getNodeClass()
404     {
405         return nodeClass;
406     }
407
408
409     public void setNodeClass(String JavaDoc nodeClass)
410     {
411         this.nodeClass = nodeClass;
412     }
413
414
415     /**
416      * @return Returns the rowClasses.
417      */

418     public String JavaDoc getRowClasses()
419     {
420         return rowClasses;
421     }
422
423
424     /**
425      * @param rowClasses The rowClasses to set.
426      */

427     public void setRowClasses(String JavaDoc rowClasses)
428     {
429         this.rowClasses = rowClasses;
430     }
431
432
433     /**
434      * @return Returns the columnClasses.
435      */

436     public String JavaDoc getColumnClasses()
437     {
438         return columnClasses;
439     }
440
441
442     /**
443      * @param columnClasses The columnClasses to set.
444      */

445     public void setColumnClasses(String JavaDoc columnClasses)
446     {
447         this.columnClasses = columnClasses;
448     }
449
450
451     /**
452      * @return Returns the selectedNodeClass.
453      */

454     public String JavaDoc getSelectedNodeClass()
455     {
456         return selectedNodeClass;
457     }
458
459
460     /**
461      * @param selectedNodeClass The selectedNodeClass to set.
462      */

463     public void setSelectedNodeClass(String JavaDoc selectedNodeClass)
464     {
465         this.selectedNodeClass = selectedNodeClass;
466     }
467
468
469     public String JavaDoc getIconClass()
470     {
471         return iconClass;
472     }
473
474
475     public void setIconClass(String JavaDoc iconClass)
476     {
477         this.iconClass = iconClass;
478     }
479
480
481     public long getExpireListeners()
482     {
483         return expireListeners;
484     }
485
486
487     public void setExpireListeners(long expireListeners)
488     {
489         this.expireListeners = expireListeners;
490     }
491
492
493     public String JavaDoc getFamily()
494     {
495         return "org.apache.myfaces.HtmlTree";
496     }
497
498
499     /**
500      * Ensures that the node identified by the specified path is expanded and
501      * viewable. If the last item in the path is a leaf, this will have no
502      * effect.
503      *
504      * @param path the <code>TreePath</code> identifying a node
505      */

506     public void expandPath(TreePath path, FacesContext context)
507     {
508         // Only expand if not leaf!
509
TreeModel model = getModel(context);
510
511         if (path != null && model != null && !model.isLeaf(path.getLastPathComponent()))
512         {
513             int[] translatedPath = HtmlTreeNode.translatePath(path, getModel(context));
514             HtmlTreeNode rootNode = getRootNode();
515             if (rootNode == null)
516             {
517                 createRootNode(context);
518                 rootNode = getRootNode();
519             }
520             if (!rootNode.isExpanded())
521             {
522                 rootNode.setExpanded(true);
523             }
524             rootNode.expandPath(translatedPath, 0);
525
526         }
527     }
528
529
530     /**
531      * Ensures that the node identified by the specified path is collapsed and
532      * viewable.
533      *
534      * @param path the <code>TreePath</code> identifying a node
535      */

536     public void collapsePath(TreePath path, FacesContext context)
537     {
538         HtmlTreeNode node = findNode(path, context);
539
540         if (node != null)
541         {
542             node.setExpanded(false);
543         }
544     }
545
546
547     public boolean isExpanded(TreePath path, FacesContext context)
548     {
549         if (path == null)
550         {
551             return false;
552         }
553
554         return findNode(path, context) != null;
555     }
556
557
558     private HtmlTreeNode findNode(TreePath path, FacesContext context)
559     {
560         HtmlTreeNode node = getRootNode();
561         int[] translatedPath = HtmlTreeNode.translatePath(path, getModel(context));
562
563         for (int i = 0; i < translatedPath.length; i++)
564         {
565             if (!node.isExpanded())
566             {
567                 return null;
568             }
569             int index = translatedPath[i];
570             node = (HtmlTreeNode) node.getChildren().get(index);
571         }
572         return node;
573     }
574
575
576     public TreePath getSelectionPath()
577     {
578         if (selectedPath == null)
579         {
580             return null;
581         }
582         return HtmlTreeNode.translatePath(selectedPath, getModel(FacesContext.getCurrentInstance()));
583     }
584
585
586     public void selectionChanged(HtmlTreeNode node)
587     {
588         TreePath oldPath = null;
589
590         if (selectedPath != null)
591         {
592             oldPath = HtmlTreeNode.translatePath(selectedPath, getModel(FacesContext.getCurrentInstance()));
593         }
594         selectedPath = node.getTranslatedPath();
595         if (node.isSelected())
596         {
597             queueEvent(new TreeSelectionEvent(this, oldPath, node.getPath()));
598         } else
599         {
600             queueEvent(new TreeSelectionEvent(this, oldPath, null));
601         }
602     }
603
604
605     private void createRootNode(FacesContext context)
606     {
607         HtmlTreeNode node;
608         TreeModel model = getModel(context);
609         Object JavaDoc root = model.getRoot();
610         node = (HtmlTreeNode) context.getApplication().createComponent(HtmlTreeNode.COMPONENT_TYPE);
611         String JavaDoc id = createUniqueId(context);
612         node.setId(id);
613
614         node.setPath(new TreePath(new Object JavaDoc[]{root}));
615         node.setUserObject(root);
616         node.setLayout(new int[]{HtmlTreeNode.CLOSED_SINGLE});
617         getFacets().put(FACET_ROOTNODE, node);
618     }
619
620
621     public HtmlTreeNode getRootNode()
622     {
623         return (HtmlTreeNode) getFacet(FACET_ROOTNODE);
624     }
625
626
627     public Object JavaDoc saveState(FacesContext context)
628     {
629         Object JavaDoc values[] = new Object JavaDoc[25];
630         values[0] = super.saveState(context);
631         values[1] = iconChildFirst;
632         values[2] = iconChildMiddle;
633         values[3] = iconChildLast;
634         values[4] = iconLine;
635         values[5] = iconNodeClose;
636         values[6] = iconNodeCloseFirst;
637         values[7] = iconNodeCloseLast;
638         values[8] = iconNodeCloseMiddle;
639         values[9] = iconNodeOpen;
640         values[10] = iconNodeOpenFirst;
641         values[11] = iconNodeOpenLast;
642         values[12] = iconNodeOpenMiddle;
643         values[13] = iconNoline;
644         values[14] = styleClass;
645         values[15] = nodeClass;
646         values[16] = selectedNodeClass;
647         values[17] = new Integer JavaDoc(uniqueIdCounter);
648         values[18] = selectedPath;
649         values[19] = iconClass;
650         values[20] = new Integer JavaDoc(internalId);
651         values[21] = new Long JavaDoc(expireListeners);
652         values[22] = rowClasses;
653         values[23] = columnClasses;
654         values[24] = var;
655         return ((Object JavaDoc) (values));
656     }
657
658
659     public void restoreState(FacesContext context, Object JavaDoc state)
660     {
661         Object JavaDoc values[] = (Object JavaDoc[]) state;
662         super.restoreState(context, values[0]);
663         iconChildFirst = (String JavaDoc) values[1];
664         iconChildMiddle = (String JavaDoc) values[2];
665         iconChildLast = (String JavaDoc) values[3];
666         iconLine = (String JavaDoc) values[4];
667         iconNodeClose = (String JavaDoc) values[5];
668         iconNodeCloseFirst = (String JavaDoc) values[6];
669         iconNodeCloseLast = (String JavaDoc) values[7];
670         iconNodeCloseMiddle = (String JavaDoc) values[8];
671         iconNodeOpen = (String JavaDoc) values[9];
672         iconNodeOpenFirst = (String JavaDoc) values[10];
673         iconNodeOpenLast = (String JavaDoc) values[11];
674         iconNodeOpenMiddle = (String JavaDoc) values[12];
675         iconNoline = (String JavaDoc) values[13];
676         styleClass = (String JavaDoc) values[14];
677         nodeClass = (String JavaDoc) values[15];
678         selectedNodeClass = (String JavaDoc) values[16];
679         uniqueIdCounter = ((Integer JavaDoc) values[17]).intValue();
680         selectedPath = (int[]) values[18];
681         iconClass = (String JavaDoc) values[19];
682         internalId = ((Integer JavaDoc) values[20]).intValue();
683         expireListeners = ((Long JavaDoc) values[21]).longValue();
684         rowClasses = (String JavaDoc) values[22];
685         columnClasses = (String JavaDoc) values[23];
686         var = (String JavaDoc) values[24];
687         addToModelListeners();
688     }
689
690
691     public void decode(FacesContext context)
692     {
693         super.decode(context);
694
695         //Save the current view root for later reference...
696
context.getExternalContext().getRequestMap().put(PREVIOUS_VIEW_ROOT, context.getViewRoot());
697         //...and remember that this instance needs NO special treatment on
698
// rendering:
699
itemStatesRestored = true;
700     }
701
702
703     public void processDecodes(FacesContext context)
704     {
705         addToModelListeners();
706         super.processDecodes(context);
707     }
708
709
710     public void processValidators(FacesContext context)
711     {
712         addToModelListeners();
713         super.processValidators(context);
714     }
715
716
717     public void processUpdates(FacesContext context)
718     {
719         addToModelListeners();
720         super.processUpdates(context);
721     }
722
723
724     public void encodeBegin(FacesContext context) throws IOException JavaDoc
725     {
726         addToModelListeners();
727         processModelEvents();
728
729         HtmlTreeNode node = getRootNode();
730
731         if (node == null)
732         {
733             createRootNode(context);
734         }
735
736         if (!itemStatesRestored)
737         {
738             UIViewRoot previousRoot = (UIViewRoot) context.getExternalContext().getRequestMap().get(PREVIOUS_VIEW_ROOT);
739             if (previousRoot != null)
740             {
741                 restoreItemStates(context, previousRoot);
742             } else
743             {
744                 //no previous root, means no decode was done
745
//--> a new request
746
}
747         }
748
749         super.encodeBegin(context);
750     }
751
752
753     public void encodeEnd(FacesContext context) throws IOException JavaDoc
754     {
755         super.encodeEnd(context);
756     }
757
758
759     public void restoreItemStates(FacesContext facesContext, UIViewRoot previousRoot)
760     {
761         HtmlTree previousTree = (HtmlTree) previousRoot.findComponent(getClientId(facesContext));
762
763         if (previousTree != null)
764         {
765             HtmlTreeNode node = previousTree.getRootNode();
766
767             if (node != null)
768             {
769                 getRootNode().restoreItemState(node);
770             }
771
772             selectedPath = previousTree.selectedPath;
773         }
774     }
775
776
777     public void treeNodesChanged(TreeModelEvent e)
778     {
779         TreePath path = e.getTreePath();
780         FacesContext context = FacesContext.getCurrentInstance();
781         HtmlTreeNode node = findNode(path, context);
782
783         if (node != null)
784         {
785             node.childrenChanged(e.getChildIndices(), context);
786         }
787     }
788
789
790     public void treeNodesInserted(TreeModelEvent e)
791     {
792         TreePath path = e.getTreePath();
793         FacesContext context = FacesContext.getCurrentInstance();
794         HtmlTreeNode node = findNode(path, context);
795
796         if (node != null)
797         {
798             node.childrenAdded(e.getChildIndices(), context);
799         }
800     }
801
802
803     public void treeNodesRemoved(TreeModelEvent e)
804     {
805         TreePath path = e.getTreePath();
806         FacesContext context = FacesContext.getCurrentInstance();
807         HtmlTreeNode node = findNode(path, context);
808
809         if (node != null)
810         {
811             node.childrenRemoved(e.getChildIndices());
812         }
813     }
814
815
816     public void treeStructureChanged(TreeModelEvent e)
817     {
818         TreePath path = e.getTreePath();
819         FacesContext context = FacesContext.getCurrentInstance();
820
821         if (isExpanded(path, context))
822         {
823             collapsePath(path, context);
824             expandPath(path, context);
825         }
826     }
827
828
829     public boolean equals(Object JavaDoc obj)
830     {
831         if (!(obj instanceof HtmlTree))
832         {
833             return false;
834         }
835         HtmlTree other = (HtmlTree) obj;
836
837         return other.getId().equals(getId());
838     }
839
840
841     public int hashCode()
842     {
843         return getClientId(FacesContext.getCurrentInstance()).hashCode();
844     }
845
846
847     public void addToModelListeners()
848     {
849         Collection listeners = getModel(FacesContext.getCurrentInstance()).getTreeModelListeners();
850         long currentTime = System.currentTimeMillis();
851         boolean found = false;
852
853         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
854         {
855             ModelListener listener = (ModelListener) iterator.next();
856
857             if (listener.getId() == internalId)
858             {
859                 found = true;
860             } else if (currentTime - listener.getLastAccessTime() > expireListeners)
861             {
862                 iterator.remove();
863             }
864         }
865         if (!found)
866         {
867             listeners.add(new ModelListener(internalId));
868         }
869     }
870
871
872     private void processModelEvents()
873     {
874         Collection listeners = getModel(FacesContext.getCurrentInstance()).getTreeModelListeners();
875
876         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
877         {
878             ModelListener listener = (ModelListener) iterator.next();
879
880             if (listener.getId() == internalId)
881             {
882                 for (Iterator events = listener.getEvents().iterator(); events.hasNext();)
883                 {
884                     Event event = (Event) events.next();
885                     event.process(this);
886                     events.remove();
887                 }
888                 break;
889             }
890         }
891     }
892
893
894     public void collapseAll()
895     {
896         HtmlTreeNode root = getRootNode();
897         FacesContext context = FacesContext.getCurrentInstance();
898         collapsePath(root.getPath(), context);
899         for (int i = 0; i < root.getChildren().size(); i++)
900         {
901             HtmlTreeNode child = (HtmlTreeNode) (root.getChildren().get(i));
902             collapsePath(child.getPath(), context);
903             if (!child.isLeaf(context))
904             {
905                 collapseChildren(context, child);
906             }
907         }
908     }
909
910
911     private void collapseChildren(FacesContext context, HtmlTreeNode parent)
912     {
913         for (int i = 0; i < parent.getChildren().size(); i++)
914         {
915             HtmlTreeNode child = (HtmlTreeNode) (parent.getChildren().get(i));
916             collapsePath(child.getPath(), context);
917             if (!child.isLeaf(context))
918             {
919                 collapseChildren(context, child);
920             }
921         }
922
923     }
924
925
926     public void expandAll()
927     {
928         HtmlTreeNode root = getRootNode();
929         FacesContext context = FacesContext.getCurrentInstance();
930         expandPath(root.getPath(), context);
931         for (int i = 0; i < root.getChildren().size(); i++)
932         {
933             HtmlTreeNode child = (HtmlTreeNode) (root.getChildren().get(i));
934             expandPath(child.getPath(), context);
935             if (!child.isLeaf(context))
936             {
937                 expandChildren(context, child);
938             }
939         }
940     }
941
942
943     private void expandChildren(FacesContext context, HtmlTreeNode parent)
944     {
945         for (int i = 0; i < parent.getChildren().size(); i++)
946         {
947             HtmlTreeNode child = (HtmlTreeNode) (parent.getChildren().get(i));
948             expandPath(child.getPath(), context);
949             if (!child.isLeaf(context))
950             {
951                 expandChildren(context, child);
952             }
953         }
954     }
955
956     public static String JavaDoc getDefaultImagePath(String JavaDoc relativePathInResourceFolder)
957     {
958         return AddResource.getResourceMappedPath(HtmlTree.class, relativePathInResourceFolder, null);
959     }
960
961     private static class ModelListener implements TreeModelListener
962     {
963
964         private long lastAccessTime = System.currentTimeMillis();
965
966         private LinkedList events = new LinkedList();
967
968         int id;
969
970
971         public ModelListener(int id)
972         {
973             this.id = id;
974         }
975
976
977         public List getEvents()
978         {
979             lastAccessTime = System.currentTimeMillis();
980             return events;
981         }
982
983
984         public int getId()
985         {
986             return id;
987         }
988
989
990         public long getLastAccessTime()
991         {
992             return lastAccessTime;
993         }
994
995
996         public void treeNodesChanged(TreeModelEvent e)
997         {
998             events.addLast(new Event(EVENT_CHANGED, e));
999         }
1000
1001
1002        public void treeNodesInserted(TreeModelEvent e)
1003        {
1004            events.addLast(new Event(EVENT_INSERTED, e));
1005        }
1006
1007
1008        public void treeNodesRemoved(TreeModelEvent e)
1009        {
1010            events.addLast(new Event(EVENT_REMOVED, e));
1011        }
1012
1013
1014        public void treeStructureChanged(TreeModelEvent e)
1015        {
1016            events.addLast(new Event(EVENT_STRUCTURE_CHANGED, e));
1017        }
1018    }
1019
1020
1021    private static class Event
1022    {
1023
1024        private int kind;
1025
1026        private TreeModelEvent event;
1027
1028
1029        public Event(int kind, TreeModelEvent event)
1030        {
1031            this.kind = kind;
1032            this.event = event;
1033        }
1034
1035
1036        public void process(HtmlTree tree)
1037        {
1038            switch (kind)
1039            {
1040                case EVENT_CHANGED:
1041                    tree.treeNodesChanged(event);
1042                    break;
1043                case EVENT_INSERTED:
1044                    tree.treeNodesInserted(event);
1045                    break;
1046                case EVENT_REMOVED:
1047                    tree.treeNodesRemoved(event);
1048                    break;
1049                case EVENT_STRUCTURE_CHANGED:
1050                    tree.treeStructureChanged(event);
1051                    break;
1052            }
1053        }
1054    }
1055}
Popular Tags