dbdeb6832713621d8b74dd4745e35460bb2e3232
[jSite2.git] / src / net / pterodactylus / util / swing / SortableTreeNode.java
1 /*
2  * jSite2 - SortableMutableTreeNode.java -
3  * Copyright © 2008 David Roden
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 package net.pterodactylus.util.swing;
21
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Comparator;
25 import java.util.Enumeration;
26 import java.util.List;
27
28 import javax.swing.tree.MutableTreeNode;
29 import javax.swing.tree.TreeNode;
30
31 /**
32  * {@link MutableTreeNode} subclass that allows to sort its children.
33  * 
34  * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
35  */
36 public class SortableTreeNode implements MutableTreeNode {
37
38         /** The parent node. */
39         private MutableTreeNode parentNode;
40
41         /** The user-defined object. */
42         private Object userObject;
43
44         /** Whether this node allows children. */
45         private boolean allowsChildren;
46
47         /** The children of this node. */
48         private List<MutableTreeNode> children = new ArrayList<MutableTreeNode>();
49
50         /**
51          * Creates a new sortable tree node.
52          * 
53          * @param allowsChildren
54          *            <code>true</code> if this node allows children,
55          *            <code>false</code> otherwise
56          */
57         public SortableTreeNode(boolean allowsChildren) {
58                 this(null, allowsChildren);
59         }
60
61         /**
62          * Creates a new sortable tree node that contains the given user-defined
63          * object.
64          * 
65          * @param userObject
66          *            The user-defined object
67          */
68         public SortableTreeNode(Object userObject) {
69                 this(userObject, true);
70         }
71
72         /**
73          * Creates a new sortable tree node that contains the given user-defined
74          * object.
75          * 
76          * @param userObject
77          *            The user-defined object
78          * @param allowsChildren
79          *            <code>true</code> if this node allows children,
80          *            <code>false</code> otherwise
81          */
82         public SortableTreeNode(Object userObject, boolean allowsChildren) {
83                 this.allowsChildren = allowsChildren;
84                 this.userObject = userObject;
85         }
86
87         //
88         // ACCESSORS
89         //
90
91         /**
92          * {@inheritDoc}
93          */
94         public boolean getAllowsChildren() {
95                 return allowsChildren;
96         }
97
98         /**
99          * {@inheritDoc}
100          */
101         public TreeNode getChildAt(int childIndex) {
102                 return children.get(childIndex);
103         }
104
105         /**
106          * {@inheritDoc}
107          */
108         public int getChildCount() {
109                 return children.size();
110         }
111
112         /**
113          * {@inheritDoc}
114          */
115         public int getIndex(TreeNode node) {
116                 return children.indexOf(node);
117         }
118
119         /**
120          * {@inheritDoc}
121          */
122         public TreeNode getParent() {
123                 return parentNode;
124         }
125
126         /**
127          * Returns the user-defined object.
128          * 
129          * @return The user-defined object
130          */
131         public Object getUserObject() {
132                 return userObject;
133         }
134
135         /**
136          * {@inheritDoc}
137          */
138         public boolean isLeaf() {
139                 return children.isEmpty();
140         }
141
142         //
143         // ACTIONS
144         //
145
146         /**
147          * Adds the given node to this node as a child.
148          * 
149          * @param child
150          *            The child node to add
151          */
152         public void add(MutableTreeNode child) {
153                 children.add(child);
154                 child.setParent(this);
155         }
156
157         /**
158          * {@inheritDoc}
159          */
160         public void insert(MutableTreeNode child, int index) {
161                 children.add(index, child);
162         }
163
164         /**
165          * {@inheritDoc}
166          */
167         public void remove(int index) {
168                 children.remove(index);
169         }
170
171         /**
172          * {@inheritDoc}
173          */
174         public void remove(MutableTreeNode node) {
175                 children.remove(node);
176         }
177
178         /**
179          * {@inheritDoc}
180          */
181         public void removeFromParent() {
182                 if (parentNode != null) {
183                         parentNode.remove(this);
184                         parentNode = null;
185                 }
186         }
187
188         /**
189          * {@inheritDoc}
190          */
191         public void setParent(MutableTreeNode newParent) {
192                 parentNode = newParent;
193         }
194
195         /**
196          * {@inheritDoc}
197          */
198         public void setUserObject(Object userObject) {
199                 this.userObject = userObject;
200         }
201
202         /**
203          * Sorts the children of this node.
204          */
205         public void sort() {
206                 Collections.sort(children, new Comparator<MutableTreeNode>() {
207
208                         /**
209                          * {@inheritDoc}
210                          */
211                         @SuppressWarnings( { "synthetic-access", "unchecked" })
212                         public int compare(MutableTreeNode firstNode, MutableTreeNode secondNode) {
213                                 if (!(firstNode instanceof SortableTreeNode) || !(secondNode instanceof SortableTreeNode)) {
214                                         return 0;
215                                 }
216                                 SortableTreeNode firstSortableNode = (SortableTreeNode) firstNode;
217                                 SortableTreeNode secondSortableNode = (SortableTreeNode) secondNode;
218                                 if ((firstSortableNode.userObject == null) && (secondSortableNode.userObject == null)) {
219                                         return 0;
220                                 }
221                                 if ((firstSortableNode.userObject == null) && (secondSortableNode.userObject != null)) {
222                                         return -1;
223                                 }
224                                 if ((firstSortableNode.userObject != null) && (secondSortableNode.userObject == null)) {
225                                         return 1;
226                                 }
227                                 if (!(firstSortableNode.userObject instanceof Comparable) || !(secondSortableNode.userObject instanceof Comparable)) {
228                                         return 0;
229                                 }
230                                 return ((Comparable<Object>) firstSortableNode.userObject).compareTo(secondSortableNode.userObject);
231                         }
232                 });
233         }
234
235         /**
236          * {@inheritDoc}
237          */
238         public Enumeration<?> children() {
239                 return Collections.enumeration(children);
240         }
241
242         /**
243          * {@inheritDoc}
244          */
245         @Override
246         public String toString() {
247                 return (userObject != null) ? userObject.toString() : null;
248         }
249
250 }