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@3
|
21 import java.util.List;
|
fiore@0
|
22 import java.util.Set;
|
fiore@0
|
23
|
fiore@3
|
24 import uk.ac.qmul.eecs.ccmi.diagrammodel.ElementChangedEvent.PropertyChangeArgs;
|
fiore@0
|
25 import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeProperties.Modifiers;
|
fiore@0
|
26
|
fiore@0
|
27 /**
|
fiore@0
|
28 * This class represents a node in the diagram.
|
fiore@0
|
29 *
|
fiore@0
|
30 */
|
fiore@0
|
31 @SuppressWarnings("serial")
|
fiore@0
|
32 public abstract class DiagramNode extends DiagramElement {
|
fiore@5
|
33 /**
|
fiore@5
|
34 * Constructor to be called by sub classes
|
fiore@5
|
35 *
|
fiore@5
|
36 * @param type the type of the new node. All nodes with this type will be
|
fiore@5
|
37 * put under the same tree node in the tree representation
|
fiore@5
|
38 * @param properties the properties of this node
|
fiore@5
|
39 */
|
fiore@0
|
40 public DiagramNode(String type, NodeProperties properties){
|
fiore@0
|
41 setType(type);
|
fiore@0
|
42 this.properties = properties;
|
fiore@0
|
43 }
|
fiore@0
|
44
|
fiore@0
|
45 /**
|
fiore@0
|
46 * Returns the properties of this node. Be aware that what is returned is the reference
|
fiore@0
|
47 * to the actual NodeProperties object inside this DiagramNode. Thereforemodifying the returned
|
fiore@0
|
48 * object will affect this node.
|
fiore@0
|
49 * @return the properties of this node
|
fiore@0
|
50 */
|
fiore@0
|
51 public NodeProperties getProperties(){
|
fiore@0
|
52 return properties;
|
fiore@0
|
53 }
|
fiore@0
|
54
|
fiore@0
|
55 /**
|
fiore@0
|
56 * Returns a copy of the properties of this node. The modifying the returned object
|
fiore@0
|
57 * won't affect this Node.
|
fiore@0
|
58 * @return Returns a copy of the properties of this node
|
fiore@0
|
59 */
|
fiore@0
|
60 public NodeProperties getPropertiesCopy(){
|
fiore@0
|
61 NodeProperties p = (NodeProperties)properties.clone();
|
fiore@0
|
62 for(String type : properties.getTypes()){
|
fiore@0
|
63 Modifiers modifiers = properties.getModifiers(type);
|
fiore@0
|
64 int index = 0;
|
fiore@0
|
65 for(String value : properties.getValues(type)){
|
fiore@0
|
66 if(properties.getModifiers(type).isNull())
|
fiore@0
|
67 p.addValue(type, value);
|
fiore@0
|
68 else
|
fiore@0
|
69 p.addValue(type, value, modifiers.getIndexes(index++));
|
fiore@0
|
70 }
|
fiore@0
|
71 }
|
fiore@0
|
72 return p;
|
fiore@0
|
73 }
|
fiore@0
|
74
|
fiore@0
|
75 /**
|
fiore@0
|
76 * Set the NodeProperties of this node
|
fiore@0
|
77 * @param properties the properties to set for this node
|
fiore@5
|
78 * @param source the source of the action that triggered this method
|
fiore@0
|
79 */
|
fiore@3
|
80 public void setProperties(NodeProperties properties, Object source){
|
fiore@0
|
81 this.properties = properties;
|
fiore@3
|
82 notifyChange(new ElementChangedEvent(this,this.properties,"properties",source));
|
fiore@0
|
83 }
|
fiore@0
|
84
|
fiore@0
|
85 /**
|
fiore@0
|
86 * Add a property to the NodeProperties of this node
|
fiore@0
|
87 * @see NodeProperties#addValue(String, String)
|
fiore@0
|
88 *
|
fiore@5
|
89 * @param propertyType the type of the property to add
|
fiore@5
|
90 * @param propertyValue the property to add
|
fiore@5
|
91 * @param source the source of the action that triggered this method
|
fiore@0
|
92 */
|
fiore@3
|
93 public void addProperty(String propertyType, String propertyValue, Object source){
|
fiore@0
|
94 getProperties().addValue(propertyType, propertyValue);
|
fiore@0
|
95 int index = getProperties().getValues(propertyType).size() - 1;
|
fiore@3
|
96 notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,index,""),"property.add",source));
|
fiore@0
|
97 }
|
fiore@0
|
98
|
fiore@0
|
99 /**
|
fiore@0
|
100 * Removes a property from the NodeProperties of this node
|
fiore@0
|
101 * @see NodeProperties#removeValue(String, int)
|
fiore@5
|
102 *
|
fiore@5
|
103 * @param propertyType the type of the property to add
|
fiore@5
|
104 * @param valueIndex the index of the property to remove
|
fiore@5
|
105 * @param source the source of the action that triggered this method
|
fiore@0
|
106 */
|
fiore@3
|
107 public void removeProperty(String propertyType, int valueIndex, Object source){
|
fiore@3
|
108 String oldValue = getProperties().getValues(propertyType).get(valueIndex);
|
fiore@0
|
109 getProperties().removeValue(propertyType, valueIndex);
|
fiore@3
|
110 notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,valueIndex,oldValue),"property.remove",source));
|
fiore@0
|
111 }
|
fiore@0
|
112
|
fiore@0
|
113 /**
|
fiore@0
|
114 * Set a property on the NodeProperties of this node to a new value
|
fiore@0
|
115 * @see NodeProperties#setValue(String, int, String)
|
fiore@5
|
116 *
|
fiore@5
|
117 * @param propertyType the type of the property to add
|
fiore@5
|
118 * @param valueIndex the index of the property to remove
|
fiore@5
|
119 * @param newValue the new value for this property
|
fiore@5
|
120 * @param source the source of the action that triggered this method
|
fiore@0
|
121 */
|
fiore@3
|
122 public void setProperty(String propertyType, int valueIndex, String newValue, Object source){
|
fiore@3
|
123 String oldValue = getProperties().getValues(propertyType).get(valueIndex);
|
fiore@0
|
124 getProperties().setValue(propertyType, valueIndex, newValue);
|
fiore@3
|
125 notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,valueIndex,oldValue),"property.set",source));
|
fiore@0
|
126 }
|
fiore@0
|
127
|
fiore@0
|
128 /**
|
fiore@0
|
129 * Removes all the values in the NodeProperties of this node
|
fiore@0
|
130 * @see NodeProperties#clear()
|
fiore@5
|
131 *
|
fiore@5
|
132 * @param source the source of the action that triggered this method
|
fiore@0
|
133 */
|
fiore@3
|
134 public void clearProperties(Object source){
|
fiore@0
|
135 getProperties().clear();
|
fiore@3
|
136 notifyChange(new ElementChangedEvent(this,this,"properties.clear",source));
|
fiore@0
|
137 }
|
fiore@0
|
138
|
fiore@0
|
139 /**
|
fiore@0
|
140 * set the modifier indexes in the NodeProperties of this node
|
fiore@0
|
141 * @see Modifiers#setIndexes(int, Set)
|
fiore@5
|
142 *
|
fiore@5
|
143 * @param propertyType the type of the property to add
|
fiore@5
|
144 * @param propertyValueIndex the index of the property value whose modifiers
|
fiore@5
|
145 * are to be changed
|
fiore@5
|
146 * @param modifierIndexes the new modifiers (identified by their index )
|
fiore@5
|
147 * for this property value
|
fiore@5
|
148 * @param source the source of the action that triggered this method
|
fiore@0
|
149 */
|
fiore@3
|
150 public void setModifierIndexes(String propertyType, int propertyValueIndex, Set<Integer> modifierIndexes,Object source){
|
fiore@3
|
151 StringBuilder oldIndexes = new StringBuilder();
|
fiore@3
|
152 List<String> modifierTypes = getProperties().getModifiers(propertyType).getTypes();
|
fiore@3
|
153 Set<Integer> indexes = getProperties().getModifiers(propertyType).getIndexes(propertyValueIndex);
|
fiore@3
|
154 for(Integer I : indexes){
|
fiore@3
|
155 oldIndexes.append(modifierTypes.get(I)).append(' ');
|
fiore@3
|
156 }
|
fiore@0
|
157 getProperties().getModifiers(propertyType).setIndexes(propertyValueIndex, modifierIndexes);
|
fiore@3
|
158 notifyChange(new ElementChangedEvent(this,new PropertyChangeArgs(propertyType,propertyValueIndex,oldIndexes.toString()),"property.modifiers",source));
|
fiore@0
|
159 }
|
fiore@0
|
160
|
fiore@0
|
161 /**
|
fiore@0
|
162 * Returns a more detailed description of the node than {@link #spokenText()}.
|
fiore@0
|
163 * the description includes which how many properties the node has and
|
fiore@0
|
164 * how many edges are attached to it.
|
fiore@0
|
165 *
|
fiore@0
|
166 * @return a description of the node
|
fiore@0
|
167 */
|
fiore@0
|
168 @Override
|
fiore@0
|
169 public String detailedSpokenText(){
|
fiore@0
|
170 StringBuilder builder = new StringBuilder(getType());
|
fiore@0
|
171 builder.append(' ');
|
fiore@0
|
172 builder.append(getName());
|
fiore@0
|
173 builder.append('.').append(' ');
|
fiore@0
|
174 for(int i=0; i<getChildCount();i++){
|
fiore@3
|
175 DiagramTreeNode treeNode = (DiagramTreeNode) getChildAt(i);
|
fiore@0
|
176 if(treeNode.getChildCount() > 0){
|
fiore@0
|
177 builder.append(treeNode.getChildCount())
|
fiore@0
|
178 .append(' ')
|
fiore@0
|
179 .append(treeNode.getName())
|
fiore@0
|
180 .append(';')
|
fiore@0
|
181 .append(' ');
|
fiore@0
|
182 }
|
fiore@0
|
183 }
|
fiore@0
|
184 return builder.toString();
|
fiore@0
|
185 }
|
fiore@0
|
186
|
fiore@0
|
187 /**
|
fiore@0
|
188 * Returns the number of attached edges
|
fiore@0
|
189 * @return the number of attached edges
|
fiore@0
|
190 */
|
fiore@0
|
191 public abstract int getEdgesNum();
|
fiore@0
|
192
|
fiore@0
|
193 /**
|
fiore@0
|
194 * Returns the attached edge at the specified index
|
fiore@0
|
195 * @param index an index into edge's list
|
fiore@0
|
196 * @return the attached edge at the specified index
|
fiore@0
|
197 */
|
fiore@0
|
198 public abstract DiagramEdge getEdgeAt(int index);
|
fiore@0
|
199
|
fiore@0
|
200 /**
|
fiore@0
|
201 * add an edge to the attached edges list
|
fiore@3
|
202 * @param e the edge to be added
|
fiore@5
|
203 *
|
fiore@5
|
204 * @return {@code true} if internal collection of edges changed as a result of the call
|
fiore@0
|
205 */
|
fiore@0
|
206 public abstract boolean addEdge(DiagramEdge e);
|
fiore@0
|
207
|
fiore@0
|
208 /**
|
fiore@0
|
209 * Removes an edge from the attached edges list
|
fiore@5
|
210 * @param e the edge to be removed
|
fiore@5
|
211 *
|
fiore@5
|
212 * @return {@code true} if internal collection of edges changed as a result of the call
|
fiore@0
|
213 */
|
fiore@0
|
214 public abstract boolean removeEdge(DiagramEdge e);
|
fiore@0
|
215
|
fiore@0
|
216 /**
|
fiore@0
|
217 * Gets the node this node is within.
|
fiore@0
|
218 * @return the parent node, or null if the node
|
fiore@0
|
219 * has no parent
|
fiore@0
|
220 */
|
fiore@0
|
221 public abstract DiagramNode getExternalNode();
|
fiore@0
|
222
|
fiore@0
|
223 /**
|
fiore@0
|
224 * Sets the node this node is within.
|
fiore@0
|
225 * @param node the parent node, or null if the node
|
fiore@0
|
226 * has no parent
|
fiore@0
|
227 */
|
fiore@0
|
228 public abstract void setExternalNode(DiagramNode node);
|
fiore@0
|
229
|
fiore@0
|
230 /**
|
fiore@0
|
231 * Returns the number of internal nodes
|
fiore@0
|
232 * @return the number of internal nodes
|
fiore@0
|
233 */
|
fiore@0
|
234 public abstract int getInternalNodesNum();
|
fiore@0
|
235
|
fiore@0
|
236 /**
|
fiore@0
|
237 * Gets the internal node at the specified index
|
fiore@0
|
238 * @param index an index into internal nodes list
|
fiore@0
|
239 * @return the internal node at the specified index
|
fiore@0
|
240 */
|
fiore@0
|
241 public abstract DiagramNode getInternalNodeAt(int index);
|
fiore@0
|
242
|
fiore@0
|
243 /**
|
fiore@0
|
244 * Adds a node to the internal nodes list.
|
fiore@0
|
245 * @param node the internal node to add
|
fiore@0
|
246 */
|
fiore@0
|
247 public abstract void addInternalNode(DiagramNode node);
|
fiore@0
|
248
|
fiore@0
|
249 /**
|
fiore@0
|
250 * Removes a node from the internal nodes list.
|
fiore@0
|
251 * @param node the internal node to remove
|
fiore@0
|
252 */
|
fiore@0
|
253 public abstract void removeInternalNode(DiagramNode node);
|
fiore@0
|
254
|
fiore@0
|
255 @Override
|
fiore@0
|
256 public Object clone(){
|
fiore@0
|
257 DiagramNode clone = (DiagramNode)super.clone();
|
fiore@0
|
258 clone.properties = (NodeProperties)properties.clone();
|
fiore@0
|
259 return clone;
|
fiore@0
|
260 }
|
fiore@0
|
261
|
fiore@0
|
262 private NodeProperties properties;
|
fiore@0
|
263 }
|