annotate java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/SimpleShapeEdge.java @ 1:71ff0735df5a

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