diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/.project b/VioletPlugin/VioletPlugin.ActivityDiagram/.project
new file mode 100644
index 0000000..b18ffd5
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/.project
@@ -0,0 +1,11 @@
+
+
+ VioletPlugin.ActivityDiagram
+
+
+
+
+
+
+
+
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/horstmann.eclipse.code.formatter.xml b/VioletPlugin/VioletPlugin.ActivityDiagram/horstmann.eclipse.code.formatter.xml
new file mode 100644
index 0000000..bef0923
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/horstmann.eclipse.code.formatter.xml
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/pom.xml b/VioletPlugin/VioletPlugin.ActivityDiagram/pom.xml
new file mode 100644
index 0000000..fca7e86
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+ com.horstmann.violet.plugin
+ com.horstmann.violet.plugin.activitydiagram
+ Violet UML Editor Activity Diagram Plugin
+ 2.0.0-SNAPSHOT
+
+ jar
+
+
+ com.horstmann.violet.framework
+ com.horstmann.violet.framework
+ 2.0.0-SNAPSHOT
+
+
+
+
+
+ src/main/resources
+
+
+ src/main/java
+
+ **/*.gif
+ **/*.jpg
+ **/*.properties
+ **/*.xml
+
+
+
+
+
+ maven-compiler-plugin
+ 2.0.2
+
+
+ 1.6
+
+
+
+
+
+
+ web.sourceforge.net
+ Violet's Maven Repository
+
+ sftp://web.sourceforge.net/home/groups/v/vi/violet/htdocs/maven2/repo
+
+
+
+
+
+ violet.repo
+ Violet's Maven repository (public access)
+ http://violet.sourceforge.net/maven2/repo/
+
+
+
\ No newline at end of file
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramConstant.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramConstant.java
new file mode 100644
index 0000000..8604f7f
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramConstant.java
@@ -0,0 +1,8 @@
+package com.horstmann.violet.product.diagram.activity;
+
+public interface ActivityDiagramConstant
+{
+
+ public static final String ACTIVITY_DIAGRAM_STRINGS = "properties.ActivityDiagramGraphStrings";
+
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramGraph.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramGraph.java
new file mode 100644
index 0000000..4cfeb11
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramGraph.java
@@ -0,0 +1,131 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.horstmann.violet.product.diagram.abstracts.AbstractGraph;
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.INode;
+import com.horstmann.violet.product.diagram.abstracts.property.BentStyle;
+import com.horstmann.violet.product.diagram.common.DiagramLinkNode;
+import com.horstmann.violet.product.diagram.common.NoteEdge;
+import com.horstmann.violet.product.diagram.common.NoteNode;
+
+/**
+ * An UML activity diagram.
+ */
+public class ActivityDiagramGraph extends AbstractGraph
+{
+ public List getNodePrototypes()
+ {
+ return NODE_PROTOTYPES;
+ }
+
+ public List getEdgePrototypes()
+ {
+ return EDGE_PROTOTYPES;
+ }
+
+ @Override
+ public boolean connect(IEdge e, INode start, Point2D startLocation, INode end, Point2D endLocation)
+ {
+ if (!ActivityTransitionEdge.class.isInstance(e))
+ {
+ return super.connect(e, start, startLocation, end, endLocation);
+ }
+ ActivityTransitionEdge transitionEdge = (ActivityTransitionEdge) e;
+ if (DecisionNode.class.isInstance(start))
+ {
+ boolean isSyncBarAtEnd = SynchronizationBarNode.class.isInstance(end);
+ if (isSyncBarAtEnd)
+ {
+ // For syn bar, we want to connect edge to north or south points
+ transitionEdge.setBentStyle(BentStyle.AUTO);
+ }
+ if (!isSyncBarAtEnd)
+ {
+ // For all the other cases, decision node are connected from east or west
+ transitionEdge.setBentStyle(BentStyle.HV);
+ }
+ }
+ return super.connect(e, start, startLocation, end, endLocation);
+ }
+
+ private static final List NODE_PROTOTYPES = new ArrayList();
+
+ private static final List EDGE_PROTOTYPES = new ArrayList();
+
+ static
+ {
+ ResourceBundle rs = ResourceBundle.getBundle(ActivityDiagramConstant.ACTIVITY_DIAGRAM_STRINGS, Locale.getDefault());
+
+ ScenarioStartNode node5 = new ScenarioStartNode();
+ node5.setToolTip(rs.getString("node5.tooltip"));
+ NODE_PROTOTYPES.add(node5);
+
+ ActivityNode node0 = new ActivityNode();
+ node0.setToolTip(rs.getString("node0.tooltip"));
+ NODE_PROTOTYPES.add(node0);
+
+ DecisionNode node1 = new DecisionNode();
+ node1.setToolTip(rs.getString("node1.tooltip"));
+ NODE_PROTOTYPES.add(node1);
+
+ SynchronizationBarNode node2 = new SynchronizationBarNode();
+ node2.setToolTip(rs.getString("node2.tooltip"));
+ NODE_PROTOTYPES.add(node2);
+
+ SignalSendingNode node3 = new SignalSendingNode();
+ node3.setToolTip(rs.getString("node3.tooltip"));
+ NODE_PROTOTYPES.add(node3);
+
+ SignalReceiptNode node4 = new SignalReceiptNode();
+ node4.setToolTip(rs.getString("node4.tooltip"));
+ NODE_PROTOTYPES.add(node4);
+
+ ScenarioEndNode node6 = new ScenarioEndNode();
+ node6.setToolTip(rs.getString("node6.tooltip"));
+ NODE_PROTOTYPES.add(node6);
+
+ NoteNode node7 = new NoteNode();
+ node7.setToolTip(rs.getString("node7.tooltip"));
+ NODE_PROTOTYPES.add(node7);
+
+ DiagramLinkNode node8 = new DiagramLinkNode();
+ node8.setToolTip(rs.getString("node8.tooltip"));
+ NODE_PROTOTYPES.add(node8);
+
+ ActivityTransitionEdge transition = new ActivityTransitionEdge();
+ transition.setToolTip(rs.getString("edge0.tooltip"));
+ EDGE_PROTOTYPES.add(transition);
+
+ NoteEdge noteEdge = new NoteEdge();
+ noteEdge.setToolTip(rs.getString("edge1.tooltip"));
+ EDGE_PROTOTYPES.add(noteEdge);
+ }
+
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramPlugin.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramPlugin.java
new file mode 100644
index 0000000..7539568
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityDiagramPlugin.java
@@ -0,0 +1,92 @@
+package com.horstmann.violet.product.diagram.activity;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import com.horstmann.violet.framework.plugin.IDiagramPlugin;
+import com.horstmann.violet.product.diagram.abstracts.IGraph;
+
+/**
+ * Describes activity diagram graph type
+ *
+ * @author Alexandre de Pellegrin
+ *
+ */
+public class ActivityDiagramPlugin implements IDiagramPlugin
+{
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.framework.plugin.AbstractPlugin#getDescription()
+ */
+ public String getDescription()
+ {
+ return "Activity UML diagram";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.framework.plugin.AbstractPlugin#getProvider()
+ */
+ public String getProvider()
+ {
+ return "Alexandre de Pellegrin / Cays S. Horstmann";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.framework.plugin.AbstractPlugin#getVersion()
+ */
+ public String getVersion()
+ {
+ return "1.0.0";
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getName()
+ */
+ public String getName()
+ {
+ return this.rs.getString("menu.activity_diagram.text");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getFileExtension()
+ */
+ public String getFileExtension()
+ {
+ return this.rs.getString("files.activity.extension");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getFileExtensionName()
+ */
+ public String getFileExtensionName()
+ {
+ return this.rs.getString("files.activity.name");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getGraphClass()
+ */
+ public Class extends IGraph> getGraphClass()
+ {
+ return ActivityDiagramGraph.class;
+ }
+
+
+ private ResourceBundle rs = ResourceBundle.getBundle(ActivityDiagramConstant.ACTIVITY_DIAGRAM_STRINGS, Locale.getDefault());
+
+
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityNode.java
new file mode 100644
index 0000000..c353aac
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityNode.java
@@ -0,0 +1,171 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.util.List;
+
+import com.horstmann.violet.product.diagram.abstracts.Direction;
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+import com.horstmann.violet.product.diagram.abstracts.property.BentStyle;
+import com.horstmann.violet.product.diagram.abstracts.property.MultiLineString;
+
+/**
+ * An activity node in an activity diagram.
+ */
+public class ActivityNode extends RectangularNode
+{
+ /**
+ * Construct an action node with a default size
+ */
+ public ActivityNode()
+ {
+ name = new MultiLineString();
+ }
+
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ g2.draw(getShape());
+ name.draw(g2, getBounds());
+ }
+
+ @Override
+ public Point2D getConnectionPoint(IEdge e)
+ {
+// if (!ActivityTransitionEdge.class.isInstance(e))
+// {
+// return super.getConnectionPoint(e);
+// }
+// if (!this.equals(e.getEnd()))
+// {
+// return super.getConnectionPoint(e);
+// }
+//
+// ActivityTransitionEdge transitionEdge = (ActivityTransitionEdge) e;
+// BentStyle bentStyle = transitionEdge.getBentStyle();
+// if (BentStyle.HV.equals(bentStyle))
+// {
+// Rectangle2D b = getBounds();
+// List edgesOnSameSide = getEdgesOnSameSide(e);
+// int position = edgesOnSameSide.indexOf(e);
+// int size = edgesOnSameSide.size();
+// Direction d = e.getDirection(this);
+// double dY = d.getY();
+// if (dY >= 0)
+// {
+// double x = b.getMaxX() - (b.getWidth() / (size + 1)) * (position + 1);
+// double y = b.getMinY();
+// return new Point2D.Double(x, y);
+// }
+// if (dY < 0)
+// {
+// double x = b.getMaxX() - (b.getWidth() / (size + 1)) * (position + 1);
+// double y = b.getMaxY();
+// return new Point2D.Double(x, y);
+// }
+// }
+// if (BentStyle.VH.equals(bentStyle))
+// {
+// Rectangle2D b = getBounds();
+// List edgesOnSameSide = getEdgesOnSameSide(e);
+// int position = edgesOnSameSide.indexOf(e);
+// int size = edgesOnSameSide.size();
+// Direction d = e.getDirection(this);
+// double dX = d.getX();
+// if (dX >= 0)
+// {
+// double x = b.getMinX();
+// double y = b.getMaxY() - (b.getHeight() / (size + 1)) * (position + 1);
+// return new Point2D.Double(x, y);
+// }
+// if (dX < 0)
+// {
+// double x = b.getMaxX();
+// double y = b.getMaxY() - (b.getHeight() / (size + 1)) * (position + 1);
+// return new Point2D.Double(x, y);
+// }
+// }
+
+ return super.getConnectionPoint(e);
+ }
+
+ @Override
+ public Shape getShape()
+ {
+ Rectangle2D bounds = getBounds();
+ return new RoundRectangle2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), ARC_SIZE, ARC_SIZE);
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D nameBounds = name.getBounds();
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = Math.max(nameBounds.getWidth(), DEFAULT_WIDTH);
+ double h = Math.max(nameBounds.getHeight(), DEFAULT_HEIGHT);
+ Rectangle2D.Double globalBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(globalBounds);
+ return snappedBounds;
+ }
+
+ /**
+ * Sets the name property value.
+ *
+ * @param newValue the new action name
+ */
+ public void setName(MultiLineString newValue)
+ {
+ name = newValue;
+ }
+
+ /**
+ * Gets the name property value.
+ *
+ * @param the action name
+ */
+ public MultiLineString getName()
+ {
+ return name;
+ }
+
+ @Override
+ public ActivityNode clone()
+ {
+ ActivityNode cloned = (ActivityNode) super.clone();
+ cloned.name = name.clone();
+ return cloned;
+ }
+
+ private MultiLineString name;
+
+ private static int ARC_SIZE = 20;
+ private static int DEFAULT_WIDTH = 80;
+ private static int DEFAULT_HEIGHT = 60;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdge.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdge.java
new file mode 100644
index 0000000..ce7ce52
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdge.java
@@ -0,0 +1,102 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+
+import com.horstmann.violet.product.diagram.abstracts.Direction;
+import com.horstmann.violet.product.diagram.abstracts.edge.SegmentedLineEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.INode;
+import com.horstmann.violet.product.diagram.abstracts.property.ArrowHead;
+import com.horstmann.violet.product.diagram.abstracts.property.BentStyle;
+
+/**
+ * An edge that is shaped like a line with up to three segments with an arrowhead
+ */
+public class ActivityTransitionEdge extends SegmentedLineEdge
+{
+
+
+ @Override
+ public ArrowHead getEndArrowHead()
+ {
+ return ArrowHead.V;
+ }
+
+ @Override
+ public Direction getDirection(INode node)
+ {
+ BentStyle bStyle = getBentStyle();
+ Direction straightDirection = super.getDirection(node);
+ double x = straightDirection.getX();
+ double y = straightDirection.getY();
+ if (node.equals(getStart()))
+ {
+ if (BentStyle.HV.equals(bStyle) || BentStyle.HVH.equals(bStyle))
+ {
+ return (x >= 0) ? Direction.EAST : Direction.WEST;
+ }
+ if (BentStyle.VH.equals(bStyle) || BentStyle.VHV.equals(bStyle))
+ {
+ return (y >= 0) ? Direction.SOUTH : Direction.NORTH;
+ }
+ }
+ if (node.equals(getEnd()))
+ {
+ if (BentStyle.HV.equals(bStyle) || BentStyle.VHV.equals(bStyle))
+ {
+ return (y >= 0) ? Direction.SOUTH : Direction.NORTH;
+ }
+ if (BentStyle.VH.equals(bStyle) || BentStyle.HVH.equals(bStyle))
+ {
+ return (x >= 0) ? Direction.EAST : Direction.WEST;
+ }
+ }
+ if (SynchronizationBarNode.class.isInstance(getStart()) || SynchronizationBarNode.class.isInstance(getEnd())) {
+ if (node.equals(getStart())) {
+ Point2D p1 = node.getLocationOnGraph();
+ Point2D p2 = getEnd().getLocationOnGraph();
+ if (p1.getY() < p2.getY()) {
+ return Direction.NORTH;
+ }
+ if (p1.getY() > p2.getY()) {
+ return Direction.SOUTH;
+ }
+ }
+ if (node.equals(getEnd())) {
+ Point2D p1 = node.getLocationOnGraph();
+ Point2D p2 = getStart().getLocationOnGraph();
+ if (p1.getY() < p2.getY()) {
+ return Direction.NORTH;
+ }
+ if (p1.getY() > p2.getY()) {
+ return Direction.SOUTH;
+ }
+ }
+ }
+ return straightDirection;
+ }
+
+
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdgeBeanInfo.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdgeBeanInfo.java
new file mode 100644
index 0000000..16860aa
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ActivityTransitionEdgeBeanInfo.java
@@ -0,0 +1,59 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.beans.SimpleBeanInfo;
+
+/**
+ * The bean info for the ActivityEdge type.
+ */
+public class ActivityTransitionEdgeBeanInfo extends SimpleBeanInfo
+{
+
+ @Override
+ public PropertyDescriptor[] getPropertyDescriptors()
+ {
+ try
+ {
+ PropertyDescriptor[] descriptors = new PropertyDescriptor[]
+ {
+ new PropertyDescriptor("startLabel", ActivityTransitionEdge.class),
+ new PropertyDescriptor("middleLabel", ActivityTransitionEdge.class),
+ new PropertyDescriptor("endLabel", ActivityTransitionEdge.class),
+ new PropertyDescriptor("bentStyle", ActivityTransitionEdge.class),
+ };
+ for (int i = 0; i < descriptors.length; i++)
+ {
+ descriptors[i].setValue("priority", new Integer(i));
+ }
+ return descriptors;
+ }
+ catch (IntrospectionException exception)
+ {
+ exception.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/DecisionNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/DecisionNode.java
new file mode 100644
index 0000000..5ee1a6f
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/DecisionNode.java
@@ -0,0 +1,173 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.Direction;
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+import com.horstmann.violet.product.diagram.abstracts.property.MultiLineString;
+
+/**
+ * A decision node in an activity diagram.
+ */
+public class DecisionNode extends RectangularNode
+{
+ /**
+ * Construct a decision node with a default size
+ */
+ public DecisionNode()
+ {
+ condition = new MultiLineString();
+ }
+
+ @Override
+ public Point2D getConnectionPoint(IEdge e)
+ {
+ Rectangle2D b = getBounds();
+
+ double x = b.getCenterX();
+ double y = b.getCenterY();
+
+ Direction d = e.getDirection(this);
+
+ Direction nearestCardinalDirection = d.getNearestCardinalDirection();
+ if (Direction.NORTH.equals(nearestCardinalDirection)) {
+ x = b.getMaxX() - (b.getWidth() / 2);
+ y = b.getMaxY();
+ }
+ if (Direction.SOUTH.equals(nearestCardinalDirection)) {
+ x = b.getMaxX() - (b.getWidth() / 2);
+ y = b.getMinY();
+ }
+ if (Direction.EAST.equals(nearestCardinalDirection)) {
+ x = b.getMinX();
+ y = b.getMaxY() - (b.getHeight() / 2);
+ }
+ if (Direction.WEST.equals(nearestCardinalDirection)) {
+ x = b.getMaxX();
+ y = b.getMaxY() - (b.getHeight() / 2);
+ }
+ return new Point2D.Double(x, y);
+ }
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ return e.getEnd() != null && this != e.getEnd();
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D b = condition.getBounds();
+ Rectangle2D textRect = new Rectangle2D.Double(0, 0, Math.max(DEFAULT_WIDTH, b.getWidth()), Math.max(DEFAULT_HEIGHT,
+ b.getHeight()));
+ double w1 = textRect.getWidth() / 2;
+ double h1 = textRect.getHeight() / 2;
+ double w2 = Math.tan(Math.toRadians(60)) * h1;
+ double h2 = Math.tan(Math.toRadians(30)) * w1;
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = (w1 + w2) * 2;
+ double h = (h1 + h2) * 2;
+ Rectangle2D globalBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(globalBounds);
+ return snappedBounds;
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ Rectangle2D shapeRect = getBounds();
+ Rectangle2D textRect = condition.getBounds();
+ textRect.setRect(shapeRect.getCenterX() - textRect.getWidth() / 2, shapeRect.getCenterY() - textRect.getHeight() / 2,
+ textRect.getWidth(), textRect.getHeight());
+
+ g2.draw(getShape());
+ condition.draw(g2, textRect);
+ }
+
+ @Override
+ public Shape getShape()
+ {
+ Rectangle2D shapeRect = getBounds();
+ GeneralPath diamond = new GeneralPath();
+ float x1 = (float) shapeRect.getX();
+ float y1 = (float) shapeRect.getCenterY();
+ float x2 = (float) shapeRect.getCenterX();
+ float y2 = (float) shapeRect.getY();
+ float x3 = (float) (shapeRect.getX() + shapeRect.getWidth());
+ float y3 = (float) shapeRect.getCenterY();
+ float x4 = (float) shapeRect.getCenterX();
+ float y4 = (float) (shapeRect.getY() + shapeRect.getHeight());
+ diamond.moveTo(x1, y1);
+ diamond.lineTo(x2, y2);
+ diamond.lineTo(x3, y3);
+ diamond.lineTo(x4, y4);
+ diamond.lineTo(x1, y1);
+ return diamond;
+ }
+
+ /**
+ * Sets the condition property value.
+ *
+ * @param newValue the branch condition
+ */
+ public void setCondition(MultiLineString newValue)
+ {
+ condition = newValue;
+ }
+
+ /**
+ * Gets the condition property value.
+ *
+ * @return the branch condition
+ */
+ public MultiLineString getCondition()
+ {
+ return condition;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public DecisionNode clone()
+ {
+ DecisionNode cloned = (DecisionNode) super.clone();
+ cloned.condition = (MultiLineString) condition.clone();
+ return cloned;
+ }
+
+ private MultiLineString condition;
+
+ private static int DEFAULT_WIDTH = 30;
+ private static int DEFAULT_HEIGHT = 20;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioEndNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioEndNode.java
new file mode 100644
index 0000000..de700ee
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioEndNode.java
@@ -0,0 +1,82 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.EllipticalNode;
+
+/**
+ * A final node (bull's eye) in an activity diagram.
+ */
+public class ScenarioEndNode extends EllipticalNode
+{
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = DEFAULT_DIAMETER + 2 * DEFAULT_GAP;
+ double h = DEFAULT_DIAMETER + 2 * DEFAULT_GAP;
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ return e.getEnd() != null && this != e.getEnd();
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ Ellipse2D circle = new Ellipse2D.Double(getBounds().getX(), getBounds().getY(), getBounds().getWidth(), getBounds()
+ .getHeight());
+
+ Rectangle2D bounds = getBounds();
+ Ellipse2D inside = new Ellipse2D.Double(bounds.getX() + DEFAULT_GAP, bounds.getY() + DEFAULT_GAP, bounds.getWidth() - 2
+ * DEFAULT_GAP, bounds.getHeight() - 2 * DEFAULT_GAP);
+ g2.fill(inside);
+ g2.draw(circle);
+ }
+
+ @Override
+ public ScenarioEndNode clone()
+ {
+ return (ScenarioEndNode) super.clone();
+ }
+
+ /** default node diameter */
+ private static int DEFAULT_DIAMETER = 14;
+
+ /** default gap between the main circle and the ring for a final node */
+ private static int DEFAULT_GAP = 3;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioStartNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioStartNode.java
new file mode 100644
index 0000000..b9b83a7
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/ScenarioStartNode.java
@@ -0,0 +1,75 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.EllipticalNode;
+
+/**
+ * An initial node (bull's eye) in an activity diagram.
+ */
+public class ScenarioStartNode extends EllipticalNode
+{
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = DEFAULT_DIAMETER;
+ double h = DEFAULT_DIAMETER;
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ return e.getEnd() != null && this != e.getEnd();
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ Rectangle2D bounds = getBounds();
+ Ellipse2D circle = new Ellipse2D.Double(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight());
+
+ g2.fill(circle);
+ }
+
+ @Override
+ public ScenarioStartNode clone()
+ {
+ return (ScenarioStartNode) super.clone();
+ }
+
+ /** default node diameter */
+ private static int DEFAULT_DIAMETER = 19;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalReceiptNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalReceiptNode.java
new file mode 100644
index 0000000..8f20aee
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalReceiptNode.java
@@ -0,0 +1,145 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+import com.horstmann.violet.product.diagram.abstracts.property.MultiLineString;
+
+/**
+ * An receive event node in an activity diagram.
+ */
+public class SignalReceiptNode extends RectangularNode
+{
+ /**
+ * Construct an receive event node with a default size
+ */
+ public SignalReceiptNode()
+ {
+ signal = new MultiLineString();
+ }
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ if (e.getEnd() != null && this != e.getEnd())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ g2.draw(getShape());
+ signal.draw(g2, getTextBounds());
+ }
+
+ @Override
+ public Shape getShape()
+ {
+ Rectangle2D b = getBounds();
+ float x1 = (float) b.getX();
+ float y1 = (float) b.getY();
+ float x2 = x1 + (float) b.getWidth();
+ float y2 = y1;
+ float x3 = x1 + (float) b.getWidth() - EDGE_WIDTH;
+ float y3 = y1 + (float) b.getHeight() / 2;
+ float x4 = x2;
+ float y4 = y1 + (float) b.getHeight();
+ float x5 = x1;
+ float y5 = y4;
+ GeneralPath path = new GeneralPath();
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ path.lineTo(x3, y3);
+ path.lineTo(x4, y4);
+ path.lineTo(x5, y5);
+ path.lineTo(x1, y1);
+ return path;
+ }
+
+ private Rectangle2D getTextBounds()
+ {
+ Rectangle2D b = getBounds();
+ return new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth() - EDGE_WIDTH, b.getHeight());
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D textBounds = signal.getBounds();
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = Math.max(textBounds.getWidth(), DEFAULT_WIDTH);
+ double h = Math.max(textBounds.getHeight(), DEFAULT_HEIGHT);
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ /**
+ * Sets the signal property value.
+ *
+ * @param newValue the new signal description
+ */
+ public void setSignal(MultiLineString newValue)
+ {
+ signal = newValue;
+ }
+
+ /**
+ * Gets the signal property value.
+ *
+ * @param the signal description
+ */
+ public MultiLineString getSignal()
+ {
+ return signal;
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public SignalReceiptNode clone()
+ {
+ SignalReceiptNode cloned = (SignalReceiptNode) super.clone();
+ cloned.signal = (MultiLineString) signal.clone();
+ return cloned;
+ }
+
+ private MultiLineString signal;
+
+ private static int DEFAULT_WIDTH = 80;
+ private static int DEFAULT_HEIGHT = 40;
+ private static int EDGE_WIDTH = 20;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalSendingNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalSendingNode.java
new file mode 100644
index 0000000..cda9c0e
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SignalSendingNode.java
@@ -0,0 +1,142 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+import com.horstmann.violet.product.diagram.abstracts.property.MultiLineString;
+
+/**
+ * An send event node in an activity diagram.
+ */
+public class SignalSendingNode extends RectangularNode
+{
+ /**
+ * Construct an send event node with a default size
+ */
+ public SignalSendingNode()
+ {
+ signal = new MultiLineString();
+ }
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ if (e.getEnd() != null && this != e.getEnd())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ g2.draw(getShape());
+ signal.draw(g2, getTextBounds());
+ }
+
+ @Override
+ public Shape getShape()
+ {
+ Rectangle2D b = getBounds();
+ float x1 = (float) b.getX();
+ float y1 = (float) b.getY();
+ float x2 = x1 + (float) b.getWidth() - EDGE_WIDTH;
+ float y2 = y1;
+ float x3 = x1 + (float) b.getWidth();
+ float y3 = y1 + (float) b.getHeight() / 2;
+ float x4 = x2;
+ float y4 = y1 + (float) b.getHeight();
+ float x5 = x1;
+ float y5 = y4;
+ GeneralPath path = new GeneralPath();
+ path.moveTo(x1, y1);
+ path.lineTo(x2, y2);
+ path.lineTo(x3, y3);
+ path.lineTo(x4, y4);
+ path.lineTo(x5, y5);
+ path.lineTo(x1, y1);
+ return path;
+ }
+
+ private Rectangle2D getTextBounds()
+ {
+ Rectangle2D b = getBounds();
+ return new Rectangle2D.Double(b.getX(), b.getY(), b.getWidth() - EDGE_WIDTH, b.getHeight());
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D textBounds = signal.getBounds();
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = Math.max(textBounds.getWidth(), DEFAULT_WIDTH);
+ double h = Math.max(textBounds.getHeight(), DEFAULT_HEIGHT);
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ /**
+ * Sets the signal property value.
+ *
+ * @param newValue the new signal description
+ */
+ public void setSignal(MultiLineString newValue)
+ {
+ signal = newValue;
+ }
+
+ /**
+ * Gets the signal property value.
+ *
+ * @param the signal description
+ */
+ public MultiLineString getSignal()
+ {
+ return signal;
+ }
+
+ @Override
+ public SignalSendingNode clone()
+ {
+ SignalSendingNode cloned = (SignalSendingNode) super.clone();
+ cloned.signal = (MultiLineString) signal.clone();
+ return cloned;
+ }
+
+ private MultiLineString signal;
+
+ private static int DEFAULT_WIDTH = 80;
+ private static int DEFAULT_HEIGHT = 40;
+ private static int EDGE_WIDTH = 20;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SynchronizationBarNode.java b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SynchronizationBarNode.java
new file mode 100644
index 0000000..9095914
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/java/com/horstmann/violet/product/diagram/activity/SynchronizationBarNode.java
@@ -0,0 +1,153 @@
+/*
+ Violet - A program for editing UML diagrams.
+
+ Copyright (C) 2007 Cay S. Horstmann (http://horstmann.com)
+ Alexandre de Pellegrin (http://alexdp.free.fr);
+
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package com.horstmann.violet.product.diagram.activity;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.horstmann.violet.product.diagram.abstracts.edge.IEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.INode;
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+
+/**
+ * A synchronization bar node in an activity diagram.
+ */
+public class SynchronizationBarNode extends RectangularNode
+{
+
+ @Override
+ public boolean addConnection(IEdge e)
+ {
+ return e.getEnd() != null && this != e.getEnd();
+ }
+
+ @Override
+ public Point2D getConnectionPoint(IEdge e)
+ {
+ Point2D defaultConnectionPoint = super.getConnectionPoint(e);
+ if (!ActivityTransitionEdge.class.isInstance(e))
+ {
+ return defaultConnectionPoint;
+ }
+
+ INode end = e.getEnd();
+ INode start = e.getStart();
+ if (this == start)
+ {
+ Point2D endConnectionPoint = end.getConnectionPoint(e);
+ double y = defaultConnectionPoint.getY();
+ double x = endConnectionPoint.getX();
+ return new Point2D.Double(x, y);
+ }
+ if (this == end)
+ {
+ Point2D startConnectionPoint = start.getConnectionPoint(e);
+ double y = defaultConnectionPoint.getY();
+ double x = startConnectionPoint.getX();
+ return new Point2D.Double(x, y);
+ }
+
+ return defaultConnectionPoint;
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D b = getDefaultBounds();
+ List connectedNodes = getConnectedNodes();
+ if (connectedNodes.size() > 0)
+ {
+ double minX = Double.MAX_VALUE;
+ double maxX = Double.MIN_VALUE;
+ for (INode n : connectedNodes)
+ {
+ Rectangle2D b2 = n.getBounds();
+ minX = Math.min(minX, b2.getMinX());
+ maxX = Math.max(maxX, b2.getMaxX());
+ }
+
+ minX -= EXTRA_WIDTH;
+ maxX += EXTRA_WIDTH;
+ // calling translate() hare is a hack but this node (at the opposite of other nodes)
+ // can have its location changed when it is connected to other nodes.
+ // Other nodes are usually only moved with a drag and drop action.
+ translate(minX - b.getX(), 0);
+ b = new Rectangle2D.Double(minX, b.getY(), maxX - minX, DEFAULT_HEIGHT);
+ }
+ return b;
+ }
+
+ /**
+ *
+ * @return minimal bounds (location + default width and default height
+ */
+ private Rectangle2D getDefaultBounds()
+ {
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = DEFAULT_WIDTH;
+ double h = DEFAULT_HEIGHT;
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ /**
+ *
+ * @return nodes which are connected (with edges) to this node
+ */
+ private List getConnectedNodes()
+ {
+ List connectedNodes = new ArrayList();
+ // needs to contain all incoming and outgoing edges
+ for (IEdge e : getGraph().getAllEdges())
+ {
+ if (e.getStart() == this) connectedNodes.add(e.getEnd());
+ if (e.getEnd() == this) connectedNodes.add(e.getStart());
+ }
+ return connectedNodes;
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ g2.fill(getShape());
+ }
+
+ /**
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public SynchronizationBarNode clone()
+ {
+ return (SynchronizationBarNode) super.clone();
+ }
+
+ private static int DEFAULT_WIDTH = 100;
+ private static int DEFAULT_HEIGHT = 4;
+ private static int EXTRA_WIDTH = 12;
+}
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings.properties b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings.properties
new file mode 100644
index 0000000..f0253a7
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings.properties
@@ -0,0 +1,14 @@
+node0.tooltip=Activity
+node1.tooltip=Decision
+node2.tooltip=Synchronization bar
+node3.tooltip=Signal sending
+node4.tooltip=Signal receipt
+node5.tooltip=Scenario start
+node6.tooltip=Scenario end
+node7.tooltip=Note
+node8.tooltip=Linked diagram
+edge0.tooltip=Transition
+edge1.tooltip=Note connector
+menu.activity_diagram.text=Activity diagram
+files.activity.name=Activity Diagram Files
+files.activity.extension=.activity.violet
\ No newline at end of file
diff --git a/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings_fr.properties b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings_fr.properties
new file mode 100644
index 0000000..b8a8834
--- /dev/null
+++ b/VioletPlugin/VioletPlugin.ActivityDiagram/src/main/resources/properties/ActivityDiagramGraphStrings_fr.properties
@@ -0,0 +1,14 @@
+node0.tooltip=Activit\u00E9
+node1.tooltip=Branchement conditionnel
+node2.tooltip=Barre de synchronisation
+node3.tooltip=Signal envoy\u00E9
+node4.tooltip=Signal re\u00E7u
+node5.tooltip=D\u00E9but du sc\u00E9nario
+node6.tooltip=Fin du sc\u00E9nario
+node7.tooltip=Note
+node8.tooltip=Diagramme li\u00E9
+edge0.tooltip=Transition
+edge1.tooltip=Connexion \u00E0 la note
+menu.activity_diagram.text=Diagramme d'activit\u00e9
+files.activity.name=Diagramme d'activit\u00e9
+files.activity.extension=.activity.violet
\ No newline at end of file