Mercurial > hg > ccmieditor
comparison java/src/uk/ac/qmul/eecs/ccmi/checkboxtree/CheckBoxTree.java @ 3:9e67171477bc
PHANTOM Omni Heptic device release
author | Fiore Martin <fiore@eecs.qmul.ac.uk> |
---|---|
date | Wed, 25 Apr 2012 17:09:09 +0100 |
parents | |
children | d66dd5880081 |
comparison
equal
deleted
inserted
replaced
2:4b2f975e35fa | 3:9e67171477bc |
---|---|
1 /* | |
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool | |
3 | |
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/) | |
5 | |
6 This program is free software: you can redistribute it and/or modify | |
7 it under the terms of the GNU General Public License as published by | |
8 the Free Software Foundation, either version 3 of the License, or | |
9 (at your option) any later version. | |
10 | |
11 This program is distributed in the hope that it will be useful, | |
12 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 GNU General Public License for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 */ | |
19 package uk.ac.qmul.eecs.ccmi.checkboxtree; | |
20 | |
21 import java.awt.event.MouseAdapter; | |
22 import java.awt.event.MouseEvent; | |
23 import java.io.IOException; | |
24 import java.io.InputStream; | |
25 import java.util.Enumeration; | |
26 | |
27 import javax.swing.JTree; | |
28 import javax.swing.tree.DefaultMutableTreeNode; | |
29 import javax.swing.tree.DefaultTreeModel; | |
30 import javax.swing.tree.TreePath; | |
31 import javax.xml.parsers.ParserConfigurationException; | |
32 import javax.xml.parsers.SAXParser; | |
33 import javax.xml.parsers.SAXParserFactory; | |
34 | |
35 import org.xml.sax.SAXException; | |
36 | |
37 | |
38 /** | |
39 * A JTree containing {@code CheckBoxTreeNode} nodes. The tree is built according to an XML file | |
40 * passed as argument to the constructor. | |
41 * The XML file hierarchical structure reflects the structure of the tree. XML tag name can be | |
42 * either {@code selectable} or {@code unselectable}. The former representing tree nodes with a check | |
43 * box associated to it, and the latter a normal tree node, much as a {@link DefaultMutableTreeNode}. | |
44 * Either tags must have an attribute {@code value}, representing the name of the node which will be displayed | |
45 * in the tree. Here is an example of a simple XML file, representing a tree with the tree root (non selectable) having | |
46 * three children, the first of which has, in turn, a child. all the descendants of the root are selectable, but the | |
47 * first child. | |
48 * | |
49 * <pre> | |
50 * {@code | |
51 * <?xml version="1.0" encoding="utf-8"?> | |
52 * <unselectable value="root"> | |
53 * <unselectable value="first child"/> | |
54 * <selectable value="second child"/> | |
55 * <selectable value "third child"> | |
56 * <selectable value="grand child"/> | |
57 * </selectable> | |
58 * </unselectable> | |
59 * } | |
60 * </pre> | |
61 * | |
62 * @see CheckBoxTreeNode | |
63 */ | |
64 @SuppressWarnings("serial") | |
65 public class CheckBoxTree extends JTree { | |
66 public CheckBoxTree(InputStream stream, SetProperties values){ | |
67 super(new DefaultTreeModel(new DefaultMutableTreeNode())); | |
68 this.properties = values; | |
69 getAccessibleContext().setAccessibleName("tree"); | |
70 treeModel = (DefaultTreeModel)getModel(); | |
71 setCellRenderer(new CheckBoxTreeCellRenderer()); | |
72 buildTree(stream); | |
73 /* mouse listener to toggle the selected tree node */ | |
74 addMouseListener(new MouseAdapter(){ | |
75 @Override | |
76 public void mousePressed(MouseEvent e){ | |
77 TreePath path = getPathForLocation(e.getX(),e.getY()); | |
78 if(path == null) | |
79 return; | |
80 CheckBoxTreeNode treeNode = (CheckBoxTreeNode)path.getLastPathComponent(); | |
81 toggleSelection(treeNode); | |
82 } | |
83 }); | |
84 } | |
85 | |
86 /** | |
87 * Builds a CheckBoxTree out of an xml file passed as argument. All the nodes | |
88 * of the tree are marked unchecked. | |
89 * | |
90 * @param stream an input stream to an xml file | |
91 */ | |
92 public CheckBoxTree(InputStream stream){ | |
93 this(stream,null); | |
94 } | |
95 | |
96 /* use a sax parser to build the tree, if an error occurs during the parsing it just stops */ | |
97 private void buildTree(InputStream stream){ | |
98 SAXParserFactory factory = SAXParserFactory.newInstance(); | |
99 try { | |
100 SAXParser saxParser = factory.newSAXParser(); | |
101 XMLHandler handler = new XMLHandler((DefaultTreeModel)getModel(),properties); | |
102 saxParser.parse(stream, handler); | |
103 } catch (IOException e) { | |
104 e.printStackTrace(); | |
105 return; | |
106 } catch (ParserConfigurationException e) { | |
107 e.printStackTrace(); | |
108 return; | |
109 } catch (SAXException e) { | |
110 e.printStackTrace(); | |
111 return; | |
112 } | |
113 } | |
114 | |
115 /** | |
116 * Returns a reference to the properties holding which nodes of the tree are currently checked. | |
117 * @return the properties or {@value null} if the constructor with no properties was used. | |
118 */ | |
119 public SetProperties getProperties(){ | |
120 return properties; | |
121 } | |
122 | |
123 /** | |
124 * Toggle the check box of the tree node passed as argument. If the tree node | |
125 * is not a leaf, then all its descendants will get the new value it. That is, | |
126 * if the tree node becomes selected as a result of the call, then all the descendants | |
127 * will become in turn selected (regardless of their previous state). If it becomes | |
128 * unselected, the descendants will become unselected as well. | |
129 * | |
130 * @param treeNode the tree node to toggle | |
131 */ | |
132 public void toggleSelection(CheckBoxTreeNode treeNode){ | |
133 if(treeNode.isSelectable()){ | |
134 boolean selection = !treeNode.isSelected(); | |
135 treeNode.setSelected(selection); | |
136 if(selection) | |
137 properties.add(treeNode.getPathAsString()); | |
138 else | |
139 properties.remove(treeNode.getPathAsString()); | |
140 treeModel.nodeChanged(treeNode); | |
141 if(!treeNode.isLeaf()){ | |
142 for( @SuppressWarnings("unchecked") | |
143 Enumeration<CheckBoxTreeNode> enumeration = treeNode.depthFirstEnumeration(); enumeration.hasMoreElements();){ | |
144 CheckBoxTreeNode t = enumeration.nextElement(); | |
145 t.setSelected(selection); | |
146 if(selection) | |
147 properties.add(t.getPathAsString()); | |
148 else | |
149 properties.remove(t.getPathAsString()); | |
150 treeModel.nodeChanged(t); | |
151 } | |
152 } | |
153 } | |
154 } | |
155 | |
156 private SetProperties properties; | |
157 private DefaultTreeModel treeModel; | |
158 } |