View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.model;
21  
22  import javax.swing.tree.TreeNode;
23  import java.io.Serializable;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.HashSet;
27  import java.util.Set;
28  
29  /**
30   * Manages the expanded state of an tree.
31   *
32   * @since 2.0.0
33   */
34  public class ExpandedState implements Serializable {
35  
36    private int defaultExpandedLevels;
37    private Set<TreePath> expandedSet;
38    private Set<TreePath> collapsedSet;
39  
40    /**
41     * Creates a new state object to store which nodes of a tree are expanded and collapsed in a view.
42     *
43     * @param defaultExpandedLevels All nodes up to this level are expanded by default.
44     */
45    public ExpandedState(final int defaultExpandedLevels) {
46      this.defaultExpandedLevels = defaultExpandedLevels;
47      this.expandedSet = new HashSet<TreePath>();
48      this.collapsedSet = new HashSet<TreePath>();
49    }
50  
51    /**
52     * Checks if a node is expanded.
53     *
54     * @param node The node to check.
55     * @return Is the node expanded?
56     */
57    public boolean isExpanded(final TreeNode node) {
58      final TreePath path = new TreePath(node);
59      return isExpanded(path);
60    }
61  
62    /**
63     * Checks if a node is expanded.
64     *
65     * @param path The path of the node to check.
66     * @return Is the node behind this path is expanded?
67     */
68    public boolean isExpanded(final TreePath path) {
69      if (expandedSet.contains(path)) {
70        return true;
71      }
72      if (collapsedSet.contains(path)) {
73        return false;
74      }
75      return path.getLength() < defaultExpandedLevels;
76    }
77  
78    /**
79     * Expands a single node.
80     *
81     * @param node The node to expand.
82     */
83    public void expand(final TreeNode node) {
84      final TreePath path = new TreePath(node);
85      expand(path);
86    }
87  
88    /**
89     * Expands a single node.
90     *
91     * @param path The path of the node to expand.
92     */
93    public void expand(final TreePath path) {
94      if (path.getLength() >= defaultExpandedLevels) {
95        expandedSet.add(path);
96      } else {
97        collapsedSet.remove(path);
98      }
99    }
100 
101   /**
102    * Expands all nodes that level are lower or equals the parameter level.
103    *
104    * @param level The level to expand.
105    */
106   public void expand(final int level) {
107     final ArrayList<TreePath> toRemove = new ArrayList<TreePath>();
108     if (level > defaultExpandedLevels) {
109       defaultExpandedLevels = level;
110       for (final TreePath treePath : expandedSet) {
111         if (treePath.getLength() < defaultExpandedLevels) {
112           toRemove.add(treePath);
113         }
114       }
115       expandedSet.removeAll(toRemove);
116       collapsedSet.clear();
117     } else {
118       for (final TreePath treePath : collapsedSet) {
119         if (treePath.getLength() < level) {
120           toRemove.add(treePath);
121         }
122       }
123       collapsedSet.removeAll(toRemove);
124     }
125   }
126 
127   /**
128    * Expands a nodes of the tree.
129    */
130   public void expandAll() {
131     defaultExpandedLevels = Integer.MAX_VALUE;
132     expandedSet.clear();
133     collapsedSet.clear();
134   }
135 
136   /**
137    * Collapses a single node.
138    *
139    * @param node The node to collapse.
140    */
141   public void collapse(final TreeNode node) {
142     final TreePath path = new TreePath(node);
143     collapse(path);
144   }
145 
146   /**
147    * Collapses a single node.
148    *
149    * @param path The path of the node to collapse.
150    */
151   public void collapse(final TreePath path) {
152     if (path.getLength() < defaultExpandedLevels) {
153       collapsedSet.add(path);
154     } else {
155       expandedSet.remove(path);
156     }
157   }
158 
159   /**
160    * Collapses all nodes that level are higher or equals the parameter level.
161    *
162    * @param level The level to expand.
163    */
164   public void collapse(int level) {
165     // to use a symmetric algorithm like in expand
166     level--;
167 
168     final ArrayList<TreePath> toRemove = new ArrayList<TreePath>();
169     if (level < defaultExpandedLevels) {
170       defaultExpandedLevels = level;
171       for (final TreePath treePath : collapsedSet) {
172         if (treePath.getLength() >= defaultExpandedLevels) {
173           toRemove.add(treePath);
174         }
175       }
176       collapsedSet.removeAll(toRemove);
177       expandedSet.clear();
178     } else {
179       for (final TreePath treePath : expandedSet) {
180         if (treePath.getLength() >= level) {
181           toRemove.add(treePath);
182         }
183       }
184       expandedSet.removeAll(toRemove);
185     }
186   }
187 
188   /**
189    * Collapses a nodes of the tree.
190    */
191   public void collapseAll() {
192     defaultExpandedLevels = 0;
193     expandedSet.clear();
194     collapsedSet.clear();
195   }
196 
197   /**
198    * Collapses a nodes of the tree. The root node will be expanded.
199    */
200   public void collapseAllButRoot() {
201     defaultExpandedLevels = 1;
202     expandedSet.clear();
203     collapsedSet.clear();
204   }
205 
206   /**
207    * Resets the state to the defaults. After this call, the nodes with level smaller than defaultExpandedLevels
208    * are expanded, the other ones are collapsed.
209    */
210   public void reset() {
211     expandedSet.clear();
212     collapsedSet.clear();
213   }
214 
215   /**
216    * @return A unmodifiable set of paths of the expanded nodes.
217    */
218   public Set<TreePath> getExpandedSet() {
219     return Collections.unmodifiableSet(expandedSet);
220   }
221 
222   /**
223    * @return A unmodifiable set of paths of the collapsed nodes.
224    */
225   public Set<TreePath> getCollapsedSet() {
226     return Collections.unmodifiableSet(collapsedSet);
227   }
228 }