fiore@3
|
1 /*
|
fiore@3
|
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
|
fiore@3
|
3
|
fiore@3
|
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
fiore@3
|
5
|
fiore@3
|
6 This program is free software: you can redistribute it and/or modify
|
fiore@3
|
7 it under the terms of the GNU General Public License as published by
|
fiore@3
|
8 the Free Software Foundation, either version 3 of the License, or
|
fiore@3
|
9 (at your option) any later version.
|
fiore@3
|
10
|
fiore@3
|
11 This program is distributed in the hope that it will be useful,
|
fiore@3
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
fiore@3
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
fiore@3
|
14 GNU General Public License for more details.
|
fiore@3
|
15
|
fiore@3
|
16 You should have received a copy of the GNU General Public License
|
fiore@3
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
fiore@3
|
18 */
|
fiore@3
|
19 package uk.ac.qmul.eecs.ccmi.diagrammodel;
|
fiore@3
|
20
|
fiore@3
|
21 import java.util.ArrayList;
|
fiore@3
|
22 import java.util.Collections;
|
fiore@3
|
23 import java.util.List;
|
fiore@3
|
24
|
fiore@3
|
25 import javax.swing.tree.DefaultMutableTreeNode;
|
fiore@3
|
26
|
fiore@3
|
27 /**
|
fiore@3
|
28 * This class represent a general node in a TreeModel
|
fiore@3
|
29 *
|
fiore@3
|
30 */
|
fiore@3
|
31 @SuppressWarnings("serial")
|
fiore@3
|
32 public abstract class DiagramTreeNode extends DefaultMutableTreeNode {
|
fiore@3
|
33 /**
|
fiore@3
|
34 * Creates a tree node with the default user object. The default user object has no label. Therefore
|
fiore@3
|
35 * this node will have no label when displayed on a tree.
|
fiore@3
|
36 */
|
fiore@3
|
37 public DiagramTreeNode() {
|
fiore@3
|
38 super();
|
fiore@3
|
39 notes = "";
|
fiore@3
|
40 userObject = new UserObject();
|
fiore@3
|
41 setSuperClassUserObject(userObject);
|
fiore@3
|
42 bookmarkKeys = new ArrayList<String>();
|
fiore@3
|
43 }
|
fiore@3
|
44
|
fiore@3
|
45 /**
|
fiore@3
|
46 * Creates a tree node, holding the user object passed as argument. The label of the
|
fiore@3
|
47 * tree node will be the string returned by {@code userObject.toString()}
|
fiore@3
|
48 *
|
fiore@3
|
49 * @param userObject the user object for this tree node
|
fiore@3
|
50 *
|
fiore@3
|
51 * @see javax.swing.tree.DefaultMutableTreeNode
|
fiore@3
|
52 */
|
fiore@3
|
53 public DiagramTreeNode(Object userObject) {
|
fiore@3
|
54 this();
|
fiore@3
|
55 setUserObject(userObject);
|
fiore@3
|
56 }
|
fiore@3
|
57
|
fiore@3
|
58 /**
|
fiore@3
|
59 * Each DiagramModelTreeNode keeps track of the bookmarks it has been assigned. Bookmarks
|
fiore@3
|
60 * will affect how this tree node will be represented on a JTree: when a tree node is bookmarked
|
fiore@3
|
61 * an apex appears at the right of its name.
|
fiore@3
|
62 *
|
fiore@3
|
63 * @param key the bookmark
|
fiore@3
|
64 * @return true if this bookmark inner collection changed as a result of the call
|
fiore@3
|
65 */
|
fiore@3
|
66 boolean addBookmarkKey(String key){
|
fiore@3
|
67 return bookmarkKeys.add(key);
|
fiore@3
|
68 }
|
fiore@3
|
69
|
fiore@3
|
70 /**
|
fiore@3
|
71 * Removes a bookmark key from the inner collection.
|
fiore@3
|
72 *
|
fiore@3
|
73 * @param key the key to remove
|
fiore@3
|
74 * @return true if this bookmark inner collection changed as a result of the call
|
fiore@3
|
75 */
|
fiore@3
|
76 boolean removeBookmarkKey(String key){
|
fiore@3
|
77 return bookmarkKeys.remove(key);
|
fiore@3
|
78 }
|
fiore@3
|
79
|
fiore@3
|
80 /**
|
fiore@3
|
81 * Returns the the bookmark keys currently associated to this tree node in the tree model.
|
fiore@3
|
82 *
|
fiore@3
|
83 * @return a n unmodifiable list of strings used as keys for bookmarks
|
fiore@3
|
84 */
|
fiore@3
|
85 public List<String> getBookmarkKeys(){
|
fiore@3
|
86 return Collections.unmodifiableList(bookmarkKeys);
|
fiore@3
|
87 }
|
fiore@3
|
88
|
fiore@3
|
89 public String getNotes(){
|
fiore@3
|
90 return notes;
|
fiore@3
|
91 }
|
fiore@3
|
92
|
fiore@3
|
93 /**
|
fiore@3
|
94 * Set a note for this tree node. A Note is a text the user wants to attach to a tree node. Notes
|
fiore@3
|
95 * will affect how this tree node will be represented on a JTree: when a tree node is assigned a note
|
fiore@3
|
96 * a number sign (#) appears at the right of its name.
|
fiore@3
|
97 *
|
fiore@3
|
98 * @param note the text of the note
|
fiore@3
|
99 * @param source used by {@code DiagramElement} to trigger {@code ElementChangeEvents}
|
fiore@3
|
100 *
|
fiore@3
|
101 * @see DiagramElement#setNotes(String, Object)
|
fiore@3
|
102 */
|
fiore@3
|
103 protected void setNotes(String note, Object source){
|
fiore@3
|
104 this.notes = note;
|
fiore@3
|
105 }
|
fiore@3
|
106
|
fiore@3
|
107 @Override
|
fiore@3
|
108 public DiagramTreeNode getParent(){
|
fiore@3
|
109 return (DiagramTreeNode)super.getParent();
|
fiore@3
|
110 }
|
fiore@3
|
111
|
fiore@3
|
112 @Override
|
fiore@3
|
113 public DiagramTreeNode getChildAt(int i){
|
fiore@3
|
114 return (DiagramTreeNode)super.getChildAt(i);
|
fiore@3
|
115 }
|
fiore@3
|
116
|
fiore@3
|
117 @Override
|
fiore@3
|
118 public DiagramTreeNode getRoot(){
|
fiore@3
|
119 return (DiagramTreeNode)super.getRoot();
|
fiore@3
|
120 }
|
fiore@3
|
121
|
fiore@3
|
122 @Override
|
fiore@3
|
123 public void setUserObject(Object userObject){
|
fiore@3
|
124 ((UserObject)this.userObject).setObject(userObject);
|
fiore@3
|
125 }
|
fiore@3
|
126
|
fiore@3
|
127 @Override
|
fiore@3
|
128 public Object getUserObject(){
|
fiore@3
|
129 return userObject;
|
fiore@3
|
130 }
|
fiore@3
|
131
|
fiore@3
|
132 /**
|
fiore@3
|
133 * Return a String representing this object for this tree node in a way more suitable
|
fiore@3
|
134 * for a text to speech synthesizer to read, than toString().
|
fiore@3
|
135 *
|
fiore@3
|
136 * @return a String suitable for text to speech synthesis
|
fiore@3
|
137 */
|
fiore@3
|
138 public String spokenText(){
|
fiore@3
|
139 return ((UserObject)userObject).spokenText();
|
fiore@3
|
140 }
|
fiore@3
|
141
|
fiore@3
|
142 /**
|
fiore@3
|
143 * Returns a more detailed description of the tree node than {@link #spokenText()}.
|
fiore@3
|
144 *
|
fiore@3
|
145 * @return a description of the tree node
|
fiore@3
|
146 */
|
fiore@3
|
147 public String detailedSpokenText(){
|
fiore@3
|
148 return spokenText();
|
fiore@3
|
149 }
|
fiore@3
|
150
|
fiore@3
|
151 /**
|
fiore@3
|
152 * returns the tree node name "as it is", without any decoration such as notes, bookmarks or cardinality;
|
fiore@3
|
153 * unlike the String returned by toString.
|
fiore@3
|
154 *
|
fiore@3
|
155 * @return the tree node name
|
fiore@3
|
156 */
|
fiore@3
|
157 public String getName(){
|
fiore@3
|
158 return ((UserObject)userObject).getName();
|
fiore@3
|
159 }
|
fiore@3
|
160
|
fiore@3
|
161 @Override
|
fiore@3
|
162 public boolean isRoot(){
|
fiore@3
|
163 return false; // root node overwrites this method
|
fiore@3
|
164 }
|
fiore@3
|
165
|
fiore@3
|
166 @Override
|
fiore@3
|
167 public DiagramTreeNode getLastLeaf() {
|
fiore@3
|
168 return (DiagramTreeNode)super.getLastLeaf();
|
fiore@3
|
169 }
|
fiore@3
|
170
|
fiore@3
|
171 @Override
|
fiore@3
|
172 public DiagramTreeNode getNextLeaf() {
|
fiore@3
|
173 return (DiagramTreeNode)super.getNextLeaf();
|
fiore@3
|
174 }
|
fiore@3
|
175
|
fiore@3
|
176 @Override
|
fiore@3
|
177 public DiagramTreeNode getNextNode() {
|
fiore@3
|
178 return (DiagramTreeNode)super.getNextNode();
|
fiore@3
|
179 }
|
fiore@3
|
180
|
fiore@3
|
181 @Override
|
fiore@3
|
182 public DiagramTreeNode getNextSibling() {
|
fiore@3
|
183 return (DiagramTreeNode)super.getNextSibling();
|
fiore@3
|
184 }
|
fiore@3
|
185
|
fiore@3
|
186 @Override
|
fiore@3
|
187 public DiagramTreeNode getPreviousLeaf() {
|
fiore@3
|
188 return (DiagramTreeNode)super.getPreviousLeaf();
|
fiore@3
|
189 }
|
fiore@3
|
190
|
fiore@3
|
191 @Override
|
fiore@3
|
192 public DiagramTreeNode getPreviousNode() {
|
fiore@3
|
193 return (DiagramTreeNode)super.getPreviousNode();
|
fiore@3
|
194 }
|
fiore@3
|
195
|
fiore@3
|
196 @Override
|
fiore@3
|
197 public DiagramTreeNode getPreviousSibling() {
|
fiore@3
|
198 return (DiagramTreeNode)super.getPreviousSibling();
|
fiore@3
|
199 }
|
fiore@3
|
200
|
fiore@3
|
201 private void setSuperClassUserObject(Object u){
|
fiore@3
|
202 super.setUserObject(u);
|
fiore@3
|
203 }
|
fiore@3
|
204
|
fiore@3
|
205 private UserObject getUserObjectInstance(){
|
fiore@3
|
206 return new UserObject();
|
fiore@3
|
207 }
|
fiore@3
|
208
|
fiore@3
|
209 /**
|
fiore@3
|
210 * The bookmarks, involving this node, entered by the user in the DiagramTree this node belongs to.
|
fiore@3
|
211 */
|
fiore@3
|
212 protected List<String> bookmarkKeys;
|
fiore@3
|
213 /**
|
fiore@3
|
214 * The notes set by the user for this node.
|
fiore@3
|
215 */
|
fiore@3
|
216 protected String notes;
|
fiore@3
|
217 /* hides the DefaultMutableTreeNode protected field */
|
fiore@3
|
218 private Object userObject;
|
fiore@3
|
219 /**
|
fiore@3
|
220 * The character that is appended to the label of this node when the user enters some notes for it.
|
fiore@3
|
221 */
|
fiore@3
|
222 protected static final char NOTES_CHAR = '#';
|
fiore@3
|
223 /**
|
fiore@3
|
224 * The character that is appended to the label of this node when it's bookmarked by the user.
|
fiore@3
|
225 */
|
fiore@3
|
226 protected static final char BOOKMARK_CHAR = '\'';
|
fiore@3
|
227 /**
|
fiore@3
|
228 * The string that is appended to the spoken text of this node when the user enters some notes for it.
|
fiore@3
|
229 *
|
fiore@3
|
230 * @see #spokenText()
|
fiore@3
|
231 */
|
fiore@3
|
232 protected static final String BOOKMARK_SPEAK = ", bookmarked";
|
fiore@3
|
233 /**
|
fiore@3
|
234 * The string that is appended to the spoken text of this node when it's bookmarked by the user.
|
fiore@3
|
235 *
|
fiore@3
|
236 * @see #spokenText()
|
fiore@3
|
237 */
|
fiore@3
|
238 protected static final String NOTES_SPEAK = ", has notes";
|
fiore@3
|
239
|
fiore@3
|
240 @Override
|
fiore@3
|
241 public Object clone(){
|
fiore@3
|
242 DiagramTreeNode clone = (DiagramTreeNode )super.clone();
|
fiore@3
|
243 clone.notes = "";
|
fiore@3
|
244 clone.bookmarkKeys = new ArrayList<String>();
|
fiore@3
|
245 clone.userObject = clone.getUserObjectInstance();
|
fiore@3
|
246 clone.setSuperClassUserObject(clone.userObject);
|
fiore@3
|
247 return clone;
|
fiore@3
|
248 }
|
fiore@3
|
249
|
fiore@3
|
250 /* this works as a wrapper for the real user object in order to provide */
|
fiore@3
|
251 /* decoration on the treeNode label to signal and/or bookmarks */
|
fiore@3
|
252 private class UserObject {
|
fiore@3
|
253 private Object object;
|
fiore@3
|
254
|
fiore@3
|
255 public UserObject(){
|
fiore@3
|
256 object = "";
|
fiore@3
|
257 }
|
fiore@3
|
258 public void setObject(Object o){
|
fiore@3
|
259 this.object = o;
|
fiore@3
|
260 }
|
fiore@3
|
261
|
fiore@3
|
262 @Override
|
fiore@3
|
263 public boolean equals(Object o){
|
fiore@3
|
264 return this.object.equals(o);
|
fiore@3
|
265 }
|
fiore@3
|
266
|
fiore@3
|
267 @Override
|
fiore@3
|
268 public String toString(){
|
fiore@3
|
269 StringBuilder builder = new StringBuilder(object.toString());
|
fiore@3
|
270 if(!"".equals(notes)){
|
fiore@3
|
271 builder.append(NOTES_CHAR);
|
fiore@3
|
272 }
|
fiore@3
|
273 if(!bookmarkKeys.isEmpty())
|
fiore@3
|
274 builder.append(BOOKMARK_CHAR);
|
fiore@3
|
275 return builder.toString();
|
fiore@3
|
276 }
|
fiore@3
|
277
|
fiore@3
|
278 public String spokenText(){
|
fiore@3
|
279 StringBuilder builder = new StringBuilder(object.toString());
|
fiore@3
|
280 if(!"".equals(notes)){
|
fiore@3
|
281 builder.append(NOTES_SPEAK);
|
fiore@3
|
282 }
|
fiore@3
|
283 if(!bookmarkKeys.isEmpty())
|
fiore@3
|
284 builder.append(BOOKMARK_SPEAK);
|
fiore@3
|
285 return builder.toString();
|
fiore@3
|
286 }
|
fiore@3
|
287
|
fiore@3
|
288 public String getName(){
|
fiore@3
|
289 return object.toString();
|
fiore@3
|
290 }
|
fiore@3
|
291 }
|
fiore@3
|
292 }
|