KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > wings > STree


1 /*
2  * $Id: STree.java,v 1.13 2005/04/08 17:41:34 blueshift Exp $
3  * Copyright 2000,2005 wingS development team.
4  *
5  * This file is part of wingS (http://www.j-wings.org).
6  *
7  * wingS is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License
9  * as published by the Free Software Foundation; either version 2.1
10  * of the License, or (at your option) any later version.
11  *
12  * Please see COPYING for the complete licence.
13  */

14 package org.wings;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.wings.plaf.TreeCG;
19 import org.wings.tree.SDefaultTreeSelectionModel;
20 import org.wings.tree.STreeCellRenderer;
21 import org.wings.tree.STreeSelectionModel;
22
23 import javax.swing.event.*;
24 import javax.swing.tree.*;
25 import java.awt.*;
26 import java.util.ArrayList JavaDoc;
27
28 /**
29  * @author <a HREF="mailto:haaf@mercatis.de">Armin Haaf</a>
30  * @version $Revision: 1.13 $
31  */

32 public class STree extends SComponent implements LowLevelEventListener, Scrollable {
33     /**
34      * Tree selection model. See {@link STreeSelectionModel#setSelectionMode(int)}
35      */

36     public static final int NO_SELECTION = SListSelectionModel.NO_SELECTION;
37
38     /**
39      * Tree selection model. See {@link STreeSelectionModel#setSelectionMode(int)}
40      */

41     public static final int SINGLE_SELECTION = SListSelectionModel.SINGLE_SELECTION;
42
43     /**
44      * Tree selection model. See {@link STreeSelectionModel#setSelectionMode(int)}
45      */

46     public static final int SINGLE_INTERVAL_SELECTION = SListSelectionModel.SINGLE_INTERVAL_SELECTION;
47
48     /**
49      * Tree selection model. See {@link STreeSelectionModel#setSelectionMode(int)}
50      */

51     public static final int MULTIPLE_SELECTION = SListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
52
53     /**
54      * Tree selection model. See {@link STreeSelectionModel#setSelectionMode(int)}
55      */

56     public static final int MULTIPLE_INTERVAL_SELECTION = SListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
57
58     private final transient static Log log = LogFactory.getLog(STree.class);
59
60     private int nodeIndentDepth;
61
62     /**
63      * Creates and returns a sample TreeModel. Used primarily for beanbuilders.
64      * to show something interesting.
65      *
66      * @return the default TreeModel
67      */

68     protected static TreeModel getDefaultTreeModel() {
69         DefaultMutableTreeNode root = new DefaultMutableTreeNode("STree");
70         DefaultMutableTreeNode parent;
71
72         parent = new DefaultMutableTreeNode("colors");
73         root.add(parent);
74         parent.add(new DefaultMutableTreeNode("blue"));
75         parent.add(new DefaultMutableTreeNode("violet"));
76         parent.add(new DefaultMutableTreeNode("red"));
77         parent.add(new DefaultMutableTreeNode("yellow"));
78
79         parent = new DefaultMutableTreeNode("sports");
80         root.add(parent);
81         parent.add(new DefaultMutableTreeNode("basketball"));
82         parent.add(new DefaultMutableTreeNode("soccer"));
83         parent.add(new DefaultMutableTreeNode("football"));
84         parent.add(new DefaultMutableTreeNode("hockey"));
85
86         parent = new DefaultMutableTreeNode("food");
87         root.add(parent);
88         parent.add(new DefaultMutableTreeNode("hot dogs"));
89         parent.add(new DefaultMutableTreeNode("pizza"));
90         parent.add(new DefaultMutableTreeNode("ravioli"));
91         parent.add(new DefaultMutableTreeNode("bananas"));
92         return new DefaultTreeModel(root);
93     }
94
95     protected TreeModel model;
96
97     transient protected TreeModelListener treeModelListener;
98
99     protected STreeCellRenderer renderer;
100
101     protected STreeSelectionModel selectionModel;
102
103     /**
104      * store here all delayed expansion events
105      */

106     private ArrayList JavaDoc delayedExpansionEvents;
107
108     /**
109      * store here expansion paths that will be processed after procession the
110      * request.
111      */

112     protected final ArrayList JavaDoc requestedExpansionPaths = new ArrayList JavaDoc();
113
114     protected AbstractLayoutCache treeState = new VariableHeightLayoutCache();
115
116     /**
117      * Implementation of the {@link Scrollable} interface.
118      */

119     protected Rectangle viewport;
120
121     /** @see LowLevelEventListener#isEpochCheckEnabled() */
122     protected boolean epochCheckEnabled = true;
123
124
125     /**
126      * used to forward the selection to the selection Listeners of the tree
127      */

128     private final TreeSelectionListener forwardSelectionEvent =
129             new TreeSelectionListener() {
130                 public void valueChanged(TreeSelectionEvent e) {
131                     fireTreeSelectionEvent(e);
132                 }
133             };
134
135     public STree(TreeModel model) {
136         super();
137         setModel(model);
138         setRootVisible(true);
139         setSelectionModel(new SDefaultTreeSelectionModel());
140     }
141
142     public STree() {
143         this(getDefaultTreeModel());
144     }
145
146     public void addTreeSelectionListener(TreeSelectionListener tsl) {
147         addEventListener(TreeSelectionListener.class, tsl);
148     }
149
150     public void removeTreeSelectionListener(TreeSelectionListener tsl) {
151         removeEventListener(TreeSelectionListener.class, tsl);
152     }
153
154     protected void fireTreeSelectionEvent(TreeSelectionEvent e) {
155         // Guaranteed to return a non-null array
156
Object JavaDoc[] listeners = getListenerList();
157         // Process the listeners last to first, notifying
158
// those that are interested in this event
159
for (int i = listeners.length - 2; i >= 0; i -= 2) {
160             if (listeners[i] == TreeSelectionListener.class) {
161                 ((TreeSelectionListener) listeners[i + 1]).valueChanged(e);
162             }
163         }
164         reload();
165     }
166
167     /**
168      * Adds a listener for <code>TreeWillExpand</code> events.
169      *
170      * @param tel a <code>TreeWillExpandListener</code> that will be notified
171      * when a tree node will be expanded or collapsed (a "negative
172      * expansion")
173      */

174     public void addTreeWillExpandListener(TreeWillExpandListener tel) {
175         addEventListener(TreeWillExpandListener.class, tel);
176     }
177
178     /**
179      * Removes a listener for <code>TreeWillExpand</code> events.
180      *
181      * @param tel the <code>TreeWillExpandListener</code> to remove
182      */

183     public void removeTreeWillExpandListener(TreeWillExpandListener tel) {
184         removeEventListener(TreeWillExpandListener.class, tel);
185     }
186
187
188     /**
189      * Notifies all listeners that have registered interest for
190      * notification on this event type. The event instance
191      * is lazily created using the <code>path</code> parameter.
192      *
193      * @param path the <code>TreePath</code> indicating the node that was
194      * expanded
195      * @see EventListenerList
196      */

197     public void fireTreeWillExpand(TreePath path, boolean expand)
198             throws ExpandVetoException {
199
200         // Guaranteed to return a non-null array
201
Object JavaDoc[] listeners = getListenerList();
202         TreeExpansionEvent e = null;
203         // Process the listeners last to first, notifying
204
// those that are interested in this event
205
for (int i = listeners.length - 2; i >= 0; i -= 2) {
206             if (listeners[i] == TreeWillExpandListener.class) {
207                 // Lazily create the event:
208
if (e == null)
209                     e = new TreeExpansionEvent(this, path);
210
211                 if (expand) {
212                     ((TreeWillExpandListener) listeners[i + 1]).
213                             treeWillExpand(e);
214                 } else {
215                     ((TreeWillExpandListener) listeners[i + 1]).
216                             treeWillCollapse(e);
217                 }
218             }
219         }
220     }
221
222     public void addTreeExpansionListener(TreeExpansionListener tel) {
223         addEventListener(TreeExpansionListener.class, tel);
224     }
225
226     public void removeTreeExpansionListener(TreeExpansionListener tel) {
227         removeEventListener(TreeExpansionListener.class, tel);
228     }
229
230
231     private static class DelayedExpansionEvent {
232         TreeExpansionEvent expansionEvent;
233         boolean expansion;
234
235         DelayedExpansionEvent(TreeExpansionEvent e, boolean b) {
236             expansionEvent = e;
237             expansion = b;
238         }
239
240     }
241
242     protected void addDelayedExpansionEvent(TreeExpansionEvent e,
243                                             boolean expansion) {
244         if (delayedExpansionEvents == null) {
245             delayedExpansionEvents = new ArrayList JavaDoc();
246         }
247
248         delayedExpansionEvents.add(new DelayedExpansionEvent(e, expansion));
249     }
250
251     protected void fireDelayedExpansionEvents() {
252         if (delayedExpansionEvents != null &&
253                 !getSelectionModel().getDelayEvents()) {
254             for (int i = 0; i < delayedExpansionEvents.size(); i++) {
255                 DelayedExpansionEvent e =
256                         (DelayedExpansionEvent) delayedExpansionEvents.get(i);
257
258                 fireTreeExpansionEvent(e.expansionEvent, e.expansion);
259             }
260             delayedExpansionEvents.clear();
261         }
262     }
263
264
265     /**
266      * Notify all listeners that have registered interest for
267      * notification on this event type. The event instance
268      * is lazily created using the parameters passed into
269      * the fire method.
270      *
271      * @param path the TreePath indicating the node that was expanded
272      * @see EventListenerList
273      */

274     protected void fireTreeExpanded(TreePath path) {
275         fireTreeExpansionEvent(new TreeExpansionEvent(this, path), true);
276     }
277
278     protected void fireTreeExpansionEvent(TreeExpansionEvent e, boolean expansion) {
279         if (getSelectionModel().getDelayEvents()) {
280             addDelayedExpansionEvent(e, expansion);
281         } else {
282             // Guaranteed to return a non-null array
283
Object JavaDoc[] listeners = getListenerList();
284             // Process the listeners last to first, notifying
285
// those that are interested in this event
286
for (int i = listeners.length - 2; i >= 0; i -= 2) {
287                 if (listeners[i] == TreeExpansionListener.class) {
288                     if (expansion)
289                         ((TreeExpansionListener) listeners[i + 1]).treeExpanded(e);
290                     else
291                         ((TreeExpansionListener) listeners[i + 1]).treeCollapsed(e);
292                 }
293             }
294         }
295     }
296
297     /**
298      * Notify all listeners that have registered interest for
299      * notification on this event type. The event instance
300      * is lazily created using the parameters passed into
301      * the fire method.
302      *
303      * @param path the TreePath indicating the node that was collapsed
304      * @see EventListenerList
305      */

306     public void fireTreeCollapsed(TreePath path) {
307         fireTreeExpansionEvent(new TreeExpansionEvent(this, path), false);
308     }
309
310     protected void processRequestedExpansionPaths() {
311         getSelectionModel().setDelayEvents(true);
312
313         for (int i = 0; i < requestedExpansionPaths.size(); i++) {
314             try {
315                 TreePath path = (TreePath) requestedExpansionPaths.get(i);
316                 togglePathExpansion(path);
317             } catch (ExpandVetoException ex) {
318                 // do not expand...
319
}
320         }
321         requestedExpansionPaths.clear();
322         getSelectionModel().setDelayEvents(false);
323     }
324
325     public void fireIntermediateEvents() {
326         processRequestedExpansionPaths();
327
328         getSelectionModel().fireDelayedIntermediateEvents();
329     }
330
331     public void fireFinalEvents() {
332         super.fireFinalEvents();
333         fireDelayedExpansionEvents();
334         getSelectionModel().fireDelayedFinalEvents();
335     }
336
337     /** @see LowLevelEventListener#isEpochCheckEnabled() */
338     public boolean isEpochCheckEnabled() {
339         return epochCheckEnabled;
340     }
341
342     /** @see LowLevelEventListener#isEpochCheckEnabled() */
343     public void setEpochCheckEnabled(boolean epochCheckEnabled) {
344         this.epochCheckEnabled = epochCheckEnabled;
345     }
346
347     public void setRootVisible(boolean rootVisible) {
348         treeState.setRootVisible(rootVisible);
349     }
350
351
352     public boolean isRootVisible() {
353         return treeState.isRootVisible();
354     }
355
356
357     public void setModel(TreeModel m) {
358         if (model != null && treeModelListener != null)
359             model.removeTreeModelListener(treeModelListener);
360         model = m;
361         treeState.setModel(m);
362
363         if (model != null) {
364             if (treeModelListener == null)
365                 treeModelListener = createTreeModelListener();
366
367             if (treeModelListener != null)
368                 model.addTreeModelListener(treeModelListener);
369
370             // Mark the root as expanded, if it isn't a leaf.
371
if (!model.isLeaf(model.getRoot()))
372                 treeState.setExpandedState(new TreePath(model.getRoot()), true);
373         }
374     }
375
376
377     public TreeModel getModel() {
378         return model;
379     }
380
381
382     public int getRowCount() {
383         return treeState.getRowCount();
384     }
385
386
387     public TreePath getPathForRow(int row) {
388         return treeState.getPathForRow(row);
389     }
390
391
392     protected int fillPathForAbsoluteRow(int row, Object JavaDoc node, ArrayList JavaDoc path) {
393         // and check if it is the
394
if (row == 0) {
395             return 0;
396         } // end of if ()
397

398         for (int i = 0; i < model.getChildCount(node); i++) {
399             path.add(model.getChild(node, i));
400             row = fillPathForAbsoluteRow(row - 1, model.getChild(node, i), path);
401             if (row == 0) {
402                 return 0;
403             } // end of if ()
404
path.remove(path.size() - 1);
405         }
406         return row;
407     }
408
409     public TreePath getPathForAbsoluteRow(int row) {
410         // fill path in this array
411
ArrayList JavaDoc path = new ArrayList JavaDoc(10);
412
413         path.add(model.getRoot());
414         fillPathForAbsoluteRow(row, model.getRoot(), path);
415
416         return new TreePath(path.toArray());
417     }
418
419     /**
420      * Sets the tree's selection model. When a null value is specified
421      * an empty electionModel is used, which does not allow selections.
422      *
423      * @param selectionModel the TreeSelectionModel to use, or null to
424      * disable selections
425      * @see TreeSelectionModel
426      */

427     public void setSelectionModel(STreeSelectionModel selectionModel) {
428         if (this.selectionModel != null)
429             this.selectionModel.removeTreeSelectionListener(forwardSelectionEvent);
430
431         if (selectionModel != null)
432             selectionModel.addTreeSelectionListener(forwardSelectionEvent);
433
434         if (selectionModel == null)
435             this.selectionModel = SDefaultTreeSelectionModel.NO_SELECTION_MODEL;
436         else
437             this.selectionModel = selectionModel;
438     }
439
440     /**
441      * Returns the model for selections. This should always return a
442      * non-null value. If you don't want to allow anything to be selected
443      * set the selection model to null, which forces an empty
444      * selection model to be used.
445      *
446      * @see #setSelectionModel
447      */

448     public STreeSelectionModel getSelectionModel() {
449         return selectionModel;
450     }
451
452     /**
453      * Returns JTreePath instances representing the path between index0
454      * and index1 (including index1).
455      *
456      * @param index0 an int specifying a display row, where 0 is the
457      * first row in the display
458      * @param index1 an int specifying a second display row
459      * @return an array of TreePath objects, one for each node between
460      * index0 and index1, inclusive
461      */

462     protected TreePath[] getPathBetweenRows(int index0, int index1) {
463         int newMinIndex = Math.min(index0, index1);
464         int newMaxIndex = Math.max(index0, index1);
465
466         TreePath[] selection = new TreePath[newMaxIndex - newMinIndex + 1];
467
468         for (int i = newMinIndex; i <= newMaxIndex; i++) {
469             selection[i - newMinIndex] = getPathForRow(i);
470         }
471
472         return selection;
473     }
474
475     /**
476      * Selects the node identified by the specified path. If any
477      * component of the path is hidden (under a collapsed node), it is
478      * exposed (made viewable).
479      *
480      * @param path the TreePath specifying the node to select
481      */

482     public void setSelectionPath(TreePath path) {
483         getSelectionModel().setSelectionPath(path);
484     }
485
486     /**
487      * Selects the nodes identified by the specified array of paths.
488      * If any component in any of the paths is hidden (under a collapsed
489      * node), it is exposed (made viewable).
490      *
491      * @param paths an array of TreePath objects that specifies the nodes
492      * to select
493      */

494     public void setSelectionPaths(TreePath[] paths) {
495         getSelectionModel().setSelectionPaths(paths);
496     }
497
498     /**
499      * Selects the node at the specified row in the display.
500      *
501      * @param row the row to select, where 0 is the first row in
502      * the display
503      */

504     public void setSelectionRow(int row) {
505         int[] rows = {row};
506         setSelectionRows(rows);
507     }
508
509     /**
510      * Selects the nodes corresponding to each of the specified rows
511      * in the display.
512      *
513      * @param rows an array of ints specifying the rows to select,
514      * where 0 indicates the first row in the display
515      */

516     public void setSelectionRows(int[] rows) {
517         if (rows == null)
518             return;
519
520         TreePath paths[] = new TreePath[rows.length];
521         for (int i = 0; i < rows.length; i++) {
522             paths[i] = getPathForRow(i);
523         }
524
525         setSelectionPaths(paths);
526     }
527
528     /**
529      * Adds the node identified by the specified TreePath to the current
530      * selection. If any component of the path isn't visible, it is
531      * made visible.
532      *
533      * @param path the TreePath to add
534      */

535     public void addSelectionPath(TreePath path) {
536         getSelectionModel().addSelectionPath(path);
537     }
538
539     /**
540      * Adds each path in the array of paths to the current selection. If
541      * any component of any of the paths isn't visible, it is
542      * made visible.
543      *
544      * @param paths an array of TreePath objects that specifies the nodes
545      * to add
546      */

547     public void addSelectionPaths(TreePath[] paths) {
548         getSelectionModel().addSelectionPaths(paths);
549     }
550
551     /**
552      * Adds the path at the specified row to the current selection.
553      *
554      * @param row an int specifying the row of the node to add,
555      * where 0 is the first row in the display
556      */

557     public void addSelectionRow(int row) {
558         int[] rows = {row};
559         addSelectionRows(rows);
560     }
561
562     /**
563      * Adds the paths at each of the specified rows to the current selection.
564      *
565      * @param rows an array of ints specifying the rows to add,
566      * where 0 indicates the first row in the display
567      */

568     public void addSelectionRows(int[] rows) {
569         if (rows != null) {
570             int numRows = rows.length;
571             TreePath[] paths = new TreePath[numRows];
572
573             for (int counter = 0; counter < numRows; counter++)
574                 paths[counter] = getPathForRow(rows[counter]);
575             addSelectionPaths(paths);
576         }
577     }
578
579     /**
580      * Returns the last path component in the first node of the current
581      * selection.
582      *
583      * @return the last Object in the first selected node's TreePath,
584      * or null if nothing is selected
585      * @see TreePath#getLastPathComponent
586      */

587     public Object JavaDoc getLastSelectedPathComponent() {
588         Object JavaDoc obj = null;
589         TreePath selPath = getSelectionModel().getSelectionPath();
590         if (selPath != null) {
591             obj = selPath.getLastPathComponent();
592         }
593         return obj;
594     }
595
596     /**
597      * Returns the path to the first selected node.
598      *
599      * @return the TreePath for the first selected node, or null if
600      * nothing is currently selected
601      */

602     public TreePath getSelectionPath() {
603         return getSelectionModel().getSelectionPath();
604     }
605
606     /**
607      * Returns the paths of all selected values.
608      *
609      * @return an array of TreePath objects indicating the selected
610      * nodes, or null if nothing is currently selected.
611      */

612     public TreePath[] getSelectionPaths() {
613         return getSelectionModel().getSelectionPaths();
614     }
615
616     /**
617      * Returns all of the currently selected rows.
618      *
619      * @return an array of ints that identifies all currently selected rows
620      * where 0 is the first row in the display
621      */

622     public int[] getSelectionRows() {
623         return getSelectionModel().getSelectionRows();
624     }
625
626     /**
627      * Returns the number of nodes selected.
628      *
629      * @return the number of nodes selected
630      */

631     public int getSelectionCount() {
632         return selectionModel.getSelectionCount();
633     }
634
635     /**
636      * Gets the first selected row.
637      *
638      * @return an int designating the first selected row, where 0 is the
639      * first row in the display
640      */

641     public int getMinSelectionRow() {
642         return getSelectionModel().getMinSelectionRow();
643     }
644
645     /**
646      * Gets the last selected row.
647      *
648      * @return an int designating the last selected row, where 0 is the
649      * first row in the display
650      */

651     public int getMaxSelectionRow() {
652         return getSelectionModel().getMaxSelectionRow();
653     }
654
655     /**
656      * Returns the row index of the last node added to the selection.
657      *
658      * @return an int giving the row index of the last node added to the
659      * selection, where 0 is the first row in the display
660      */

661     public int getLeadSelectionRow() {
662         return getSelectionModel().getLeadSelectionRow();
663     }
664
665     /**
666      * Returns the path of the last node added to the selection.
667      *
668      * @return the TreePath of the last node added to the selection.
669      */

670     public TreePath getLeadSelectionPath() {
671         return getSelectionModel().getLeadSelectionPath();
672     }
673
674     /**
675      * Returns true if the item identified by the path is currently selected.
676      *
677      * @param path a TreePath identifying a node
678      * @return true if the node is selected
679      */

680     public boolean isPathSelected(TreePath path) {
681         return getSelectionModel().isPathSelected(path);
682     }
683
684     /**
685      * Returns true if the node identitifed by row is selected.
686      *
687      * @param row an int specifying a display row, where 0 is the first
688      * row in the display
689      * @return true if the node is selected
690      */

691     public boolean isRowSelected(int row) {
692         return getSelectionModel().isRowSelected(row);
693     }
694
695     /**
696      * Removes the nodes between index0 and index1, inclusive, from the
697      * selection.
698      *
699      * @param index0 an int specifying a display row, where 0 is the
700      * first row in the display
701      * @param index1 an int specifying a second display row
702      */

703     public void removeSelectionInterval(int index0, int index1) {
704         TreePath[] paths = getPathBetweenRows(index0, index1);
705         this.getSelectionModel().removeSelectionPaths(paths);
706     }
707
708     /**
709      * Removes the node identified by the specified path from the current
710      * selection.
711      *
712      * @param path the TreePath identifying a node
713      */

714     public void removeSelectionPath(TreePath path) {
715         getSelectionModel().removeSelectionPath(path);
716     }
717
718     /**
719      * Removes the nodes identified by the specified paths from the
720      * current selection.
721      *
722      * @param paths an array of TreePath objects that specifies the nodes
723      * to remove
724      */

725     public void removeSelectionPaths(TreePath[] paths) {
726         getSelectionModel().removeSelectionPaths(paths);
727     }
728
729     /**
730      * Removes the path at the index <code>row</code> from the current
731      * selection.
732      *
733      * @param row the row identifying the node to remove
734      */

735     public void removeSelectionRow(int row) {
736         int[] rows = {row};
737         removeSelectionRows(rows);
738     }
739
740     public void removeSelectionRows(int[] rows) {
741         TreePath[] paths = new TreePath[rows.length];
742         for (int i = 0; i < rows.length; i++)
743             paths[i] = getPathForRow(rows[i]);
744         removeSelectionPaths(paths);
745     }
746
747     public int getMaximumExpandedDepth() {
748         int max = 0;
749         for (int i = 0; i < getRowCount(); i++)
750             max = Math.max(max, getPathForRow(i).getPathCount());
751         return max;
752     }
753
754     /**
755      * Expand this tree row.
756      * If tree is inside a {@link SScrollPane} try to
757      * adjust pane, so that as much as possible new
758      * nodes are visible.
759      *
760      * @param p the TreePath to expand
761      */

762     public void expandRow(TreePath p) {
763         treeState.setExpandedState(p, true);
764         /*
765           if ( viewport != null )
766           {
767           int ccount = model.getChildCount( p.getLastPathComponent() );
768           if ( ccount + 1 <= viewport.height )
769           viewport.y += ccount;
770           else
771           viewport.y = treeState.getRowForPath( p );
772             
773           }
774         */

775         fireTreeExpanded(p);
776         reload();
777     }
778
779     public void expandRow(int row) {
780         expandRow(getPathForRow(row));
781     }
782
783     public void collapseRow(TreePath p) {
784         treeState.setExpandedState(p, false);
785         fireTreeCollapsed(p);
786         reload();
787     }
788
789     public void collapseRow(int row) {
790         collapseRow(getPathForRow(row));
791     }
792
793     public boolean isVisible(TreePath path) {
794         if (path != null) {
795             TreePath parentPath = path.getParentPath();
796
797             if (parentPath != null)
798                 return isExpanded(parentPath);
799
800             // Root.
801
return true;
802         }
803
804         return false;
805     }
806
807     public boolean isExpanded(TreePath path) {
808         return treeState.isExpanded(path);
809     }
810
811     protected void togglePathSelection(TreePath path) {
812         if (path != null) {
813             if (isPathSelected(path)) {
814                 removeSelectionPath(path);
815             } else {
816                 addSelectionPath(path);
817             }
818         }
819     }
820
821     protected void togglePathExpansion(TreePath path)
822             throws ExpandVetoException {
823         if (path != null) {
824             if (treeState.isExpanded(path)) {
825                 fireTreeWillExpand(path, false);
826                 collapseRow(path);
827             } else {
828                 fireTreeWillExpand(path, true);
829                 expandRow(path);
830             }
831         }
832     }
833
834     /**
835      * This is for plafs only!
836      * With this parameter the tree expands the given node
837      */

838     public String JavaDoc getExpansionParameter(int row, boolean absolute) {
839         return (absolute ? "j" : "h") + row;
840     }
841
842     /**
843      * This is for plafs only!
844      * With this parameter the tree selects the given node
845      */

846     public String JavaDoc getSelectionParameter(int row, boolean absolute) {
847         return (absolute ? "a" : "b") + row;
848     }
849
850
851     public void processLowLevelEvent(String JavaDoc action, String JavaDoc[] values) {
852         processKeyEvents(values);
853
854         getSelectionModel().setDelayEvents(true);
855         for (int i = 0; i < values.length; i++) {
856             if (values[i].length() < 2) continue; // incorrect format
857

858             int row = Integer.parseInt(values[i].substring(1));
859
860             if (row < 0) continue; // row not found...
861

862             if (values[i].charAt(0) == 'b') {
863                 TreePath path = getPathForRow(row);
864                 //selection
865
if (path != null) {
866                     togglePathSelection(path);
867                 }
868             } else if (values[i].charAt(0) == 'h') {
869                 TreePath path = getPathForRow(row);
870                 //selection
871
if (path != null) {
872                     requestedExpansionPaths.add(path);
873                 }
874             } else if (values[i].charAt(0) == 'a') {
875                 TreePath path = getPathForAbsoluteRow(row);
876                 //selection
877
if (path != null) {
878                     togglePathSelection(path);
879                 }
880             } else if (values[i].charAt(0) == 'j') {
881                 TreePath path = getPathForAbsoluteRow(row);
882                 //selection
883
if (path != null) {
884                     requestedExpansionPaths.add(path);
885                 }
886             }
887         }
888         SForm.addArmedComponent(this);
889         getSelectionModel().setDelayEvents(false);
890     }
891
892     public void setNodeIndentDepth(int depth) {
893         nodeIndentDepth = depth;
894     }
895
896     public int getNodeIndentDepth() {
897         return nodeIndentDepth;
898     }
899
900     public void setCellRenderer(STreeCellRenderer x) {
901         renderer = x;
902     }
903
904     public STreeCellRenderer getCellRenderer() {
905         return renderer;
906     }
907
908     /**
909      * Creates an instance of TreeModelHandler.
910      */

911     protected TreeModelListener createTreeModelListener() {
912         return new TreeModelHandler();
913     }
914
915
916     /**
917      * Listens to the model and updates the expandedState accordingly
918      * when nodes are removed, or changed.
919      */

920     protected class TreeModelHandler implements TreeModelListener {
921         public void treeNodesChanged(TreeModelEvent e) {
922             if (e == null)
923                 return;
924             treeState.treeNodesChanged(e);
925             reload();
926         }
927
928         public void treeNodesInserted(TreeModelEvent e) {
929             if (e == null)
930                 return;
931             treeState.treeNodesInserted(e);
932             reload();
933         }
934
935         public void treeStructureChanged(TreeModelEvent e) {
936             if (e == null)
937                 return;
938             treeState.treeStructureChanged(e);
939             reload();
940         }
941
942         public void treeNodesRemoved(TreeModelEvent e) {
943             if (e == null)
944                 return;
945             treeState.treeNodesRemoved(e);
946             reload();
947         }
948     }
949
950     public void setParent(SContainer p) {
951         super.setParent(p);
952         if (getCellRendererPane() != null)
953             getCellRendererPane().setParent(p);
954     }
955
956     protected void setParentFrame(SFrame f) {
957         super.setParentFrame(f);
958         if (getCellRendererPane() != null)
959             getCellRendererPane().setParentFrame(f);
960     }
961
962
963     // do not initalize with null!
964
private SCellRendererPane cellRendererPane = new SCellRendererPane();
965
966
967     public SCellRendererPane getCellRendererPane() {
968         return cellRendererPane;
969     }
970
971     /**
972      * Returns the maximum size of this tree.
973      *
974      * @return maximum size
975      */

976     public Rectangle getScrollableViewportSize() {
977         return new Rectangle(0, 0, 1, getRowCount());
978     }
979
980     /*
981      * Setzt den anzuzeigenden Teil
982      */

983     public void setViewportSize(Rectangle d) {
984         Rectangle oldViewport = viewport;
985         viewport = d;
986         if ((viewport == null && oldViewport != null) ||
987                 (viewport != null && !viewport.equals(oldViewport)))
988             reload();
989     }
990
991     public Rectangle getViewportSize() {
992         return viewport;
993     }
994
995     public Dimension getPreferredExtent() {
996         return null;
997     }
998
999     public void setCG(TreeCG cg) {
1000        super.setCG(cg);
1001    }
1002}
1003
1004
1005
Popular Tags