001: /*
002: * $Id$ $Revision$ $Date$
003: *
004: * ==============================================================================
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy of
007: * the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations under
015: * the License.
016: */
017: package wicket.extensions.markup.html.tree;
018:
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.Collection;
022: import java.util.Collections;
023: import java.util.HashSet;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Set;
027:
028: import javax.swing.tree.TreeNode;
029:
030: /**
031: * Default implementation of TreeState.
032: * <p>
033: * This implementation tries to be as lightweight as possible.
034: *
035: * @author Matej Knopp
036: */
037: public class DefaultTreeState implements ITreeState, Serializable {
038: private static final long serialVersionUID = 1L;
039:
040: /** Whether multiple selections can be done. */
041: private boolean allowSelectMultiple = false;
042:
043: /** Tree state listeners. */
044: private final List listeners = new ArrayList(1);
045:
046: /**
047: * set of nodes which are collapsed or expanded (depends on nodesCollapsed
048: * veriable).
049: */
050: private final Set nodes = new HashSet();
051:
052: /** Whether the nodes set should be treated as collapsed or expanded. */
053: private boolean nodesCollapsed = true;
054:
055: /** Set selected nodes. */
056: private final Set selectedNodes = new HashSet();
057:
058: /**
059: * @see wicket.extensions.markup.html.tree.ITreeState#addTreeStateListener(wicket.extensions.markup.html.tree.ITreeStateListener)
060: */
061: public void addTreeStateListener(ITreeStateListener l) {
062: if (listeners.contains(l) == false) {
063: listeners.add(l);
064: }
065: }
066:
067: /**
068: * @see wicket.extensions.markup.html.tree.ITreeState#collapseAll()
069: */
070: public void collapseAll() {
071: if (nodes.isEmpty() && nodesCollapsed == false) {
072: // all nodes are already collapsed, do nothing
073: } else {
074: // clear all nodes from the set and sets the nodes as expanded
075: nodes.clear();
076: nodesCollapsed = false;
077:
078: Object[] listenersCopy = listeners.toArray();
079: for (int i = 0; i < listenersCopy.length; i++) {
080: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
081: l.allNodesCollapsed();
082: }
083: }
084: }
085:
086: /**
087: * @see wicket.extensions.markup.html.tree.ITreeState#collapseNode(javax.swing.tree.TreeNode)
088: */
089: public void collapseNode(TreeNode node) {
090: if (nodesCollapsed == true) {
091: nodes.add(node);
092: } else {
093: nodes.remove(node);
094: }
095:
096: Object[] listenersCopy = listeners.toArray();
097: for (int i = 0; i < listenersCopy.length; i++) {
098: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
099: l.nodeCollapsed(node);
100: }
101: }
102:
103: /**
104: * @see wicket.extensions.markup.html.tree.ITreeState#expandAll()
105: */
106: public void expandAll() {
107: if (nodes.isEmpty() && nodesCollapsed == true) {
108: // all nodes are already expanded, do nothing
109: } else {
110: // clear node set and set nodes policy as collapsed
111: nodes.clear();
112: nodesCollapsed = true;
113:
114: Object[] listenersCopy = listeners.toArray();
115: for (int i = 0; i < listenersCopy.length; i++) {
116: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
117: l.allNodesCollapsed();
118: }
119: }
120: }
121:
122: /**
123: * @see wicket.extensions.markup.html.tree.ITreeState#expandNode(javax.swing.tree.TreeNode)
124: */
125: public void expandNode(TreeNode node) {
126: if (nodesCollapsed == false) {
127: nodes.add(node);
128: } else {
129: nodes.remove(node);
130: }
131:
132: Object[] listenersCopy = listeners.toArray();
133: for (int i = 0; i < listenersCopy.length; i++) {
134: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
135: l.nodeExpanded(node);
136: }
137: }
138:
139: /**
140: * @see wicket.extensions.markup.html.tree.ITreeState#getSelectedNodes()
141: */
142: public Collection getSelectedNodes() {
143: return Collections
144: .unmodifiableList(new ArrayList(selectedNodes));
145: }
146:
147: /**
148: * @see wicket.extensions.markup.html.tree.ITreeState#isAllowSelectMultiple()
149: */
150: public boolean isAllowSelectMultiple() {
151: return allowSelectMultiple;
152: }
153:
154: /**
155: * @see wicket.extensions.markup.html.tree.ITreeState#isNodeExpanded(javax.swing.tree.TreeNode)
156: */
157: public boolean isNodeExpanded(TreeNode node) {
158: if (nodesCollapsed == false) {
159: return nodes.contains(node);
160: } else {
161: return nodes.contains(node) == false;
162: }
163: }
164:
165: /**
166: * @see wicket.extensions.markup.html.tree.ITreeState#isNodeSelected(javax.swing.tree.TreeNode)
167: */
168: public boolean isNodeSelected(TreeNode node) {
169: return selectedNodes.contains(node);
170: }
171:
172: /**
173: * @see wicket.extensions.markup.html.tree.ITreeState#removeTreeStateListener(wicket.extensions.markup.html.tree.ITreeStateListener)
174: */
175: public void removeTreeStateListener(ITreeStateListener l) {
176: listeners.remove(l);
177: }
178:
179: /**
180: * @see wicket.extensions.markup.html.tree.ITreeState#selectNode(javax.swing.tree.TreeNode,
181: * boolean)
182: */
183: public void selectNode(TreeNode node, boolean selected) {
184: if (selected == true && selectedNodes.contains(node) == false) {
185: if (isAllowSelectMultiple() == false
186: && selectedNodes.size() > 0) {
187: for (Iterator i = selectedNodes.iterator(); i.hasNext();) {
188: TreeNode current = (TreeNode) i.next();
189: i.remove();
190: Object[] listenersCopy = listeners.toArray();
191: for (int j = 0; j < listenersCopy.length; j++) {
192: ITreeStateListener l = (ITreeStateListener) listenersCopy[j];
193: l.nodeUnselected(current);
194: }
195: }
196: }
197: selectedNodes.add(node);
198: Object[] listenersCopy = listeners.toArray();
199: for (int i = 0; i < listenersCopy.length; i++) {
200: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
201: l.nodeSelected(node);
202: }
203: } else if (selected == false
204: && selectedNodes.contains(node) == true) {
205: selectedNodes.remove(node);
206: Object[] listenersCopy = listeners.toArray();
207: for (int i = 0; i < listenersCopy.length; i++) {
208: ITreeStateListener l = (ITreeStateListener) listenersCopy[i];
209: l.nodeUnselected(node);
210: }
211: }
212: }
213:
214: /**
215: * @see wicket.extensions.markup.html.tree.ITreeState#setAllowSelectMultiple(boolean)
216: */
217: public void setAllowSelectMultiple(boolean value) {
218: this.allowSelectMultiple = value;
219: }
220: }
|