fiore@0
|
1 /*
|
fiore@0
|
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
|
fiore@0
|
3
|
fiore@0
|
4 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
fiore@0
|
5
|
fiore@0
|
6 This program is free software: you can redistribute it and/or modify
|
fiore@0
|
7 it under the terms of the GNU General Public License as published by
|
fiore@0
|
8 the Free Software Foundation, either version 3 of the License, or
|
fiore@0
|
9 (at your option) any later version.
|
fiore@0
|
10
|
fiore@0
|
11 This program is distributed in the hope that it will be useful,
|
fiore@0
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
fiore@0
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
fiore@0
|
14 GNU General Public License for more details.
|
fiore@0
|
15
|
fiore@0
|
16 You should have received a copy of the GNU General Public License
|
fiore@0
|
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
fiore@0
|
18 */
|
fiore@0
|
19 package uk.ac.qmul.eecs.ccmi.diagrammodel;
|
fiore@0
|
20
|
fiore@0
|
21 import java.io.InputStream;
|
fiore@3
|
22 import java.util.concurrent.locks.ReentrantLock;
|
fiore@3
|
23
|
fiore@0
|
24
|
fiore@0
|
25 /**
|
fiore@0
|
26 * A Diagram Element is either a node or an edge of the diagram. It's an abstract
|
fiore@0
|
27 * class which is extended by DiagramEdge and DiagramNode.
|
fiore@0
|
28 *
|
fiore@0
|
29 */
|
fiore@0
|
30 @SuppressWarnings("serial")
|
fiore@3
|
31 public abstract class DiagramElement extends DiagramTreeNode implements Cloneable{
|
fiore@0
|
32
|
fiore@0
|
33 protected DiagramElement(){
|
fiore@0
|
34 name = "";
|
fiore@0
|
35 id = NO_ID;
|
fiore@0
|
36 notifier = DUMMY_NOTIFIER; // initially set to no effect notifier
|
fiore@0
|
37 }
|
fiore@0
|
38
|
fiore@0
|
39 /**
|
fiore@3
|
40 * Returns the type of this diagram element. The type is like the category this element belongs to.
|
fiore@3
|
41 * For instance in a public transport diagram one might have three types of diagram element: tube, train
|
fiore@3
|
42 * and busses.
|
fiore@3
|
43 *
|
fiore@0
|
44 * @return the type of this element
|
fiore@0
|
45 */
|
fiore@0
|
46 public String getType(){
|
fiore@0
|
47 return type;
|
fiore@0
|
48 }
|
fiore@0
|
49
|
fiore@0
|
50 /**
|
fiore@0
|
51 * Set the type of this diagram element. This method should be called as soon as the object is created
|
fiore@0
|
52 * and should not be called anymore on this object.
|
fiore@3
|
53 *
|
fiore@0
|
54 * @param type the type of this element
|
fiore@0
|
55 */
|
fiore@0
|
56 protected void setType(String type){
|
fiore@0
|
57 this.type = type;
|
fiore@0
|
58 }
|
fiore@0
|
59
|
fiore@0
|
60 /**
|
fiore@0
|
61 * Notifies the model of a changed that has happened on this element. If this element is not
|
fiore@0
|
62 * held by any model than this method will have no effect.
|
fiore@0
|
63 * @param evt an event representing the fact that the element is changed
|
fiore@0
|
64 */
|
fiore@0
|
65 protected void notifyChange(ElementChangedEvent evt){
|
fiore@0
|
66 notifier.notifyChange(evt);
|
fiore@0
|
67 }
|
fiore@0
|
68
|
fiore@0
|
69 /**
|
fiore@0
|
70 * returns the tree node name "as it is", without any decoration such as notes, bookmarks or cardinality.
|
fiore@0
|
71 * Unlike the String returned by toString
|
fiore@0
|
72 * @return the tree node name
|
fiore@0
|
73 */
|
fiore@0
|
74 public String getName(){
|
fiore@0
|
75 if(name.isEmpty() && id != NO_ID)
|
fiore@0
|
76 return "new " + getType() + " " + id;
|
fiore@0
|
77 return name;
|
fiore@0
|
78 }
|
fiore@0
|
79
|
fiore@0
|
80 /**
|
fiore@0
|
81 * Sets the name of this element instance.
|
fiore@0
|
82 *
|
fiore@3
|
83 * @param s the string to set as the name
|
fiore@3
|
84 * @param source the source of this action
|
fiore@0
|
85 */
|
fiore@3
|
86 public void setName(String s, Object source){
|
fiore@0
|
87 String name = s;
|
fiore@0
|
88 /* if the user enters an empty string we go back to the default name */
|
fiore@0
|
89 if(s.isEmpty() && id != NO_ID){
|
fiore@0
|
90 name = "new " + getType() + " " + id;
|
fiore@0
|
91 }
|
fiore@0
|
92 setUserObject(name);
|
fiore@0
|
93 this.name = name;
|
fiore@3
|
94 notifyChange(new ElementChangedEvent(this,this,"name",source));
|
fiore@0
|
95 }
|
fiore@0
|
96
|
fiore@0
|
97 /**
|
fiore@0
|
98 * Returns an InputStream to a sound file with the sound of this element
|
fiore@0
|
99 * @return an InputStream
|
fiore@0
|
100 */
|
fiore@0
|
101 public abstract InputStream getSound();
|
fiore@0
|
102
|
fiore@0
|
103 /**
|
fiore@0
|
104 * Sets the if for this element. The id is a number which uniquely identifies this instance
|
fiore@0
|
105 * within a DiagramModel.
|
fiore@0
|
106 * Unlike the name, which can be the same for two different instances.
|
fiore@0
|
107 * @param id a long number which must be greater than 0
|
fiore@0
|
108 * @throws IllegalArgumentException id the id passe as argument is lower or equal to 0.
|
fiore@0
|
109 */
|
fiore@0
|
110 public void setId(long id){
|
fiore@0
|
111 if (id < NO_ID)
|
fiore@0
|
112 throw new IllegalArgumentException();
|
fiore@0
|
113 else
|
fiore@0
|
114 this.id = id;
|
fiore@0
|
115 if(name.isEmpty() && id != NO_ID){
|
fiore@0
|
116 String s = "new " + getType() + " " + id;
|
fiore@0
|
117 this.name = s;
|
fiore@0
|
118 setUserObject(s);
|
fiore@0
|
119 }
|
fiore@0
|
120 }
|
fiore@0
|
121
|
fiore@0
|
122 /**
|
fiore@0
|
123 * Returns the id of this instance of DiagramElement.
|
fiore@0
|
124 * @return a long representing the id of this instance of the element
|
fiore@0
|
125 * or NO_ID if it hasn't got one.
|
fiore@0
|
126 */
|
fiore@0
|
127 public long getId(){
|
fiore@0
|
128 return id;
|
fiore@0
|
129 }
|
fiore@3
|
130
|
fiore@3
|
131 public ReentrantLock getMonitor(){
|
fiore@3
|
132 if(notifier == null)
|
fiore@3
|
133 return null;
|
fiore@3
|
134 return (ReentrantLock)notifier;
|
fiore@3
|
135 }
|
fiore@0
|
136
|
fiore@0
|
137 /**
|
fiore@0
|
138 * Sets the notifier to be used for notification
|
fiore@0
|
139 * following an internal change of the node
|
fiore@0
|
140 * @param notifier the notifier call the notify method(s) on
|
fiore@0
|
141 */
|
fiore@3
|
142 <N extends DiagramNode,E extends DiagramEdge> void setNotifier(DiagramModel<N,E>.ReentrantLockNotifier notifier){
|
fiore@0
|
143 this.notifier = notifier;
|
fiore@0
|
144 }
|
fiore@0
|
145
|
fiore@0
|
146 @Override
|
fiore@0
|
147 public Object clone(){
|
fiore@0
|
148 DiagramElement clone = (DiagramElement)super.clone();
|
fiore@0
|
149 clone.name = "";
|
fiore@0
|
150 clone.id = NO_ID;
|
fiore@0
|
151 return clone;
|
fiore@0
|
152 }
|
fiore@0
|
153
|
fiore@0
|
154 /**
|
fiore@0
|
155 * Returns a description of the DiagramElement passed as argument, suitable
|
fiore@0
|
156 * for logging purposes.
|
fiore@0
|
157 *
|
fiore@0
|
158 * @param de the diagram element to log stuff about
|
fiore@0
|
159 * @return a log entry describing the element passed as agument
|
fiore@0
|
160 */
|
fiore@0
|
161 public static String toLogString(DiagramElement de){
|
fiore@0
|
162 StringBuilder builder = new StringBuilder(de.getName());
|
fiore@0
|
163 builder.append('(');
|
fiore@0
|
164 if(de.getId() == DiagramElement.NO_ID)
|
fiore@0
|
165 builder.append("no id");
|
fiore@0
|
166 else
|
fiore@0
|
167 builder.append(de.getId());
|
fiore@0
|
168 builder.append(')');
|
fiore@0
|
169 return builder.toString();
|
fiore@0
|
170 }
|
fiore@0
|
171
|
fiore@0
|
172 private long id = NO_ID;
|
fiore@0
|
173 private ElementNotifier notifier;
|
fiore@0
|
174 private String type;
|
fiore@0
|
175 private String name;
|
fiore@0
|
176 private static final ElementNotifier DUMMY_NOTIFIER = new ElementNotifier(){
|
fiore@0
|
177 @Override
|
fiore@0
|
178 public void notifyChange(ElementChangedEvent evt) {}
|
fiore@0
|
179 };
|
fiore@0
|
180 /**
|
fiore@0
|
181 * The value returned by getId() if the element instance has not been assigned any id
|
fiore@0
|
182 */
|
fiore@0
|
183 public static final long NO_ID = 0;
|
fiore@0
|
184 }
|