diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/java/src/uk/ac/qmul/eecs/ccmi/simpletemplate/SimpleShapeEdge.java	Fri Dec 16 17:35:51 2011 +0000
@@ -0,0 +1,321 @@
+/*  
+ CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
+  
+ Copyright (C) 2011  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/  
+
+package uk.ac.qmul.eecs.ccmi.simpletemplate;
+
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import uk.ac.qmul.eecs.ccmi.diagrammodel.DiagramNode;
+import uk.ac.qmul.eecs.ccmi.gui.Edge;
+import uk.ac.qmul.eecs.ccmi.gui.GraphElement;
+import uk.ac.qmul.eecs.ccmi.gui.LineStyle;
+import uk.ac.qmul.eecs.ccmi.gui.Node;
+import uk.ac.qmul.eecs.ccmi.gui.persistence.PersistenceManager;
+import uk.ac.qmul.eecs.ccmi.sound.SoundFactory;
+
+@SuppressWarnings("serial")
+public class SimpleShapeEdge extends Edge {
+
+	public SimpleShapeEdge(String type, LineStyle style, ArrowHead[] heads, String[] availableEndDescriptions, int minAttachedNodes, int maxAttachedNodes) {
+		super(type,availableEndDescriptions,minAttachedNodes,maxAttachedNodes,style);
+		this.heads = heads;
+		currentHeads = new HashMap<Node,ArrowHead>();
+	}
+	
+	@Override
+	public boolean removeNode(DiagramNode n){
+		currentHeads.remove(n);
+		return super.removeNode(n);
+	}
+
+	@Override
+	public void draw(Graphics2D g2) {
+		 Stroke oldStroke = g2.getStroke();
+		 g2.setStroke(getStyle().getStroke());
+		
+		 /* straight line  */
+		 if(points.isEmpty()){
+			 Line2D line = getSegment(getNodeAt(0),getNodeAt(1));
+			 g2.draw(line);
+			 
+			 /* draw arrow heads if any */
+			 ArrowHead h = currentHeads.get(getNodeAt(0));
+			 if( h != null && h != ArrowHead.TAIL){
+				 Line2D revLine = getSegment(getNodeAt(1),getNodeAt(0));
+				 h.draw(g2, revLine.getP1(), revLine.getP2());
+			 }
+			 h = currentHeads.get(getNodeAt(1));
+			 if( h != null && h != ArrowHead.TAIL){
+				 h.draw(g2, line.getP1(), line.getP2());
+			 }
+			 
+			 /* draw labels if any */
+			 String label;
+			 if((label = getEndLabel(getNodeAt(0))) != null){
+				 EdgeDrawSupport.drawString(g2, line.getP2(), line.getP1(), currentHeads.get(getNodeAt(0)), label, false);
+			 }
+			 if((label = getEndLabel(getNodeAt(1))) != null){
+				 EdgeDrawSupport.drawString(g2, line.getP1(), line.getP2(), currentHeads.get(getNodeAt(1)), label, false);
+			 }
+			 
+			 /* draw name if any */
+			 if(!getName().isEmpty()){
+				 EdgeDrawSupport.drawString(g2, line.getP2(), line.getP1(), null, getName(), true);
+			 }
+			 if(!"".equals(getNotes()))
+				 EdgeDrawSupport.drawMarker(g2,line.getP1(),line.getP2());
+		 }else{
+			 /* edge with inner points: it can be a multiended(eventually bended) edge or a straight bended edge */
+			 
+			 /* arrow and labels are drawn in the same way in either case */
+			 for(InnerPoint p : points){
+				 for(GraphElement ge : p.getNeighbours()){
+					 g2.draw(getSegment(p,ge));
+					 if(ge instanceof Node){ // this is the inner point which is connected to a Node 
+						/* draw arrow if any */
+						ArrowHead h = currentHeads.get((Node)ge);
+						if(h != null && h != ArrowHead.TAIL){
+							Line2D line = getSegment(p,ge);
+							h.draw(g2, line.getP1() , line.getP2());
+						}
+						
+						/* draw label if any */
+						String label = getEndLabel((Node)ge);
+						if(label != null){
+							Line2D line = getSegment(p,ge);
+							EdgeDrawSupport.drawString(g2, line.getP1(), line.getP2(), currentHeads.get((Node)ge), label, false);
+						}
+					 }
+				 }
+				 p.draw(g2);
+			 }
+			 /* name is drawn differently : 
+			  * for multiended edges name is drawn on the master inner point
+			  * for two ends bended name is drawn in (about) the middle point of the edge 
+			  */
+			 
+			 if(masterInnerPoint != null){/* multiended edge  */
+				 Rectangle2D bounds = masterInnerPoint.getBounds();
+				 Point2D p = new Point2D.Double(bounds.getCenterX() - 1,bounds.getCenterY());
+				 Point2D q = new Point2D.Double(bounds.getCenterX() + 1,bounds.getCenterY());
+				 if(!getName().isEmpty())
+					 EdgeDrawSupport.drawString(g2, p, q, null, getName(), true);
+				 if(!"".equals(getNotes()))
+					 EdgeDrawSupport.drawMarker(g2,p,q);
+			 }else{
+			 /* straight edge which has been bended */ 
+				 GraphElement ge1 = getNodeAt(0);
+				 GraphElement ge2 = getNodeAt(1);
+				 InnerPoint c1 = null;
+				 InnerPoint c2 = null;
+					 
+				 for(InnerPoint innp : points){
+					 if(innp.getNeighbours().contains(ge1)){
+						 c1 = innp;
+					 }
+					 if(innp.getNeighbours().contains(ge2)){
+						 c2 = innp;
+					 }
+				 }
+				 
+				 /* draw name if any */
+				 if(!getName().isEmpty()){
+					 /* we only have two nodes but the edge has been bended */
+					 while((c1 != c2)&&(!c2.getNeighbours().contains(c1))){
+						 if(c1.getNeighbours().get(0) == ge1){
+							 ge1 = c1;
+							 c1 = (InnerPoint)c1.getNeighbours().get(1);
+						 }
+						 else{
+							 ge1 = c1;
+							 c1 = (InnerPoint)c1.getNeighbours().get(0);
+						 }
+						 if(c2.getNeighbours().get(0) == ge2){
+							 ge2 = c2;
+							 c2 = (InnerPoint)c2.getNeighbours().get(1);
+						 }
+						 else{
+							 ge2 = c2;
+							 c2 = (InnerPoint)c2.getNeighbours().get(0);
+						 }
+					 }
+					 
+					 Point2D p = new Point2D.Double();
+					 Point2D q = new Point2D.Double();
+					 if(c1 == c2){
+						 Rectangle2D bounds = c1.getBounds();
+						 p.setLocation( bounds.getCenterX() - 1,bounds.getCenterY());
+						 q.setLocation(  bounds.getCenterX() + 1,bounds.getCenterY());
+					 }else{
+						 Rectangle2D bounds = c1.getBounds();
+						 p.setLocation( bounds.getCenterX(),bounds.getCenterY());
+						 bounds = c2.getBounds();
+						 q.setLocation(bounds.getCenterX(),bounds.getCenterY());
+						 
+					 }
+					 if(!getName().isEmpty())
+						 EdgeDrawSupport.drawString(g2, p, q, null, getName(), true);
+					 if(!"".equals(getNotes()))
+						 EdgeDrawSupport.drawMarker(g2,p,q);
+				 }
+			 }
+		 }
+		 g2.setStroke(oldStroke);
+	}
+	
+	public Rectangle2D getBounds() {
+		if(points.isEmpty()){
+			return getSegment(getNodeAt(0), getNodeAt(1)).getBounds2D();
+		}else{
+			Rectangle2D bounds = points.get(0).getBounds();
+			for(InnerPoint p : points){
+				for(GraphElement ge : p.getNeighbours())
+					bounds.add(getSegment(p,ge).getBounds2D());
+			}
+			return bounds;
+		}
+	}
+	
+	public ArrowHead[] getHeads() {
+		return heads;
+	}
+	
+	@Override
+	public InputStream getSound(){
+		switch(getStyle()){
+		case Dashed : return dashedSound;
+		case Dotted : return dottedSound;
+		default : return straightSound;
+		}
+	}
+	
+	@Override
+	 public void setEndDescription(DiagramNode diagramNode, int index){
+		Node n = (Node)diagramNode;
+		if(index == NO_END_DESCRIPTION_INDEX){
+			 currentHeads.remove(n);
+			 super.setEndDescription(n, index);
+		 }else{
+			 ArrowHead h = heads[index];
+			 currentHeads.put(n, h);
+			 super.setEndDescription(n, index);
+		 }
+	}
+	
+	@Override
+	public void encode(Document doc, Element parent, List<Node> nodes){
+		super.encode(doc, parent, nodes);
+		/* add the head attribute to the NODE tag */
+		NodeList nodeTagList = parent.getElementsByTagName(PersistenceManager.NODE);
+		for(int i = 0 ; i< nodeTagList.getLength(); i++){
+			Element nodeTag = (Element)nodeTagList.item(i);
+			String nodeIdAsString = nodeTag.getAttribute(PersistenceManager.ID);
+			long nodeId = Long.parseLong(nodeIdAsString);
+			Node node = null;
+			/* find the node with the id of the tag */
+			for(Node n : nodes)
+				if(n.getId() == nodeId){
+					node = n;
+					break;
+				}
+			String head = (currentHeads.get(node) == null) ? "" : currentHeads.get(node).toString();
+			nodeTag.setAttribute(SimpleShapePrototypePersistenceDelegate.HEAD, head );
+		}
+	}
+	
+	@Override
+	public void decode(Document doc, Element edgeTag, Map<String,Node> nodesId) throws IOException{
+		super.decode(doc, edgeTag, nodesId);
+		NodeList nodeList = edgeTag.getElementsByTagName(PersistenceManager.NODE);
+		for(int i=0; i<nodeList.getLength(); i++){
+			Element nodeTag = (Element)nodeList.item(i);
+			String id = nodeTag.getAttribute(PersistenceManager.ID);
+			if(id.isEmpty()) 
+				throw new IOException();
+			String head = nodeTag.getAttribute(SimpleShapePrototypePersistenceDelegate.HEAD);
+			if(!head.isEmpty()){
+				ArrowHead headShape = null;
+				try{
+					headShape = ArrowHead.getArrowHeadFromString(head);
+				}catch(IOException e){
+					throw e;
+				}
+				currentHeads.put(nodesId.get(id), headShape);
+				int headDescriptionIndex = Edge.NO_END_DESCRIPTION_INDEX;
+				for(int j=0; j<heads.length;j++){
+					if(heads[j].equals(headShape)){
+						headDescriptionIndex = j;
+						break;
+					}
+				}
+				setEndDescription(nodesId.get(id),headDescriptionIndex);
+			}
+		}
+	}
+	
+	@Override
+	public int getStipplePattern(){
+		int result = 0;
+		switch(getStyle()){
+		case Solid : result = 0xFFFF;
+		break;
+		case Dashed : result = 0xF0F0;
+		break;
+		case Dotted : result = 0xAAAA ;
+		break;
+		}
+		return result;
+	}
+	
+	@Override
+	public Object clone(){
+		return new SimpleShapeEdge(getType(), getStyle(), heads, getAvailableEndDescriptions(), getMinAttachedNodes(), getMaxAttachedNodes() );
+	}
+	
+	
+
+	private ArrowHead[] heads;	
+	private Map<Node,ArrowHead> currentHeads;
+	private static InputStream straightSound;
+	private static InputStream dottedSound;
+	private static InputStream dashedSound;
+	
+	static{
+		Class<SimpleShapeEdge> c = SimpleShapeEdge.class; 
+		straightSound = c.getResourceAsStream("audio/straightLine.mp3");
+		dottedSound = c.getResourceAsStream("audio/dashedLine.mp3");
+		dashedSound = c.getResourceAsStream("audio/dottedLine.mp3");
+		SoundFactory.getInstance().loadSound(straightSound);
+		SoundFactory.getInstance().loadSound(dottedSound);
+		SoundFactory.getInstance().loadSound(dashedSound);
+	}
+}