diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.classpath b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.classpath
new file mode 100644
index 0000000..2d9e006
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.project b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.project
new file mode 100644
index 0000000..c55a105
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/.project
@@ -0,0 +1,17 @@
+
+
+ VioletPlugin.StateDiagram
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/horstmann.eclipse.code.formatter.xml b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/horstmann.eclipse.code.formatter.xml
new file mode 100644
index 0000000..bef0923
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/horstmann.eclipse.code.formatter.xml
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/pom.xml b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/pom.xml
new file mode 100644
index 0000000..0e36684
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/pom.xml
@@ -0,0 +1,62 @@
+
+
+ 4.0.0
+ com.horstmann.violet.plugin
+ com.horstmann.violet.plugin.statediagram
+ Violet UML Editor State 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/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularFinalStateNode.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularFinalStateNode.java
new file mode 100644
index 0000000..2afc105
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularFinalStateNode.java
@@ -0,0 +1,74 @@
+/*
+ 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.state;
+
+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.node.EllipticalNode;
+
+/**
+ * An initial or final node (bull's eye) in a state or activity diagram.
+ */
+public class CircularFinalStateNode 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;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.framework.Node#draw(java.awt.Graphics2D)
+ */
+ 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);
+ }
+
+ /** 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/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularInitialStateNode.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularInitialStateNode.java
new file mode 100644
index 0000000..c04d9bc
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/CircularInitialStateNode.java
@@ -0,0 +1,71 @@
+/*
+ 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.state;
+
+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.node.EllipticalNode;
+
+/**
+ * An initial or final node (bull's eye) in a state or activity diagram.
+ */
+public class CircularInitialStateNode 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;
+ }
+
+ 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);
+ }
+
+ /**
+ * Kept for compatibility with old versions
+ *
+ * @param dummy
+ */
+ public void setFinal(boolean dummy)
+ {
+ // Nothing to do
+ }
+
+ /** default node diameter */
+ private static int DEFAULT_DIAMETER = 20;
+
+}
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramConstant.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramConstant.java
new file mode 100644
index 0000000..bca0749
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramConstant.java
@@ -0,0 +1,8 @@
+package com.horstmann.violet.product.diagram.state;
+
+public interface StateDiagramConstant
+{
+
+ public static final String STATE_DIAGRAM_STRINGS = "properties.StateDiagramGraphStrings";
+
+}
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramGraph.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramGraph.java
new file mode 100644
index 0000000..3a7a003
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramGraph.java
@@ -0,0 +1,88 @@
+/*
+ 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.state;
+
+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.common.DiagramLinkNode;
+import com.horstmann.violet.product.diagram.common.NoteEdge;
+import com.horstmann.violet.product.diagram.common.NoteNode;
+
+/**
+ * An UML state diagram.
+ */
+public class StateDiagramGraph extends AbstractGraph
+{
+ public List getNodePrototypes()
+ {
+ return NODE_PROTOTYPES;
+ }
+
+ public List getEdgePrototypes()
+ {
+ return EDGE_PROTOTYPES;
+ }
+
+ private static final List NODE_PROTOTYPES = new ArrayList();
+
+ private static final List EDGE_PROTOTYPES = new ArrayList();
+
+ static
+ {
+ ResourceBundle rs = ResourceBundle.getBundle(StateDiagramConstant.STATE_DIAGRAM_STRINGS, Locale.getDefault());
+
+ CircularInitialStateNode circularInitialStateNode = new CircularInitialStateNode();
+ circularInitialStateNode.setToolTip(rs.getString("node1.tooltip"));
+ NODE_PROTOTYPES.add(circularInitialStateNode);
+
+ StateNode stateNode = new StateNode();
+ stateNode.setToolTip(rs.getString("node0.tooltip"));
+ NODE_PROTOTYPES.add(stateNode);
+
+ CircularFinalStateNode circularFinalStateNode = new CircularFinalStateNode();
+ circularFinalStateNode.setToolTip(rs.getString("node2.tooltip"));
+ NODE_PROTOTYPES.add(circularFinalStateNode);
+
+ NoteNode noteNode = new NoteNode();
+ noteNode.setToolTip(rs.getString("node3.tooltip"));
+ NODE_PROTOTYPES.add(noteNode);
+
+ DiagramLinkNode diagramLinkNode = new DiagramLinkNode();
+ diagramLinkNode.setToolTip(rs.getString("node4.tooltip"));
+ NODE_PROTOTYPES.add(diagramLinkNode);
+
+ StateTransitionEdge stateTransitionEdge = new StateTransitionEdge();
+ stateTransitionEdge.setToolTip(rs.getString("edge0.tooltip"));
+ EDGE_PROTOTYPES.add(stateTransitionEdge);
+
+ NoteEdge noteEdge = new NoteEdge();
+ noteEdge.setToolTip(rs.getString("edge1.tooltip"));
+ EDGE_PROTOTYPES.add(noteEdge);
+ }
+
+}
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramPlugin.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramPlugin.java
new file mode 100644
index 0000000..41b414d
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateDiagramPlugin.java
@@ -0,0 +1,103 @@
+package com.horstmann.violet.product.diagram.state;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+
+import com.horstmann.violet.framework.plugin.IDiagramPlugin;
+import com.horstmann.violet.framework.plugin.extensionpoint.Violet016FileFilterExtensionPoint;
+import com.horstmann.violet.product.diagram.abstracts.IGraph;
+
+/**
+ * Describes state diagram graph type
+ *
+ * @author Alexandre de Pellegrin
+ *
+ */
+public class StateDiagramPlugin implements IDiagramPlugin, Violet016FileFilterExtensionPoint
+{
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.framework.plugin.AbstractPlugin#getDescription()
+ */
+ public String getDescription()
+ {
+ return "State 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.state_diagram.text");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getFileExtension()
+ */
+ public String getFileExtension()
+ {
+ return this.rs.getString("files.state.extension");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getFileExtensionName()
+ */
+ public String getFileExtensionName()
+ {
+ return this.rs.getString("files.state.name");
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.horstmann.violet.product.diagram.abstracts.GraphType#getGraphClass()
+ */
+ public Class extends IGraph> getGraphClass()
+ {
+ return StateDiagramGraph.class;
+ }
+
+ public Map getMappingToKeepViolet016Compatibility()
+ {
+ Map replaceMap = new HashMap();
+ replaceMap.put("com.horstmann.violet.CircularStateNode", CircularInitialStateNode.class.getName());
+ replaceMap.put("com.horstmann.violet.StateDiagramGraph", StateDiagramGraph.class.getName());
+ replaceMap.put("com.horstmann.violet.StateNode", StateNode.class.getName());
+ replaceMap.put("com.horstmann.violet.StateTransitionEdge", StateTransitionEdge.class.getName());
+ return replaceMap;
+ }
+
+ private ResourceBundle rs = ResourceBundle.getBundle(StateDiagramConstant.STATE_DIAGRAM_STRINGS, Locale.getDefault());
+
+}
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateNode.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateNode.java
new file mode 100644
index 0000000..03fc64e
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateNode.java
@@ -0,0 +1,107 @@
+/*
+ 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.state;
+
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+
+import com.horstmann.violet.product.diagram.abstracts.node.RectangularNode;
+import com.horstmann.violet.product.diagram.abstracts.property.MultiLineString;
+
+/**
+ * A node in a state diagram.
+ */
+public class StateNode extends RectangularNode
+{
+ /**
+ * Construct a state node with a default size
+ */
+ public StateNode()
+ {
+ name = new MultiLineString();
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D b = name.getBounds();
+ Point2D currentLocation = getLocation();
+ double x = currentLocation.getX();
+ double y = currentLocation.getY();
+ double w = Math.max(b.getWidth(), DEFAULT_WIDTH);
+ double h = Math.max(b.getHeight(), DEFAULT_HEIGHT);
+ Rectangle2D currentBounds = new Rectangle2D.Double(x, y, w, h);
+ Rectangle2D snappedBounds = getGraph().getGrid().snap(currentBounds);
+ return snappedBounds;
+ }
+
+ @Override
+ public void draw(Graphics2D g2)
+ {
+ super.draw(g2);
+ g2.draw(getShape());
+ name.draw(g2, getBounds());
+ }
+
+ @Override
+ public Shape getShape()
+ {
+ return new RoundRectangle2D.Double(getBounds().getX(), getBounds().getY(), getBounds().getWidth(), getBounds().getHeight(),
+ ARC_SIZE, ARC_SIZE);
+ }
+
+ /**
+ * Sets the name property value.
+ *
+ * @param newValue the new state name
+ */
+ public void setName(MultiLineString newValue)
+ {
+ name = newValue;
+ }
+
+ /**
+ * Gets the name property value.
+ *
+ * @param the state name
+ */
+ public MultiLineString getName()
+ {
+ return name;
+ }
+
+ public StateNode clone()
+ {
+ StateNode cloned = (StateNode) 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/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateTransitionEdge.java b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateTransitionEdge.java
new file mode 100644
index 0000000..f1a5244
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/java/com/horstmann/violet/product/diagram/state/StateTransitionEdge.java
@@ -0,0 +1,180 @@
+/*
+ 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.state;
+
+import java.awt.Dimension;
+import java.awt.Graphics2D;
+import java.awt.Shape;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JLabel;
+
+import com.horstmann.violet.product.diagram.abstracts.Direction;
+import com.horstmann.violet.product.diagram.abstracts.edge.ShapeEdge;
+import com.horstmann.violet.product.diagram.abstracts.node.INode;
+import com.horstmann.violet.product.diagram.abstracts.property.ArrowHead;
+
+/**
+ * A curved edge for a state transition in a state diagram.
+ */
+public class StateTransitionEdge extends ShapeEdge
+{
+ /**
+ * Sets the label property value.
+ *
+ * @param newValue the new value
+ */
+ public void setLabel(String newValue)
+ {
+ labelText = newValue;
+ }
+
+ /**
+ * Gets the label property value.
+ *
+ * @return the current value
+ */
+ public String getLabel()
+ {
+ return labelText;
+ }
+
+ public void draw(Graphics2D g2)
+ {
+ g2.draw(getShape());
+ drawLabel(g2);
+ ArrowHead.V.draw(g2, getControlPoint(), getConnectionPoints().getP2());
+ }
+
+ /**
+ * Draws the label.
+ *
+ * @param g2 the graphics context
+ */
+ private void drawLabel(Graphics2D g2)
+ {
+ Rectangle2D labelBounds = getLabelBounds();
+ double x = labelBounds.getX();
+ double y = labelBounds.getY();
+
+ g2.translate(x, y);
+ label.paint(g2);
+ g2.translate(-x, -y);
+ }
+
+ /**
+ * Gets the bounds of the label text
+ *
+ * @param g2 the graphics context
+ * @return the bounds of the label text
+ */
+ private Rectangle2D getLabelBounds()
+ {
+ BufferedImage dummy = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+ // need a dummy image to get a Graphics to
+ // measure the size
+ Graphics2D g2 = (Graphics2D) dummy.getGraphics();
+
+ label.setText("" + labelText + "");
+ label.setFont(g2.getFont());
+ Dimension d = label.getPreferredSize();
+ label.setBounds(0, 0, d.width, d.height);
+
+ Line2D line = getConnectionPoints();
+ Point2D control = getControlPoint();
+ double x = control.getX() / 2 + line.getX1() / 4 + line.getX2() / 4;
+ double y = control.getY() / 2 + line.getY1() / 4 + line.getY2() / 4;
+
+ final int GAP = 3;
+ if (line.getY1() == line.getY2()) x -= d.getWidth() / 2;
+ else if (line.getY1() <= line.getY2()) x += GAP;
+ else x -= d.getWidth() + GAP;
+
+ if (line.getX1() == line.getX2()) y += d.getHeight() / 2;
+ else if (line.getX1() <= line.getX2()) y -= d.getHeight() + GAP;
+ else y += GAP;
+ if (Math.abs(line.getX1() - line.getX2()) >= Math.abs(line.getY1() - line.getY2()))
+ {
+ x = x - d.getWidth() / 2;
+ }
+ if (Math.abs(line.getX1() - line.getX2()) <= Math.abs(line.getY1() - line.getY2()))
+ {
+ y = y - d.getHeight() / 2;
+ }
+ return new Rectangle2D.Double(x, y, d.width, d.height);
+ }
+
+ /**
+ * Gets the control point for the quadratic spline.
+ *
+ * @return the control point
+ */
+ private Point2D getControlPoint()
+ {
+ Line2D line = getConnectionPoints();
+ double t = Math.tan(Math.toRadians(angle));
+ double dx = (line.getX2() - line.getX1()) / 2;
+ double dy = (line.getY2() - line.getY1()) / 2;
+ return new Point2D.Double((line.getX1() + line.getX2()) / 2 + t * dy, (line.getY1() + line.getY2()) / 2 - t * dx);
+ }
+
+ public Shape getShape()
+ {
+ Line2D line = getConnectionPoints();
+ Point2D control = getControlPoint();
+ GeneralPath p = new GeneralPath();
+ p.moveTo((float) line.getX1(), (float) line.getY1());
+ p.quadTo((float) control.getX(), (float) control.getY(), (float) line.getX2(), (float) line.getY2());
+ return p;
+ }
+
+ @Override
+ public Rectangle2D getBounds()
+ {
+ Rectangle2D r = super.getBounds();
+ r.add(getLabelBounds());
+ return r;
+ }
+
+ @Override
+ public Direction getDirection(INode node)
+ {
+ if (getStart() == getEnd())
+ {
+ angle = 60;
+ if (node.equals(getStart())) return Direction.EAST.turn(-30);
+ if (node.equals(getEnd())) return Direction.EAST.turn(30);
+ }
+ angle = 10;
+ return super.getDirection(node);
+ }
+
+
+ private double angle;
+ private String labelText = "";
+
+ private static JLabel label = new JLabel();
+}
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/META-INF/services/com.horstmann.violet.framework.plugin.IDiagramPlugin b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/META-INF/services/com.horstmann.violet.framework.plugin.IDiagramPlugin
new file mode 100644
index 0000000..c13ba66
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/META-INF/services/com.horstmann.violet.framework.plugin.IDiagramPlugin
@@ -0,0 +1 @@
+com.horstmann.violet.product.diagram.state.StateDiagramPlugin
\ No newline at end of file
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings.properties b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings.properties
new file mode 100644
index 0000000..f58923f
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings.properties
@@ -0,0 +1,10 @@
+node0.tooltip=State
+node1.tooltip=Scenario start
+node2.tooltip=Scenario end
+node3.tooltip=Note
+node4.tooltip=Linked diagram
+edge0.tooltip=Event / Action
+edge1.tooltip=Note connector
+menu.state_diagram.text=State diagram
+files.state.name=State Diagram Files
+files.state.extension=.state.violet
diff --git a/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings_fr.properties b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings_fr.properties
new file mode 100644
index 0000000..eef7a8d
--- /dev/null
+++ b/VioletPluginStateDiagram/VioletPlugin.StateDiagram/src/main/resources/properties/StateDiagramGraphStrings_fr.properties
@@ -0,0 +1,10 @@
+node0.tooltip=Etat
+node1.tooltip=D\u00E9but du sc\u00E9nario
+node2.tooltip=Fin du sc\u00E9nario
+node3.tooltip=Note
+node4.tooltip=Diagramme li\u00E9
+edge0.tooltip=Ev\u00E8nement / Action
+edge1.tooltip=Connexion \u00E0 la note
+menu.state_diagram.text=Diagramme d'\u00e9tat
+files.state.name=Diagramme d'\u00e9tat
+files.state.extension=.state.violet