comparison java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/SimpleShapeEdge.java @ 0:9418ab7b7f3f

Initial import
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Fri, 16 Dec 2011 17:35:51 +0000
parents
children 9e67171477bc
comparison
equal deleted inserted replaced
-1:000000000000 0:9418ab7b7f3f
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
20 package uk.ac.qmul.eecs.ccmi.simpletemplate;
21
22 import java.awt.Graphics2D;
23 import java.awt.Stroke;
24 import java.awt.geom.Line2D;
25 import java.awt.geom.Point2D;
26 import java.awt.geom.Rectangle2D;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Map;
32
33 import org.w3c.dom.Document;
34 import org.w3c.dom.Element;
35 import org.w3c.dom.NodeList;
36
37 import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramNode;
38 import uk.ac.qmul.eecs.ccmi.gui.Edge;
39 import uk.ac.qmul.eecs.ccmi.gui.GraphElement;
40 import uk.ac.qmul.eecs.ccmi.gui.LineStyle;
41 import uk.ac.qmul.eecs.ccmi.gui.Node;
42 import uk.ac.qmul.eecs.ccmi.gui.persistence.PersistenceManager;
43 import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
44
45 @SuppressWarnings("serial")
46 public class SimpleShapeEdge extends Edge {
47
48 public SimpleShapeEdge(String type, LineStyle style, ArrowHead[] heads, String[] availableEndDescriptions, int minAttachedNodes, int maxAttachedNodes) {
49 super(type,availableEndDescriptions,minAttachedNodes,maxAttachedNodes,style);
50 this.heads = heads;
51 currentHeads = new HashMap<Node,ArrowHead>();
52 }
53
54 @Override
55 public boolean removeNode(DiagramNode n){
56 currentHeads.remove(n);
57 return super.removeNode(n);
58 }
59
60 @Override
61 public void draw(Graphics2D g2) {
62 Stroke oldStroke = g2.getStroke();
63 g2.setStroke(getStyle().getStroke());
64
65 /* straight line */
66 if(points.isEmpty()){
67 Line2D line = getSegment(getNodeAt(0),getNodeAt(1));
68 g2.draw(line);
69
70 /* draw arrow heads if any */
71 ArrowHead h = currentHeads.get(getNodeAt(0));
72 if( h != null && h != ArrowHead.TAIL){
73 Line2D revLine = getSegment(getNodeAt(1),getNodeAt(0));
74 h.draw(g2, revLine.getP1(), revLine.getP2());
75 }
76 h = currentHeads.get(getNodeAt(1));
77 if( h != null && h != ArrowHead.TAIL){
78 h.draw(g2, line.getP1(), line.getP2());
79 }
80
81 /* draw labels if any */
82 String label;
83 if((label = getEndLabel(getNodeAt(0))) != null){
84 EdgeDrawSupport.drawString(g2, line.getP2(), line.getP1(), currentHeads.get(getNodeAt(0)), label, false);
85 }
86 if((label = getEndLabel(getNodeAt(1))) != null){
87 EdgeDrawSupport.drawString(g2, line.getP1(), line.getP2(), currentHeads.get(getNodeAt(1)), label, false);
88 }
89
90 /* draw name if any */
91 if(!getName().isEmpty()){
92 EdgeDrawSupport.drawString(g2, line.getP2(), line.getP1(), null, getName(), true);
93 }
94 if(!"".equals(getNotes()))
95 EdgeDrawSupport.drawMarker(g2,line.getP1(),line.getP2());
96 }else{
97 /* edge with inner points: it can be a multiended(eventually bended) edge or a straight bended edge */
98
99 /* arrow and labels are drawn in the same way in either case */
100 for(InnerPoint p : points){
101 for(GraphElement ge : p.getNeighbours()){
102 g2.draw(getSegment(p,ge));
103 if(ge instanceof Node){ // this is the inner point which is connected to a Node
104 /* draw arrow if any */
105 ArrowHead h = currentHeads.get((Node)ge);
106 if(h != null && h != ArrowHead.TAIL){
107 Line2D line = getSegment(p,ge);
108 h.draw(g2, line.getP1() , line.getP2());
109 }
110
111 /* draw label if any */
112 String label = getEndLabel((Node)ge);
113 if(label != null){
114 Line2D line = getSegment(p,ge);
115 EdgeDrawSupport.drawString(g2, line.getP1(), line.getP2(), currentHeads.get((Node)ge), label, false);
116 }
117 }
118 }
119 p.draw(g2);
120 }
121 /* name is drawn differently :
122 * for multiended edges name is drawn on the master inner point
123 * for two ends bended name is drawn in (about) the middle point of the edge
124 */
125
126 if(masterInnerPoint != null){/* multiended edge */
127 Rectangle2D bounds = masterInnerPoint.getBounds();
128 Point2D p = new Point2D.Double(bounds.getCenterX() - 1,bounds.getCenterY());
129 Point2D q = new Point2D.Double(bounds.getCenterX() + 1,bounds.getCenterY());
130 if(!getName().isEmpty())
131 EdgeDrawSupport.drawString(g2, p, q, null, getName(), true);
132 if(!"".equals(getNotes()))
133 EdgeDrawSupport.drawMarker(g2,p,q);
134 }else{
135 /* straight edge which has been bended */
136 GraphElement ge1 = getNodeAt(0);
137 GraphElement ge2 = getNodeAt(1);
138 InnerPoint c1 = null;
139 InnerPoint c2 = null;
140
141 for(InnerPoint innp : points){
142 if(innp.getNeighbours().contains(ge1)){
143 c1 = innp;
144 }
145 if(innp.getNeighbours().contains(ge2)){
146 c2 = innp;
147 }
148 }
149
150 /* draw name if any */
151 if(!getName().isEmpty()){
152 /* we only have two nodes but the edge has been bended */
153 while((c1 != c2)&&(!c2.getNeighbours().contains(c1))){
154 if(c1.getNeighbours().get(0) == ge1){
155 ge1 = c1;
156 c1 = (InnerPoint)c1.getNeighbours().get(1);
157 }
158 else{
159 ge1 = c1;
160 c1 = (InnerPoint)c1.getNeighbours().get(0);
161 }
162 if(c2.getNeighbours().get(0) == ge2){
163 ge2 = c2;
164 c2 = (InnerPoint)c2.getNeighbours().get(1);
165 }
166 else{
167 ge2 = c2;
168 c2 = (InnerPoint)c2.getNeighbours().get(0);
169 }
170 }
171
172 Point2D p = new Point2D.Double();
173 Point2D q = new Point2D.Double();
174 if(c1 == c2){
175 Rectangle2D bounds = c1.getBounds();
176 p.setLocation( bounds.getCenterX() - 1,bounds.getCenterY());
177 q.setLocation( bounds.getCenterX() + 1,bounds.getCenterY());
178 }else{
179 Rectangle2D bounds = c1.getBounds();
180 p.setLocation( bounds.getCenterX(),bounds.getCenterY());
181 bounds = c2.getBounds();
182 q.setLocation(bounds.getCenterX(),bounds.getCenterY());
183
184 }
185 if(!getName().isEmpty())
186 EdgeDrawSupport.drawString(g2, p, q, null, getName(), true);
187 if(!"".equals(getNotes()))
188 EdgeDrawSupport.drawMarker(g2,p,q);
189 }
190 }
191 }
192 g2.setStroke(oldStroke);
193 }
194
195 public Rectangle2D getBounds() {
196 if(points.isEmpty()){
197 return getSegment(getNodeAt(0), getNodeAt(1)).getBounds2D();
198 }else{
199 Rectangle2D bounds = points.get(0).getBounds();
200 for(InnerPoint p : points){
201 for(GraphElement ge : p.getNeighbours())
202 bounds.add(getSegment(p,ge).getBounds2D());
203 }
204 return bounds;
205 }
206 }
207
208 public ArrowHead[] getHeads() {
209 return heads;
210 }
211
212 @Override
213 public InputStream getSound(){
214 switch(getStyle()){
215 case Dashed : return dashedSound;
216 case Dotted : return dottedSound;
217 default : return straightSound;
218 }
219 }
220
221 @Override
222 public void setEndDescription(DiagramNode diagramNode, int index){
223 Node n = (Node)diagramNode;
224 if(index == NO_END_DESCRIPTION_INDEX){
225 currentHeads.remove(n);
226 super.setEndDescription(n, index);
227 }else{
228 ArrowHead h = heads[index];
229 currentHeads.put(n, h);
230 super.setEndDescription(n, index);
231 }
232 }
233
234 @Override
235 public void encode(Document doc, Element parent, List<Node> nodes){
236 super.encode(doc, parent, nodes);
237 /* add the head attribute to the NODE tag */
238 NodeList nodeTagList = parent.getElementsByTagName(PersistenceManager.NODE);
239 for(int i = 0 ; i< nodeTagList.getLength(); i++){
240 Element nodeTag = (Element)nodeTagList.item(i);
241 String nodeIdAsString = nodeTag.getAttribute(PersistenceManager.ID);
242 long nodeId = Long.parseLong(nodeIdAsString);
243 Node node = null;
244 /* find the node with the id of the tag */
245 for(Node n : nodes)
246 if(n.getId() == nodeId){
247 node = n;
248 break;
249 }
250 String head = (currentHeads.get(node) == null) ? "" : currentHeads.get(node).toString();
251 nodeTag.setAttribute(SimpleShapePrototypePersistenceDelegate.HEAD, head );
252 }
253 }
254
255 @Override
256 public void decode(Document doc, Element edgeTag, Map<String,Node> nodesId) throws IOException{
257 super.decode(doc, edgeTag, nodesId);
258 NodeList nodeList = edgeTag.getElementsByTagName(PersistenceManager.NODE);
259 for(int i=0; i<nodeList.getLength(); i++){
260 Element nodeTag = (Element)nodeList.item(i);
261 String id = nodeTag.getAttribute(PersistenceManager.ID);
262 if(id.isEmpty())
263 throw new IOException();
264 String head = nodeTag.getAttribute(SimpleShapePrototypePersistenceDelegate.HEAD);
265 if(!head.isEmpty()){
266 ArrowHead headShape = null;
267 try{
268 headShape = ArrowHead.getArrowHeadFromString(head);
269 }catch(IOException e){
270 throw e;
271 }
272 currentHeads.put(nodesId.get(id), headShape);
273 int headDescriptionIndex = Edge.NO_END_DESCRIPTION_INDEX;
274 for(int j=0; j<heads.length;j++){
275 if(heads[j].equals(headShape)){
276 headDescriptionIndex = j;
277 break;
278 }
279 }
280 setEndDescription(nodesId.get(id),headDescriptionIndex);
281 }
282 }
283 }
284
285 @Override
286 public int getStipplePattern(){
287 int result = 0;
288 switch(getStyle()){
289 case Solid : result = 0xFFFF;
290 break;
291 case Dashed : result = 0xF0F0;
292 break;
293 case Dotted : result = 0xAAAA ;
294 break;
295 }
296 return result;
297 }
298
299 @Override
300 public Object clone(){
301 return new SimpleShapeEdge(getType(), getStyle(), heads, getAvailableEndDescriptions(), getMinAttachedNodes(), getMaxAttachedNodes() );
302 }
303
304
305
306 private ArrowHead[] heads;
307 private Map<Node,ArrowHead> currentHeads;
308 private static InputStream straightSound;
309 private static InputStream dottedSound;
310 private static InputStream dashedSound;
311
312 static{
313 Class<SimpleShapeEdge> c = SimpleShapeEdge.class;
314 straightSound = c.getResourceAsStream("audio/straightLine.mp3");
315 dottedSound = c.getResourceAsStream("audio/dashedLine.mp3");
316 dashedSound = c.getResourceAsStream("audio/dottedLine.mp3");
317 SoundFactory.getInstance().loadSound(straightSound);
318 SoundFactory.getInstance().loadSound(dottedSound);
319 SoundFactory.getInstance().loadSound(dashedSound);
320 }
321 }