diff --git a/.idea/libraries/pne_editor.xml b/.idea/libraries/pne_editor.xml new file mode 100644 index 0000000000000000000000000000000000000000..70f5bb4e15769c6d66efe285d24f4a9b0eb7639e --- /dev/null +++ b/.idea/libraries/pne_editor.xml @@ -0,0 +1,11 @@ +<component name="libraryTable"> + <library name="pne-editor"> + <CLASSES> + <root url="file://$PROJECT_DIR$/../pne-editor" /> + </CLASSES> + <JAVADOC /> + <SOURCES> + <root url="file://$PROJECT_DIR$/../pne-editor/src" /> + </SOURCES> + </library> +</component> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 699a522f7ccada5ab5aa11cbe3dcfc6fc6edc881..665a20dfe80ae8313d941b963d1d1731aa098648 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> <component name="ExternalStorageConfigurationManager" enabled="true" /> + <component name="JavadocGenerationManager"> + <option name="OUTPUT_DIRECTORY" value="$USER_HOME$/Desktop/javadoc" /> + </component> <component name="MavenProjectsManager"> <option name="originalFiles"> <list> diff --git a/pne-editor/.idea/.gitignore b/pne-editor/.idea/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..13566b81b018ad684f3a35fee301741b2734c8f4 --- /dev/null +++ b/pne-editor/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/pne-editor/.idea/codeStyles/Project.xml b/pne-editor/.idea/codeStyles/Project.xml new file mode 100644 index 0000000000000000000000000000000000000000..919ce1f1f77253454105acb2aad9997c1047a0e6 --- /dev/null +++ b/pne-editor/.idea/codeStyles/Project.xml @@ -0,0 +1,7 @@ +<component name="ProjectCodeStyleConfiguration"> + <code_scheme name="Project" version="173"> + <ScalaCodeStyleSettings> + <option name="MULTILINE_STRING_CLOSING_QUOTES_ON_NEW_LINE" value="true" /> + </ScalaCodeStyleSettings> + </code_scheme> +</component> \ No newline at end of file diff --git a/pne-editor/.idea/codeStyles/codeStyleConfig.xml b/pne-editor/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000000000000000000000000000000000..a55e7a179bde3e4e772c29c0c85e53354aa54618 --- /dev/null +++ b/pne-editor/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ +<component name="ProjectCodeStyleConfiguration"> + <state> + <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" /> + </state> +</component> \ No newline at end of file diff --git a/pne-editor/.idea/misc.xml b/pne-editor/.idea/misc.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6e01e18be8e6159bef4674ebe8a95fd9f1d04ff --- /dev/null +++ b/pne-editor/.idea/misc.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="PDMPlugin"> + <option name="skipTestSources" value="false" /> + </component> + <component name="ProjectRootManager" version="2" project-jdk-name="21" project-jdk-type="JavaSDK"> + <output url="file://$PROJECT_DIR$/out" /> + </component> +</project> \ No newline at end of file diff --git a/pne-editor/.idea/modules.xml b/pne-editor/.idea/modules.xml new file mode 100644 index 0000000000000000000000000000000000000000..473bd99265097ee7aedbd0934e7f396748563ee2 --- /dev/null +++ b/pne-editor/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/pne-editor.iml" filepath="$PROJECT_DIR$/.idea/pne-editor.iml" /> + </modules> + </component> +</project> \ No newline at end of file diff --git a/pne-editor/.idea/pne-editor.iml b/pne-editor/.idea/pne-editor.iml new file mode 100644 index 0000000000000000000000000000000000000000..d6ebd4805981b8400db3e3291c74a743fef9a824 --- /dev/null +++ b/pne-editor/.idea/pne-editor.iml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module> \ No newline at end of file diff --git a/pne-editor/.settings/org.eclipse.jdt.core.prefs b/pne-editor/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000000000000000000000000000000000..3a21537071bf4118b9e1ee864cb4bc258aa48211 --- /dev/null +++ b/pne-editor/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,11 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/pne-editor/README.md b/pne-editor/README.md new file mode 100644 index 0000000000000000000000000000000000000000..27f492c6ac3682405eac165934b3cb0df1b8ef36 --- /dev/null +++ b/pne-editor/README.md @@ -0,0 +1,28 @@ +PNEditor (Petri Net editor) +======== + +The original PNE can be downloaded from [www.pneditor.org](http://www.pneditor.org/) + +This instance is the result of a student project by Joris Thaveau for teaching purpose. + +It is a simplified Petri net editor that allows the editing of many PetriNet models. + +To use: + +1. Run org.pneditor.editor.Main as a Java application +2. Select the model used (the menu scans the org.pneditor.petrinet.adapters folder to build a list of available models and adapters). initial and imta are available. Places and transitions are displayed in different ways. +3. Edit the PetriNet and fire transitions. + +You may experiment some unexpected exceptions. Especially if you mix models. + +The pedagogical approach consists in: + +1. Develop your own PetriNet model in an independent project/environment - with no GUI, just the ''business'' view +2. Pack it as a jar, and let it be visible in the path +3. Develop an Adapter in the org.pneditor.petrinet.adapters folder of PNE to make your model editable + +The adapter may be simple or complex depending on the "distance" between your model and the one expected by PNE. + +Code license: [GNU GPL v3](http://www.gnu.org/licenses/gpl.html) + +Requirements: Java SE 8+ diff --git a/pne-editor/examples/insurance-company.pflow b/pne-editor/examples/insurance-company.pflow new file mode 100644 index 0000000000000000000000000000000000000000..9dbdfdc47bdae3d791817c02eac16f39b2dab177 --- /dev/null +++ b/pne-editor/examples/insurance-company.pflow @@ -0,0 +1,400 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document> + <id/> + <x/> + <y/> + <label/> + <subnet> + <id/> + <x>0</x> + <y>0</y> + <label/> + <place> + <id>26</id> + <x>-230</x> + <y>141</y> + <label>begin</label> + <tokens>1</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>10</id> + <x>-230</x> + <y>9</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>8</id> + <x>-15</x> + <y>4</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>2</id> + <x>-18</x> + <y>-154</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>20</id> + <x>-17</x> + <y>-94</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>17</id> + <x>117</x> + <y>4</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>5</id> + <x>240</x> + <y>4</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>4</id> + <x>69</x> + <y>193</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>7</id> + <x>187</x> + <y>138</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>19</id> + <x>329</x> + <y>138</y> + <label>end</label> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>3</id> + <x>-157</x> + <y>-65</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>14</id> + <x>300</x> + <y>-121</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <place> + <id>16</id> + <x>-62</x> + <y>139</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <transition> + <id>23</id> + <x>-230</x> + <y>71</y> + <label>Register</label> + </transition> + <transition> + <id>25</id> + <x>-230</x> + <y>-65</y> + <label>Classify</label> + </transition> + <transition> + <id>24</id> + <x>99</x> + <y>-154</y> + <label>Phone garage</label> + </transition> + <transition> + <id>18</id> + <x>101</x> + <y>-94</y> + <label>Check insurance</label> + </transition> + <transition> + <id>1</id> + <x>179</x> + <y>4</y> + <label>Check history</label> + </transition> + <transition> + <id>11</id> + <x>300</x> + <y>4</y> + <label>Phone garage</label> + </transition> + <transition> + <id>12</id> + <x>-124</x> + <y>139</y> + <label>Decide</label> + </transition> + <transition> + <id>9</id> + <x>135</x> + <y>193</y> + <label>Pay</label> + </transition> + <transition> + <id>27</id> + <x>254</x> + <y>138</y> + <label>Send letter</label> + </transition> + <transition> + <id>22</id> + <x>-84</x> + <y>-128</y> + <label>simple</label> + </transition> + <transition> + <id>15</id> + <x>-83</x> + <y>4</y> + <label>complex</label> + </transition> + <transition> + <id>6</id> + <x>50</x> + <y>4</y> + <label>Check insurance</label> + </transition> + <transition> + <id>13</id> + <x>2</x> + <y>193</y> + <label>ok</label> + </transition> + <transition> + <id>21</id> + <x>2</x> + <y>98</y> + <label>not ok</label> + </transition> + <arc> + <sourceId>21</sourceId> + <destinationId>7</destinationId> + <multiplicity>1</multiplicity> + <breakPoint> + <x>131</x> + <y>98</y> + </breakPoint> + </arc> + <arc> + <sourceId>16</sourceId> + <destinationId>21</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>16</sourceId> + <destinationId>13</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>12</sourceId> + <destinationId>16</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>13</sourceId> + <destinationId>4</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>24</sourceId> + <destinationId>14</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>14</sourceId> + <destinationId>12</destinationId> + <multiplicity>2</multiplicity> + <breakPoint> + <x>360</x> + <y>-121</y> + </breakPoint> + <breakPoint> + <x>360</x> + <y>57</y> + </breakPoint> + <breakPoint> + <x>-179</x> + <y>57</y> + </breakPoint> + <breakPoint> + <x>-179</x> + <y>139</y> + </breakPoint> + </arc> + <arc> + <sourceId>11</sourceId> + <destinationId>14</destinationId> + <multiplicity>2</multiplicity> + </arc> + <arc> + <sourceId>6</sourceId> + <destinationId>17</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>8</sourceId> + <destinationId>6</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>22</sourceId> + <destinationId>20</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>22</sourceId> + <destinationId>2</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>15</sourceId> + <destinationId>8</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>3</sourceId> + <destinationId>15</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>3</sourceId> + <destinationId>22</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>25</sourceId> + <destinationId>3</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>26</sourceId> + <destinationId>23</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>23</sourceId> + <destinationId>10</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>10</sourceId> + <destinationId>25</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>2</sourceId> + <destinationId>24</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>20</sourceId> + <destinationId>18</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>17</sourceId> + <destinationId>1</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>1</sourceId> + <destinationId>5</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>5</sourceId> + <destinationId>11</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>4</sourceId> + <destinationId>9</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>9</sourceId> + <destinationId>7</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>7</sourceId> + <destinationId>27</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>27</sourceId> + <destinationId>19</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>18</sourceId> + <destinationId>14</destinationId> + <multiplicity>1</multiplicity> + </arc> + </subnet> + <roles> + <role> + <id>5</id> + <name>Employee</name> + <transitionId>1</transitionId> + <transitionId>6</transitionId> + <transitionId>23</transitionId> + <transitionId>18</transitionId> + <transitionId>24</transitionId> + <transitionId>27</transitionId> + <transitionId>11</transitionId> + <createCase>false</createCase> + <destroyCase>false</destroyCase> + </role> + <role> + <id>6</id> + <name>Claim handler</name> + <transitionId>22</transitionId> + <transitionId>15</transitionId> + <transitionId>25</transitionId> + <createCase>false</createCase> + <destroyCase>false</destroyCase> + </role> + <role> + <id>7</id> + <name>Finance</name> + <transitionId>21</transitionId> + <transitionId>9</transitionId> + <transitionId>13</transitionId> + <transitionId>12</transitionId> + <createCase>false</createCase> + <destroyCase>false</destroyCase> + </role> + </roles> +</document> diff --git a/pne-editor/examples/start-stop-cancel.pflowx b/pne-editor/examples/start-stop-cancel.pflowx new file mode 100644 index 0000000000000000000000000000000000000000..5162b65171fee4f5176ff0394edad191547b8b2a --- /dev/null +++ b/pne-editor/examples/start-stop-cancel.pflowx @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<document> + <id/> + <x/> + <y/> + <label/> + <subnet> + <id>0</id> + <x>-78</x> + <y>-58</y> + <label/> + <place> + <id>4</id> + <x>-6</x> + <y>-2</y> + <label/> + <tokens>0</tokens> + <isStatic>false</isStatic> + </place> + <transition> + <id>2</id> + <x>-86</x> + <y>-2</y> + <label>start</label> + </transition> + <transition> + <id>5</id> + <x>80</x> + <y>-2</y> + <label>finish</label> + </transition> + <transition> + <id>8</id> + <x>-87</x> + <y>-84</y> + <label>cancel</label> + </transition> + <arc> + <sourceId>1</sourceId> + <destinationId>2</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>2</sourceId> + <destinationId>4</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>4</sourceId> + <destinationId>5</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>5</sourceId> + <destinationId>6</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>4</sourceId> + <destinationId>8</destinationId> + <multiplicity>1</multiplicity> + </arc> + <arc> + <sourceId>8</sourceId> + <destinationId>1</destinationId> + <multiplicity>1</multiplicity> + </arc> + <referencePlace> + <id>1</id> + <x>-171</x> + <y>-2</y> + <connectedPlaceId>3</connectedPlaceId> + </referencePlace> + <referencePlace> + <id>6</id> + <x>168</x> + <y>-2</y> + <connectedPlaceId>7</connectedPlaceId> + </referencePlace> + </subnet> +</document> diff --git a/pne-editor/lib/hamcrest-core-1.3.jar b/pne-editor/lib/hamcrest-core-1.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..9d5fe16e3dd37ebe79a36f61f5d0e1a69a653a8a Binary files /dev/null and b/pne-editor/lib/hamcrest-core-1.3.jar differ diff --git a/pne-editor/lib/javax.xml.bind.jar b/pne-editor/lib/javax.xml.bind.jar new file mode 100644 index 0000000000000000000000000000000000000000..2b5dc7e398c9f8e13ad94c8fa64525296858c0e5 Binary files /dev/null and b/pne-editor/lib/javax.xml.bind.jar differ diff --git a/pne-editor/lib/pn-imta-initial-models-and-adapters.jar b/pne-editor/lib/pn-imta-initial-models-and-adapters.jar new file mode 100644 index 0000000000000000000000000000000000000000..0283a4ff788ff775519a5bca23d14bbca6d0b5ee Binary files /dev/null and b/pne-editor/lib/pn-imta-initial-models-and-adapters.jar differ diff --git a/pne-editor/src/logger/PNEditorLogger.java b/pne-editor/src/logger/PNEditorLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..d09a1a8c0801586ea424dc157c505c26310c3ee2 --- /dev/null +++ b/pne-editor/src/logger/PNEditorLogger.java @@ -0,0 +1,98 @@ +package logger; + +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; + + +public class PNEditorLogger { + + /** + * Instantiate a logger to be used by the software + */ + private final static Logger LOGGER = Logger.getLogger(PNEditorLogger.class.getName()); + + + /** + * Specify a fileName.log to write logs + * + * @param fileName + */ + public static void addFileLog(final String fileName) { + final SimpleFormatter simpleFormatter = new SimpleFormatter(); + try { + final FileHandler fileHandler = new FileHandler(fileName + ".log", true); + fileHandler.setFormatter(simpleFormatter); + LOGGER.addHandler(fileHandler); + } catch (SecurityException e) { + LOGGER.severe("Security Problem: can't add this file"); + } catch (IOException e) { + LOGGER.severe("Can't add this file"); + } + } + + + /** + * Prints on console (+files if created) logs of severe Level + * + * @param data + */ + public static void severeLogs(final String data) { + LOGGER.severe(data); + } + + /** + * Prints on console (+files if created) logs of warning Level + * + * @param data + */ + public static void warningLogs(final String data) { + LOGGER.warning(data); + } + + /** + * Prints on console (+files if created) logs of info level + * + * @param data + */ + public static void infoLogs(final String data) { + LOGGER.info(data); + } + + /** + * Prints on console (+files if created) logs of config Level + * + * @param data + */ + public static void configLogs(final String data) { + LOGGER.config(data); + } + + /** + * Prints on console (+files if created) logs of fine Level + * + * @param data + */ + public static void fineLogs(final String data) { + LOGGER.fine(data); + } + + /** + * Prints on console (+files if created) logs of finer Level + * + * @param data + */ + public static void finerLogs(final String data) { + LOGGER.finer(data); + } + + /** + * Prints on console (+files if created) logs of finest Level + * + * @param data + */ + public static void finestLogs(final String data) { + LOGGER.finest(data); + } +} diff --git a/pne-editor/src/org/petriNet/Arc.java b/pne-editor/src/org/petriNet/Arc.java new file mode 100644 index 0000000000000000000000000000000000000000..99565782b104e3eac3ada88854e33accac259427 --- /dev/null +++ b/pne-editor/src/org/petriNet/Arc.java @@ -0,0 +1,50 @@ +package org.petriNet; + +public abstract class Arc { + + private final int id; + private Place place; + private final Transition transition; + private int weight; + + public Arc(Transition transition, Place place, int weight, int id) { + this.place = place; + this.transition = transition; + // verify that the weight is not negative + if (weight >= 0) { + this.weight = weight; + } else { + System.out.println("The weight cannot be negative."); + } + this.id = id; // Assign a unique ID with the generateId method in the PetriNet class + } + + public abstract void validate(); + + public int getWeight() { + return this.weight; + } + + public int getId() { + return this.id; + } + + public Place getPlace() { + return this.place; + } + + public Transition getTransition() { + return this.transition; + } + + public void setPlace(Place place) { + this.place = place; + } + + public void setWeight(int weight) { + this.weight = weight; + } + +} + + diff --git a/pne-editor/src/org/petriNet/IncomingArc.java b/pne-editor/src/org/petriNet/IncomingArc.java new file mode 100644 index 0000000000000000000000000000000000000000..5f66af3ddd528cab2ea5bf1aa280e0332ed55410 --- /dev/null +++ b/pne-editor/src/org/petriNet/IncomingArc.java @@ -0,0 +1,31 @@ +package org.petriNet; + +public abstract class IncomingArc extends Arc { + + /** + * IncomingArc are incoming to a transition and outgoing from a place. + * They allow tokens to be removed from a place. + * They are therefore the abstract parent class of OutgoingArc_Simple, IncomingArc_Videur, and IncomingArc_Zero. + * This is a difference from the submitted class diagram. + */ + + public IncomingArc(Transition transition, Place place, int weight, int id) { + super(transition, place, weight, id); + } + + /** + * In the IncomingArc class, tokens are only removed from the place, + * there are no tokens to add. + * This justifies the change from the submitted class diagram. + */ + + public boolean canFire() { + return this.getPlace().getTokenCount() >= this.getWeight(); + } + + @Override + public void validate() { + // Remove the number of tokens equal to the weight of the arc + this.getPlace().removeTokens(this.getWeight()); + } +} \ No newline at end of file diff --git a/pne-editor/src/org/petriNet/IncomingArc_Simple.java b/pne-editor/src/org/petriNet/IncomingArc_Simple.java new file mode 100644 index 0000000000000000000000000000000000000000..7c1f2e8080e84e25c31e0d114a4115293e012102 --- /dev/null +++ b/pne-editor/src/org/petriNet/IncomingArc_Simple.java @@ -0,0 +1,9 @@ +package org.petriNet; + +public class IncomingArc_Simple extends IncomingArc { + + public IncomingArc_Simple(Transition transition, Place place, int weight, int id) { + super(transition, place, weight, id); + } + +} diff --git a/pne-editor/src/org/petriNet/IncomingArc_Videur.java b/pne-editor/src/org/petriNet/IncomingArc_Videur.java new file mode 100644 index 0000000000000000000000000000000000000000..d238af246a6d0a6adc117a534798ebf5d9f489a0 --- /dev/null +++ b/pne-editor/src/org/petriNet/IncomingArc_Videur.java @@ -0,0 +1,25 @@ +package org.petriNet; + +public class IncomingArc_Videur extends IncomingArc { + + public IncomingArc_Videur(Transition transition, Place place, int poids, int id) { + super(transition, place, poids, id); + } + + // Les arcs «videurs» qui sont actifs dès qu’il y a un jeton dans la place source et qui enlèvent + // tous les jetons présents lorsqu’ils sont activés. + + @Override + public boolean canFire() { + return this.getPlace().getTokenCount() > 0; + } + + @Override + public void validate() { + // On retire le nombre de jetons du poids de l'arc + // prendre en cond la place choisie + this.getPlace().removeTokens(this.getPlace().getTokenCount()); + } + + +} diff --git a/pne-editor/src/org/petriNet/IncomingArc_Zero.java b/pne-editor/src/org/petriNet/IncomingArc_Zero.java new file mode 100644 index 0000000000000000000000000000000000000000..dd48bb62bccfb6e93c32e35e42c3f9540bfc6687 --- /dev/null +++ b/pne-editor/src/org/petriNet/IncomingArc_Zero.java @@ -0,0 +1,13 @@ +package org.petriNet; + + public class IncomingArc_Zero extends IncomingArc { + + public IncomingArc_Zero(Transition transition, Place place, int weight, int id) { + super(transition, place, weight, id); + } + + @Override + public boolean canFire() { + return this.getPlace().getTokenCount() == 0; + } +} diff --git a/pne-editor/src/org/petriNet/Main.java b/pne-editor/src/org/petriNet/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..798714eefc1414d40fc5f7a08b455a388d8d8a2e --- /dev/null +++ b/pne-editor/src/org/petriNet/Main.java @@ -0,0 +1,134 @@ +package org.petriNet; + +public class Main { + + public static void main(String[] args) { + System.out.println("Running Standard Petri Network Simulation..."); + + // CR1 + PetriNet Mutex = new PetriNet(); + Arc arc; + + // CP1 + Place P1 = new Place(0, Mutex.generateId(1)); + Mutex.addPlace(P1); + + // CT1 + Transition T1 = new Transition("T1", Mutex.generateId(2)); + Mutex.addTransition(T1); + + // CP2 + Place P2 = new Place(1, Mutex.generateId(1)); + Mutex.addPlace(P2); + + // CT2 + Transition T2 = new Transition("T2", Mutex.generateId(2)); + Mutex.addTransition(T2); + + // CP5 + Place P3 = new Place(0, Mutex.generateId(1)); + Mutex.addPlace(P3); + + // CT3 + Transition T3 = new Transition("T3", Mutex.generateId(2)); + Mutex.addTransition(T3); + + // CP4 + Place P4 = new Place(0, Mutex.generateId(1)); + Mutex.addPlace(P4); + + // CT4 + Transition T4 = new Transition("T4", Mutex.generateId(2)); + Mutex.addTransition(T4); + + // CP5 + Place P5 = new Place(1, Mutex.generateId(1)); + Mutex.addPlace(P5); + + // CPT1 + // Create the simple incoming arc to T1 from P1 + arc = new IncomingArc_Simple(T1, P1, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T1.addIncomingArc((IncomingArc) arc); + + + // CTP2 + // Create the simple outgoing arc from T2 to P1 + arc = new OutgoingArc(T2, P1, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T2.addOutgoingArc((OutgoingArc) arc); + + + // CTP1 + // Create the simple outgoing arc from T1 to P2 + arc = new OutgoingArc(T1, P2, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T1.addOutgoingArc((OutgoingArc) arc); + + + // CPT2 + // Create the simple incoming arc to T2 from P2 + arc = new IncomingArc_Simple(T2, P2, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T2.addIncomingArc((IncomingArc) arc); + + + // CPT5 + // Create the simple incoming arc to T1 from P3 + arc = new IncomingArc_Simple(T1, P3, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T1.addIncomingArc((IncomingArc) arc); + + + // CTP5 + // Create the simple outgoing arc from T2 to P3 + arc = new OutgoingArc(T2, P3, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T2.addOutgoingArc((OutgoingArc) arc); + + + // CPT6 + // Create the simple incoming arc to T3 from P3 + arc = new IncomingArc_Simple(T3, P3, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T3.addIncomingArc((IncomingArc) arc); + + + // CTP6 + // Create the simple outgoing arc from T4 to P3 + arc = new OutgoingArc(T4, P3, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T4.addOutgoingArc((OutgoingArc) arc); + + + // CTP3 + // Create the simple outgoing arc from T3 to P4 + arc = new OutgoingArc(T3, P4, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T3.addOutgoingArc((OutgoingArc) arc); + + + // CPT4 + // Create the simple incoming arc to T4 from P4 + arc = new IncomingArc_Simple(T4, P4, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T4.addIncomingArc((IncomingArc) arc); + + + // CPT3 + // Create the simple incoming arc to T3 from P5 + arc = new IncomingArc_Simple(T3, P5, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T3.addIncomingArc((IncomingArc) arc); + + + // CTP4 + // Create the simple outgoing arc from T4 to P5 + arc = new OutgoingArc(T4, P5, 1, Mutex.generateId(0)); + Mutex.addArc(arc); + T4.addOutgoingArc((OutgoingArc) arc); + + + Mutex.displayState(); + } +} diff --git a/pne-editor/src/org/petriNet/OutgoingArc.java b/pne-editor/src/org/petriNet/OutgoingArc.java new file mode 100644 index 0000000000000000000000000000000000000000..589a91e08a03daaf4f49026864cbe9e3f62ef5c3 --- /dev/null +++ b/pne-editor/src/org/petriNet/OutgoingArc.java @@ -0,0 +1,15 @@ +package org.petriNet; + +public class OutgoingArc extends Arc { + + public OutgoingArc(Transition transition, Place place, int weight, int id) { + super(transition, place, weight, id); + } + + + @Override + public void validate() { + this.getPlace().addTokens(this.getWeight()); + } + +} \ No newline at end of file diff --git a/pne-editor/src/org/petriNet/PetriNet.java b/pne-editor/src/org/petriNet/PetriNet.java new file mode 100644 index 0000000000000000000000000000000000000000..680203ddc70f3e95550b9314604177fa6c1231be --- /dev/null +++ b/pne-editor/src/org/petriNet/PetriNet.java @@ -0,0 +1,457 @@ + package org.petriNet; + + import java.util.*; + + public class PetriNet implements PetriNetService { + + // Create attributes as Lists of Places, Transitions, and Arcs + private final LinkedList<Integer> idCounters; + private List<Place> places; + private List<Transition> transitions; + private LinkedList<Arc> arcs; + private String networkState = "No transition fired"; + + // Create a constructor + public PetriNet() { + // Initialize the lists as empty + this.places = new ArrayList<>(); + this.transitions = new ArrayList<>(); + this.arcs = new LinkedList<>(); + idCounters = new LinkedList<>(); + + // Initialize the id counters for Arcs, Places, and Transitions + idCounters.add(0); + idCounters.add(0); + idCounters.add(0); + } + + // Create a method to generate unique ids + public int generateId(int index) { + int id = idCounters.get(index); + idCounters.set(index, id + 1); + return id; + } + + // Create getters and setters + public List<Place> getPlaces() { + return places; + } + + public void setPlaces(List<Place> places) { + this.places = places; + } + + public List<Transition> getTransitions() { + return transitions; + } + + public void setTransitions(List<Transition> transitions) { + this.transitions = transitions; + } + + public LinkedList<Arc> getArcs() { + return this.arcs; + } + + public void setArcs(LinkedList<Arc> arcs) { + this.arcs = arcs; + } + + @Override + public void addPlace(Place place) { + // Verify that there is no similar place in the list + for (Place place1 : this.places) { + if (place1.getId() == place.getId()) { + System.out.println("Place already exists"); + return; + } + } + this.places.add(place); + } + + @Override + public void addTransition(Transition transition) { + // Verify that there is no similar transition in the list + for (Transition transition1 : this.transitions) { + if (transition1.getId() == transition.getId()) { + System.out.println("Transition already exists"); + return; + } + } + this.transitions.add(transition); + } + + @Override + public void addArc(Arc arc) { + // Verify that there is no similar arc in the list + for (Arc arc1 : this.arcs) { + if (arc1.getPlace().getId() == arc.getPlace().getId() && + arc1.getTransition().getId() == arc.getTransition().getId() && + arc1.getClass() == arc.getClass()) { + System.out.println("Arc already exists"); + return; + } + } + this.arcs.add(arc); + } + + /** + * We add a method to create many transitions at once. + * This is an enhancement to avoid many lines of code. + * @param numberOfTransitions the number of transitions to create + * @return List<Transition> + */ + + public LinkedList<Transition> createTransitions(int numberOfTransitions) { + LinkedList<Transition> transitions = new LinkedList<>(); + // verify that the number of transitions is positive + if (numberOfTransitions <= 0) { + System.out.println("The number of transitions must be positive"); + return transitions; + } + for (int i = 0; i < numberOfTransitions; i++) { + int id = this.generateId(2); + Transition transition = new Transition("Transition " + id, id); + transitions.add(transition); + } + return transitions; + } + + /** + * We add a method to create many places at once. + * This is an enhancement to avoid many lines of code. + * @param numberOfPlaces the number of places to create + * @param numberOfTokens List<int> of tokens for each place + * @return List<Place> + */ + + public LinkedList<Place> createPlaces(int numberOfPlaces, List<Integer> numberOfTokens) { + LinkedList<Place> places = new LinkedList<>(); + + /* Verify that the number of tokens is equal to the number of places + * Verify that the number of tokens is positive + * verify that the number of places is positive + */ + + if (numberOfPlaces <= 0 || numberOfTokens.size() != numberOfPlaces || numberOfTokens.stream().anyMatch(token -> token < 0)) { + System.out.println("Error: The number of places must be positive, the number of tokens must be positive and equal to the number of places"); + return places; + } + + for (int i = 0; i < numberOfPlaces; i++) { + places.add(new Place( numberOfTokens.get(i), this.generateId(1))); + } + return places; + } + + /** + * We add a method to create many Incoming arcs at once. + * This is an enhancement to avoid many lines of code. + * If one of the types of arcs is not valid, the method will return null. + * + * @param numberOfArcs the number of Incoming Arcs to create + * @param weights List<int> of weights for each Incoming Arc + * @param places List<Place> of places for each Incoming Arc + * @param transitions List<Transition> of transitions for each Incoming Arc + * @param types_of_arcs List<String> of types for each Incoming Arc + * @return List<IncomingArc> + */ + + public LinkedList<Arc> createIncomingArcs(int numberOfArcs, List<String> types_of_arcs, List<Integer> weights, List<Place> places, List<Transition> transitions) { + LinkedList<Arc> IncomingArc = new LinkedList<>(); + + /* Verify that the number of IncomingArc is positive + * Verify that the number of weights is equal to the number of IncomingArc + * Verify that the number of weights is positive + * Verify that the number of places is equal to the number of IncomingArc + * Verify that the number of transitions is equal to the number of IncomingArc + */ + + if (numberOfArcs <= 0 || weights.size() != numberOfArcs || weights.stream().anyMatch(weight -> weight < 0) || + places.size() != numberOfArcs || transitions.size() != numberOfArcs) { + System.out.println("Error: The number of weights, places, and transitions must be positive and equal to the number of IncomingArc"); + return IncomingArc; + } + + for (int i = 0; i < numberOfArcs; i++) { + switch (types_of_arcs.get(i)) { + case "zero": + IncomingArc.add(new IncomingArc_Zero(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + case "videur": + IncomingArc.add(new IncomingArc_Videur(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + case "simple": + IncomingArc.add(new IncomingArc_Simple(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + break; + case "Simple": + IncomingArc.add(new IncomingArc_Simple(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + break; + case "Videur": + IncomingArc.add(new IncomingArc_Videur(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + break; + case "Zero": + IncomingArc.add(new IncomingArc_Zero(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + break; + default: + System.out.println("Error: one of he type of arc is not valid"); + return null; + } + } + return IncomingArc; + } + + /** + * We add a method to create many Outgoing arcs at once. + * This is an enhancement to avoid many lines of code. + * @param numberOfArcs the number of Outgoing Arcs to create + * @param weights List<int> of weights for each Outgoing Arc + * @param places List<Place> of places for each Outgoing Arc + * @param transitions List<Transition> of transitions for each Outgoing Arc + * @return List<Arc> + */ + + public LinkedList<Arc> createOutgoingArcs(int numberOfArcs, List<Integer> weights, List<Place> places, List<Transition> transitions) { + LinkedList<Arc> OutgoingArc = new LinkedList<>(); + + /* Verify that the number of OutgoingArc is positive + * Verify that the number of weights is equal to the number of OutgoingArc + * Verify that the number of weights is positive + * Verify that the number of places is equal to the number of OutgoingArc + * Verify that the number of transitions is equal to the number of OutgoingArc + */ + + if (numberOfArcs <= 0 || weights.size() != numberOfArcs || weights.stream().anyMatch(weight -> weight < 0) || + places.size() != numberOfArcs || transitions.size() != numberOfArcs) { + System.out.println("Error: The number of weights, places, and transitions must be positive and equal to the number of OutgoingArc"); + return OutgoingArc; + } + + for (int i = 0; i < numberOfArcs; i++) { + OutgoingArc.add(new OutgoingArc(transitions.get(i), places.get(i), weights.get(i), this.generateId(0))); + } + return OutgoingArc; + } + + @Override + public Place FindPlaceById(int id) { + for (Place place : this.places) { + if (place.getId() == id) { + return place; + } + } + System.out.println("Place not found"); + return null; + } + + @Override + public Arc FindArcById(int id) { + for (Arc arc : this.arcs) { + if (arc.getId() == id) { + return arc; + } + } + System.out.println("Arc not found"); + return null; + } + + /** + * Removing a place results in the removal of all arcs linked to it. + * Removing a transition results in the removal of all arcs linked to it. + */ + @Override + public void removePlace(Place place) { + this.places.remove(place); + // Remove all arcs linked to the place + this.arcs.removeIf(arc -> arc.getPlace().getId() == place.getId()); + } + + @Override + public void removeTransition(Transition transition) { + this.transitions.remove(transition); + // Remove all arcs linked to the transition + this.arcs.removeIf(arc -> arc.getTransition().getId() == transition.getId()); + } + + @Override + public void removeArc(Arc arc) { + this.arcs.remove(arc); + // Remove it from the list of arcs of the transition + if (arc instanceof IncomingArc) { + arc.getTransition().getIncomingArcs().remove(arc); + } else if (arc instanceof OutgoingArc) { + arc.getTransition().getOutgoingArcs().remove(arc); + } + } + + @Override + public void fireTransition(String id) { + // Set the state of the network to "Transition being validated" + this.networkState = "Transition being validated"; + + // Find the transition with the id + Transition chosenTransition = null; + for (Transition transition : this.transitions) { + if (String.valueOf(transition.getId()).equals(id)) { + chosenTransition = transition; + } + } + + // Check if the transition id is valid + if (chosenTransition == null) { + System.out.println("The transition id is not valid"); + return; + } else { + chosenTransition.fire(); + } + + // Set the state of the network to "No transition fired" + this.networkState = "No transition fired"; + } + + @Override + public void displayState() { + if (this.networkState.equals("No transition fired")) { + System.out.println("No transition fired"); + Scanner scanner = new Scanner(System.in); + while (true) { + System.out.println("Choose an option:"); + System.out.println("1. Display the network"); + System.out.println("2. Fire a transition"); + System.out.println("3. Change the number of tokens in a place"); + System.out.println("4. Change the weight of an arc"); + System.out.println("5. Change an arc to an IncomingArc_Videur or IncomingArc_Zero"); + System.out.println("6. Exit"); + String response = scanner.nextLine(); + + switch (response) { + case "1": + displayNetwork(); + break; + case "2": + System.out.println("Enter the id of the transition to fire: "); + int transitionId = getIntInput(scanner); + fireTransition(String.valueOf(transitionId)); + break; + case "3": + System.out.println("Enter the id of the place to change tokens: "); + int placeId = getIntInput(scanner); + System.out.println("Enter the new number of tokens: "); + int tokens = getIntInput(scanner); + Place place = this.FindPlaceById(placeId); + if (place == null) { + break; + } + place.setTokenCount(tokens); + break; + case "4": + System.out.println("Enter the id of the arc to change weight: "); + int arcId = getIntInput(scanner); + System.out.println("Enter the new weight: "); + int weight = getIntInput(scanner); + Arc arc = this.FindArcById(arcId); + if (arc == null) { + break; + } + arc.setWeight(weight); + break; + case "5": + System.out.println("Enter the id of the arc to change: "); + int arcToChangeId = getIntInput(scanner); + Arc arcToChange = this.FindArcById(arcToChangeId); + if (arcToChange == null) { + break; + } + if (arcToChange instanceof IncomingArc) { + System.out.println("Choose the type of arc to change to:"); + System.out.println("1. IncomingArc_Videur"); + System.out.println("2. IncomingArc_Zero"); + int arcType = getIntInput(scanner); + Transition transition = arcToChange.getTransition(); + Place placeToChange = arcToChange.getPlace(); + this.removeArc(arcToChange); + if (arcType == 1) { + IncomingArc_Videur newArc = new IncomingArc_Videur(transition, placeToChange, arcToChange.getWeight(), this.generateId(0)); + this.addArc(newArc); + transition.addIncomingArc(newArc); + System.out.println("Arc changed to IncomingArc_Videur."); + } else if (arcType == 2) { + IncomingArc_Zero newArc = new IncomingArc_Zero(transition, placeToChange, arcToChange.getWeight(), this.generateId(0)); + this.addArc(newArc); + transition.addIncomingArc(newArc); + System.out.println("Arc changed to IncomingArc_Zero."); + } else { + System.out.println("Invalid arc type."); + } + } else { + System.out.println("Arc is not an IncomingArc."); + } + break; + case "6": + return; // Exit the method + default: + System.out.println("Invalid option. Please try again."); + } + } + } else { + System.out.println("Transition being validated"); + } + } + + @Override + public void displayNetwork() { + System.out.println("Petri Net"); + System.out.println(this.places.size() + " places"); + System.out.println(this.transitions.size() + " transitions"); + System.out.println(this.arcs.size() + " arcs"); + + System.out.println("List of places:"); + // Iterate through the list of arcs to display the places + // A list for incoming arcs and a list for outgoing arcs + for (Place place : this.places) { + List<Arc> incomingArcs = new ArrayList<>(); + List<Arc> outgoingArcs = new ArrayList<>(); + for (Arc arc : this.arcs) { + // Verify if arc.getPlace() == place + if (arc.getPlace().getId() == place.getId()) { + // Verify if it's an incoming arc + if (arc instanceof IncomingArc) { + incomingArcs.add(arc); + } else if (arc instanceof OutgoingArc) { + outgoingArcs.add(arc); + } + } + } + // Display incoming/outgoing arcs for the place + System.out.println(place.getId() + " : place with " + place.getTokenCount() + " tokens, " + + incomingArcs.size() + " outgoing arc(s), " + outgoingArcs.size() + " incoming arc(s)"); + } + + System.out.println("List of transitions:"); + for (Transition transition : this.transitions) { + System.out.println(transition.getId() + " : transition " + transition.getName() + " " + transition.getIncomingArcs().size() + + " incoming arc(s), " + transition.getOutgoingArcs().size() + " outgoing arc(s)"); + } + + System.out.println("List of arcs:"); + for (Arc arc : this.arcs) { + if (arc instanceof IncomingArc) { + System.out.println(arc.getId() + " : " + + (arc instanceof IncomingArc_Videur ? "videur" : (arc instanceof IncomingArc_Zero ? "zero" : "simple arc")) + + " with weight " + arc.getWeight() + " (" + + "Place with Id " + arc.getPlace().getId() + " to " + arc.getTransition().getName() + ")"); + } else { + System.out.println(arc.getId() + " : outgoing arc with weight " + arc.getWeight() + " (" + + arc.getTransition().getName() + " to " + "Place with Id " + arc.getPlace().getId() + ")"); + } + } + } + + private int getIntInput(Scanner scanner) { + while (!scanner.hasNextInt()) { + System.out.println("Invalid input. Please enter an integer."); + scanner.next(); // discard invalid input + } + int input = scanner.nextInt(); + scanner.nextLine(); // consume the newline character + return input; + } + } \ No newline at end of file diff --git a/pne-editor/src/org/petriNet/PetriNetService.java b/pne-editor/src/org/petriNet/PetriNetService.java new file mode 100644 index 0000000000000000000000000000000000000000..473a38eafee96987b9c44c22f21b4f1e60ffd75d --- /dev/null +++ b/pne-editor/src/org/petriNet/PetriNetService.java @@ -0,0 +1,31 @@ +package org.petriNet; + +public interface PetriNetService { + + void addPlace(Place place); + + void addTransition(Transition transition); + + void addArc(Arc arc); + + void removePlace(Place place); + + void removeTransition(Transition transition); + + void removeArc(Arc arc); + + Place FindPlaceById(int id); + + Arc FindArcById(int id); + + void displayState(); + + /** + * Display the Petri net + * We found that this function is useful for visualizing + * the Petri net + */ + void displayNetwork(); + + void fireTransition(String id); +} diff --git a/pne-editor/src/org/petriNet/Place.java b/pne-editor/src/org/petriNet/Place.java new file mode 100644 index 0000000000000000000000000000000000000000..77e9fde88a718b156ec0b52980de9bcf3a5f4402 --- /dev/null +++ b/pne-editor/src/org/petriNet/Place.java @@ -0,0 +1,53 @@ +package org.petriNet; + +public class Place { + + private final int id; + private int tokenCount; + + public Place(int tokenCount, int id) { + this.id = id; + // VERIFY THAT THE NUMBER OF TOKENS IS NOT NEGATIVE + if (tokenCount >= 0) { + this.tokenCount = tokenCount; + } else { + System.out.println("The number of tokens cannot be negative."); + } + } + + public void addTokens(int tokens) { + // verify that the number of tokens is not negative + if (tokens >= 0) { + this.tokenCount += tokens; + } else { + System.out.println("The number of tokens cannot be negative."); + } + } + + public void removeTokens(int tokens) { + // verify that the number of tokens is not negative + if (tokens >= 0) { + this.tokenCount = Math.max(0, this.tokenCount - tokens); + } else { + System.out.println("The number of tokens cannot be negative."); + } + } + + public int getTokenCount() { + return this.tokenCount; + } + + public int getId() { + return id; + } + + public void setTokenCount(int tokenCount) { + if (tokenCount < 0) { + System.out.println("Token count cannot be negative."); + this.tokenCount = 0; + } else { + this.tokenCount = tokenCount; + } + } + +} diff --git a/pne-editor/src/org/petriNet/Transition.java b/pne-editor/src/org/petriNet/Transition.java new file mode 100644 index 0000000000000000000000000000000000000000..6ce6c8d49081196b95db41b52dec3a0cfb470a48 --- /dev/null +++ b/pne-editor/src/org/petriNet/Transition.java @@ -0,0 +1,105 @@ +package org.petriNet; + +import java.util.LinkedList; +import java.util.List; + +public class Transition { + + private final int id; + String name; + private LinkedList<OutgoingArc> outgoingArcs; + private LinkedList<IncomingArc> incomingArcs; + + public Transition(String name, int id) { + this.id = id; + this.name = name; + this.outgoingArcs = new LinkedList<>(); + this.incomingArcs = new LinkedList<>(); + } + + /** + * We add two methods to be able to add incoming and outgoing arcs to the transition. + * This is a difference from the submitted class diagram. + */ + + public String getName() { + return name; + } + + public int getId() { + return id; + } + + public List<OutgoingArc> getOutgoingArcs() { + return outgoingArcs; + } + + public List<IncomingArc> getIncomingArcs() { + return incomingArcs; + } + + public void setOutgoingArcs(LinkedList<OutgoingArc> outgoingArcs) { + this.outgoingArcs = outgoingArcs; + } + + public void setIncomingArcs(LinkedList<IncomingArc> incomingArcs) { + this.incomingArcs = incomingArcs; + } + + public void addOutgoingArc(OutgoingArc outgoingArc) { + // verify that the arc doesn't already exist + for (OutgoingArc existingArc : outgoingArcs) { + if (existingArc.getPlace().getId() == outgoingArc.getPlace().getId() && + existingArc.getTransition().getId() == outgoingArc.getTransition().getId() && + existingArc.getClass() == outgoingArc.getClass()) { + System.out.println("The arc already exists."); + return; + } + } + this.outgoingArcs.add(outgoingArc); + } + + public void addIncomingArc(IncomingArc incomingArc) { + // verify that the arc doesn't already exist + for (IncomingArc existingArc : incomingArcs) { + if (existingArc.getPlace().getId() == incomingArc.getPlace().getId() && + existingArc.getTransition().getId() == incomingArc.getTransition().getId() && + existingArc.getClass() == incomingArc.getClass()) { + System.out.println("The arc already exists."); + return; + } + } + this.incomingArcs.add(incomingArc); + } + + public boolean canFire() { + for (IncomingArc incomingArc : this.incomingArcs) { + if (!incomingArc.canFire()) { + System.out.println("The transition cannot fire"); + return false; + } + } + System.out.println("The transition can fire"); + return true; + } + + public void fire() { + boolean canFire = canFire(); + + if (canFire) { + for (IncomingArc incomingArc : this.getIncomingArcs()) { + incomingArc.validate(); + } + + for (OutgoingArc outgoingArc : this.getOutgoingArcs()) { + outgoingArc.validate(); + } + System.out.println("Transition fired successfully"); + } + } + + public void setName(String label) { + this.name = label; + + } +} diff --git a/pne-editor/src/org/pneditor/PNEConstantsConfiguration.java b/pne-editor/src/org/pneditor/PNEConstantsConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..94026f969704a2422a2957581d059bc74bf32e47 --- /dev/null +++ b/pne-editor/src/org/pneditor/PNEConstantsConfiguration.java @@ -0,0 +1,84 @@ +package org.pneditor; + +import java.io.File; + +public final class PNEConstantsConfiguration { + + /* + * WARNING : resources path have a "/" separator not a File.seprator. + * (Whatever the OS is) + */ + + private PNEConstantsConfiguration() { + throw new AssertionError(); + } + + /* + * resources/ + * └── pneditor + * ├── canvas + * ├── filechooser + * */ + public static final String RESOURCESDIR = "/"+"resources"+"/";// + public static final String PNEDITOR_RESOURCES = RESOURCESDIR+"pneditor"+"/"; + public static final String CANVAS_RESOURCES = PNEDITOR_RESOURCES+"canvas"+"/"; + public static final String FILECHOOSER_RESOURCES = PNEDITOR_RESOURCES+"filechooser"+"/"; + + /* + * resources/ + * */ + public static final String ICON16 = RESOURCESDIR+"icon16.png"; + public static final String ICON32 = RESOURCESDIR+"icon32.png"; + public static final String ICON48 = RESOURCESDIR+"icon48.png"; + + /* + * resources/ + * └── pneditor + * */ + public static final String ABOUT16 = PNEDITOR_RESOURCES+"About16.gif"; + public static final String ARC16 = PNEDITOR_RESOURCES+"arc16.gif"; + public static final String CONVERTTRANSITIONTOSUBNET = PNEDITOR_RESOURCES+"converttransitiontosubnet.gif"; + public static final String COPY16 = PNEDITOR_RESOURCES+"Copy16.gif"; + public static final String CUT16 = PNEDITOR_RESOURCES+"Cut16.gif"; + public static final String DELETE16 = PNEDITOR_RESOURCES+"Delete16.gif"; + public static final String EXPORT = PNEDITOR_RESOURCES+"export.gif"; + public static final String IMPORT = PNEDITOR_RESOURCES+"import.gif"; + public static final String LABEL = PNEDITOR_RESOURCES+"label.gif"; + public static final String MULTIPLICITY = PNEDITOR_RESOURCES+"multiplicity.gif"; + public static final String NEW16 = PNEDITOR_RESOURCES+"New16.gif"; + public static final String OPEN16 = PNEDITOR_RESOURCES+"Open16.gif"; + public static final String PASTE16 = PNEDITOR_RESOURCES+"Paste16.gif"; + public static final String PLACE16 = PNEDITOR_RESOURCES+"place16.gif"; + public static final String REDO16 = PNEDITOR_RESOURCES+"Redo16.gif"; + public static final String SAVE16 = PNEDITOR_RESOURCES+"Save16.gif"; + public static final String SAVEAS16 = PNEDITOR_RESOURCES+"SaveAs16.gif"; + public static final String SELECT = PNEDITOR_RESOURCES+"select.gif"; + public static final String SETARCRESETACTION = PNEDITOR_RESOURCES+"setarcresetaction.gif"; + public static final String TOKENS = PNEDITOR_RESOURCES+"tokens.gif"; + public static final String TOKEN_AND_FIRE16 = PNEDITOR_RESOURCES+"token_and_fire16.gif"; + public static final String TRANSITION16 = PNEDITOR_RESOURCES+"transition16.gif"; + public static final String UNDO16 = PNEDITOR_RESOURCES+"Undo16.gif"; + + /* + * resources/ + * └── pneditor + * ├── canvas + * */ + public static final String ARC = CANVAS_RESOURCES+"arc.gif"; + public static final String FIRE = CANVAS_RESOURCES+"fire.gif"; + public static final String PLACE = CANVAS_RESOURCES+"place.gif"; + public static final String TOKEN = CANVAS_RESOURCES+"token.gif"; + public static final String TOKEN_OR_FIRE = CANVAS_RESOURCES+"token_or_fire.gif"; + public static final String TRANSITION = CANVAS_RESOURCES+"transition.gif"; + + /* + * resources/ + * └── pneditor + * ├── filechooser + * */ + public static final String EPS = FILECHOOSER_RESOURCES+"eps.gif"; + public static final String PFLOW = FILECHOOSER_RESOURCES+"pflow.gif"; + public static final String PNG = FILECHOOSER_RESOURCES+"png.gif"; + public static final String PNML = FILECHOOSER_RESOURCES+"pnml.gif"; + +} diff --git a/pne-editor/src/org/pneditor/editor/DrawingBoard.java b/pne-editor/src/org/pneditor/editor/DrawingBoard.java new file mode 100644 index 0000000000000000000000000000000000000000..5e6537d40a050cb8d7e068ecca99a67d07b9222f --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/DrawingBoard.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import javax.swing.JPanel; +import javax.swing.JScrollBar; +import org.pneditor.editor.canvas.Canvas; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class DrawingBoard extends JPanel { + + private final JScrollBar verticalScrollBar = new JScrollBar(JScrollBar.VERTICAL, 0, 10_000, 0, 10_000); + private final JScrollBar horizontalScrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 10_000, 0, 10_000); + + DrawingBoard(final Canvas canvas) { + super(); + this.setLayout(new GridBagLayout()); + final GridBagConstraints constraints = new GridBagConstraints(); + + constraints.gridx = 0; + constraints.gridy = 0; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1; + constraints.weighty = 1; + this.add(canvas, constraints); + constraints.gridx = 1; + constraints.gridy = 0; + constraints.weightx = 0; + constraints.weighty = 0; + this.add(this.verticalScrollBar, constraints); + constraints.gridx = 0; + constraints.gridy = 1; + constraints.weightx = 0; + constraints.weighty = 0; + this.add(this.horizontalScrollBar, constraints); + + this.verticalScrollBar.setUnitIncrement(30); + this.horizontalScrollBar.setUnitIncrement(30); + } + + public JScrollBar getVerticalScrollBar() { + return this.verticalScrollBar; + } + + public JScrollBar getHorizontalScrollBar() { + return this.horizontalScrollBar; + } +} diff --git a/pne-editor/src/org/pneditor/editor/LocalClipboard.java b/pne-editor/src/org/pneditor/editor/LocalClipboard.java new file mode 100644 index 0000000000000000000000000000000000000000..5c2696190b14d4299996fb3e706849500216a294 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/LocalClipboard.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + +import java.util.HashSet; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; + + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class LocalClipboard { + + private final GraphicPetriNet gPetriNet; + + LocalClipboard() { + this.gPetriNet = new GraphicPetriNet(); + } + + LocalClipboard(final String model) { + this.gPetriNet = new GraphicPetriNet(model); + } + + public void setContents(final Set<GraphicElement> elements) { + this.gPetriNet.removeElements(); + this.gPetriNet.addAll(elements); + final Set<GraphicElement> filteredElements = filterOutDisconnectedArcs(elements); + this.gPetriNet.removeElements(); + this.gPetriNet.addAll(filteredElements); + } + + public Set<GraphicElement> getContents() { + return new HashSet<GraphicElement>(this.gPetriNet.getElements()); + } + + public boolean isEmpty() { + return this.gPetriNet.getElements().isEmpty(); + } + + private Set<GraphicElement> filterOutDisconnectedArcs(final Set<GraphicElement> elements) { + final Set<GraphicElement> filteredElements = new HashSet<>(); + final Set<GraphicNode> nodes = getNodes(elements); + for (final GraphicNode node : nodes) { + final Set<GraphicArc> connectedArcEdges = this.gPetriNet.getConnectedGraphicArcs(node); + for (final GraphicArc connectedArcEdge : connectedArcEdges) { + if (nodes.contains(connectedArcEdge.getSource()) && nodes.contains(connectedArcEdge.getDestination())) { + filteredElements.add(connectedArcEdge); + } + } + } + filteredElements.addAll(nodes); + return filteredElements; + } + + public Set<GraphicNode> getNodes(final Set<GraphicElement> elements) { + final Set<GraphicNode> nodes = new HashSet<>(); + for (final GraphicElement element : elements) { + if (element.isNode()) { + nodes.add((GraphicNode) element); + } + } + return nodes; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/Main.java b/pne-editor/src/org/pneditor/editor/Main.java new file mode 100644 index 0000000000000000000000000000000000000000..053455e6525acc44da0c7e74071e65f6605452a0 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/Main.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class Main { + + public static void main(String[] args) { + new Root(args); + } +} diff --git a/pne-editor/src/org/pneditor/editor/MainFrame.java b/pne-editor/src/org/pneditor/editor/MainFrame.java new file mode 100644 index 0000000000000000000000000000000000000000..3846647c60e50a2bd020a9da57485b451a8f51b2 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/MainFrame.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + +import java.awt.Color; + +import javax.swing.JFrame; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class MainFrame extends JFrame { + + MainFrame(final String title) { + super(title); + UIManager.getDefaults().put("ToolTip.hideAccelerator", Boolean.TRUE); + UIManager.put("swing.boldMetal", Boolean.FALSE); + UIManager.put("MenuItem.Foreground", Color.WHITE); + final String lookAndFeel = UIManager.getSystemLookAndFeelClassName(); + try { + UIManager.setLookAndFeel(lookAndFeel); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException + | UnsupportedLookAndFeelException e) { + PNEditorLogger.infoLogs("Couldn't load the Look and Feel"); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/Root.java b/pne-editor/src/org/pneditor/editor/Root.java new file mode 100644 index 0000000000000000000000000000000000000000..6fc0a6839d62104f73a0f4ef6ab8f7138881e8ba --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/Root.java @@ -0,0 +1,786 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + +import java.awt.BorderLayout; +import java.awt.Cursor; +import java.awt.Frame; +import java.awt.Image; +import java.awt.Point; +import java.awt.event.*; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.*; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.prefs.Preferences; +import javax.swing.*; +import javax.swing.event.*; +import org.pneditor.editor.actions.*; +import org.pneditor.editor.actions.algorithms.BoundednessAction; +import org.pneditor.editor.actions.draw.ArcSelectToolAction; +import org.pneditor.editor.actions.draw.PlaceSelectToolAction; +import org.pneditor.editor.actions.draw.SelectionSelectToolAction; +import org.pneditor.editor.actions.draw.TokenSelectToolAction; +import org.pneditor.editor.actions.draw.TransitionSelectToolAction; +import org.pneditor.editor.actions.edit.CopyAction; +import org.pneditor.editor.actions.edit.CutAction; +import org.pneditor.editor.actions.edit.DeleteAction; +import org.pneditor.editor.actions.edit.PasteAction; +import org.pneditor.editor.actions.edit.RedoAction; +import org.pneditor.editor.actions.edit.SelectAllAction; +import org.pneditor.editor.actions.edit.UndoAction; +import org.pneditor.editor.actions.element.SetArcInhibitoryAction; +import org.pneditor.editor.actions.element.SetArcMultiplicityAction; +import org.pneditor.editor.actions.element.SetArcRegularAction; +import org.pneditor.editor.actions.element.SetArcResetAction; +import org.pneditor.editor.actions.element.SetLabelAction; +import org.pneditor.editor.actions.element.SetTokensAction; +import org.pneditor.editor.actions.file.ExportAction; +import org.pneditor.editor.actions.file.ImportAction; +import org.pneditor.editor.actions.file.NewFileAction; +import org.pneditor.editor.actions.file.OpenFileAction; +import org.pneditor.editor.actions.file.QuitAction; +import org.pneditor.editor.actions.file.SaveAction; +import org.pneditor.editor.actions.file.SaveFileAsAction; +import org.pneditor.editor.canvas.*; +import org.pneditor.editor.filechooser.EpsFileType; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.editor.filechooser.PflowFileType; +import org.pneditor.editor.filechooser.PngFileType; +import org.pneditor.editor.filechooser.ViptoolPnmlFileType; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * This class is the main point of the application. + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public final class Root implements WindowListener, ListSelectionListener, SelectionChangedListener { + + private static final String APP_NAME = "PNEditor"; + private static final String APP_VERSION = "0.71"; + + public Root(final String[] varargs) { + loadPreferences(); + this.selection.setSelectionChangedListener(this); + + setupMainFrame(); + this.mainFrame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + setupFrameIcons(); + + if (varargs.length == 1) { + final String filename = varargs[0]; + final File file = new File(filename); + final FileType fileType = FileType.getAcceptingFileType(file, FileType.getAllFileTypes()); + try { + final GraphicPetriNet petriNet = fileType.load(file, getCurrentModel()); + this.setGraphicPetriNet(petriNet); + this.setCurrentFile(file); // TODO: make it DRY with OpenFileAction + this.setModified(false); + this.setCurrentDirectory(file.getParentFile()); + this.canvas.repaint(); + } catch (FileTypeException ex) { + Logger.getLogger(Root.class.getName()).log(Level.INFO, null, ex); + } + } + } + + private static final String CURRENT_DIRECTORY = "current_directory"; + + private void loadPreferences() { + final Preferences preferences = Preferences.userNodeForPackage(this.getClass()); + setCurrentDirectory(new File(preferences.get(CURRENT_DIRECTORY, System.getProperty("user.home")))); + } + + private void savePreferences() { + final Preferences preferences = Preferences.userNodeForPackage(this.getClass()); + preferences.put(CURRENT_DIRECTORY, getCurrentDirectory().toString()); + } + + // Undo manager - per application + private final UndoAction undo = new UndoAction(this); + private final RedoAction redo = new RedoAction(this); + private final UndoManager undoManager = new UndoManager(this, this.undo, this.redo); + + public UndoManager getUndoManager() { + return this.undoManager; + } + + // Current directory - per application + private File currentDirectory; + + public File getCurrentDirectory() { + return this.currentDirectory; + } + + public void setCurrentDirectory(final File currentDirectory) { + this.currentDirectory = currentDirectory; + } + + // Main frame - per application + private final MainFrame mainFrame = new MainFrame(getNewWindowTitle()); + + public Frame getParentFrame() { + return this.mainFrame; + } + + // Document - per tab + private GraphicPetriNet graphicPetriNet = new GraphicPetriNet(); + + public GraphicPetriNet getGraphicPetriNet() { + return this.graphicPetriNet; + } + + public void setGraphicPetriNet(final GraphicPetriNet graphicPetriNet) { + this.graphicPetriNet = graphicPetriNet; + getUndoManager().eraseAll(); + refreshAll(); + } + + public void updateGraphicPetriNet(final GraphicPetriNet newGraphicPetriNet) { + this.graphicPetriNet = newGraphicPetriNet; + refreshAll(); + } + + public PetriNetInterface getPetriNet() { + return this.graphicPetriNet.getPetriNet(); + } + + private String model = "initial"; + + public String getCurrentModel() { + return this.model; + } + + public void setCurrentModel(final String model) { + this.model = model; + this.mainFrame.setTitle(getNewWindowTitle()); + + for (final JMenuItem modelItem : this.modelsList) { + if (modelItem.getName().equals(getCurrentModel())) { + modelItem.setEnabled(false); + } else { + modelItem.setEnabled(true); + } + } + } + + // Clicked element - per tab + private GraphicElement clickedElement; + + public GraphicElement getClickedElement() { + return this.clickedElement; + } + + public void setClickedElement(final GraphicElement clickedElement) { + this.clickedElement = clickedElement; + enableOnlyPossibleActions(); + } + + // Selection - per tab + private final Selection selection = new Selection(); + + public Selection getSelection() { + return this.selection; + } + + @Override + public void selectionChanged() { + enableOnlyPossibleActions(); + } + + // Selection + clicked element + public Set<GraphicElement> getSelectedElementsWithClickedElement() { + final Set<GraphicElement> selectedElements = new HashSet<>(); + selectedElements.addAll(getSelection().getElements()); + if (getClickedElement() != null) { + selectedElements.add(getClickedElement()); + } + return selectedElements; + } + + // List editor - per tab + + @Override + public void valueChanged(final ListSelectionEvent e) { + enableOnlyPossibleActions(); + repaintCanvas(); + } + + // per tab + public void selectToolSelect() { + this.select.setSelected(true); + this.canvas.activeCursor = Cursor.getDefaultCursor(); + this.canvas.setCursor(this.canvas.activeCursor); + repaintCanvas(); + } + + public boolean isSelectedToolSelect() { + return this.select.isSelected(); + } + + public void selectToolPlace() { + this.place.setSelected(true); + + this.canvas.activeCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.PLACE, new Point(16, 16)); + this.canvas.setCursor(this.canvas.activeCursor); + repaintCanvas(); + } + + public boolean isSelectedToolPlace() { + return this.place.isSelected(); + } + + public void selectToolTransition() { + this.transition.setSelected(true); + this.canvas.activeCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.TRANSITION, new Point(16, 16)); + this.canvas.setCursor(this.canvas.activeCursor); + repaintCanvas(); + } + + public boolean isSelectedToolTransition() { + return this.transition.isSelected(); + } + + public void selectToolArc() { + this.arc.setSelected(true); + this.canvas.activeCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.ARC, new Point(0, 0)); + this.canvas.setCursor(this.canvas.activeCursor); + repaintCanvas(); + } + + public boolean isSelectedToolArc() { + return this.arc.isSelected(); + } + + public void selectToolToken() { + this.token.setSelected(true); + this.canvas.activeCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.TOKEN_OR_FIRE, new Point(16, 0)); + this.canvas.setCursor(this.canvas.activeCursor); + repaintCanvas(); + } + + public boolean isSelectedToolToken() { + return this.token.isSelected(); + } + + // per tab + private final Canvas canvas = new Canvas(this); + private final DrawingBoard drawingBoard = new DrawingBoard(this.canvas); + + private JPopupMenu placePopup; + private JPopupMenu transitionPopup; + private JPopupMenu arcPopup; + private JPopupMenu canvasPopup; + + public JPopupMenu getPlacePopup() { + return this.placePopup; + } + + private void setupPlacePopup() { + this.placePopup = new JPopupMenu(); + this.placePopup.add(this.setLabel); + this.placePopup.add(this.setTokens); + this.placePopup.addSeparator(); + this.placePopup.add(this.cutAction); + this.placePopup.add(this.copyAction); + this.placePopup.add(this.delete); + } + + public JPopupMenu getTransitionPopup() { + return this.transitionPopup; + } + + private void setupTransitionPopup() { + this.transitionPopup = new JPopupMenu(); + this.transitionPopup.add(this.setLabel); + this.transitionPopup.addSeparator(); + this.transitionPopup.add(this.cutAction); + this.transitionPopup.add(this.copyAction); + this.transitionPopup.add(this.delete); + } + + public JPopupMenu getArcPopup() { + return this.arcPopup; + } + + private void setupArcPopup() { + this.arcPopup = new JPopupMenu(); + this.arcPopup.add(this.setArcMultiplicity); + this.arcPopup.add(this.setArcRegular); + this.arcPopup.add(this.setArcInhibitory); + this.arcPopup.add(this.setArcReset); + + this.arcPopup.add(this.delete); + } + + public JPopupMenu getCanvasPopup() { + return this.canvasPopup; + } + + private void setupCanvasPopup() { + this.canvasPopup = new JPopupMenu(); + this.canvasPopup.add(this.pasteAction); + } + + // per application + private JToggleButton select; + private JToggleButton place; + private JToggleButton transition; + private JToggleButton arc; + private JToggleButton token; + + private Action setLabel; + private Action setTokens; + private Action setArcMultiplicity; + private Action setArcInhibitory; + private Action setArcReset; + private Action setArcRegular; + + private Action delete; + private Action cutAction; + private Action copyAction; + private Action pasteAction; + private Action selectAllAction; + + private final Set<JMenuItem> modelsList = new HashSet<>(); + + public void refreshAll() { + this.canvas.repaint(); + enableOnlyPossibleActions(); + } + + public void repaintCanvas() { + this.canvas.repaint(); + } + + private void enableOnlyPossibleActions() { + final boolean isDeletable = this.clickedElement != null || !this.selection.isEmpty(); + final boolean isCutable = isDeletable; + final boolean isCopyable = isCutable; + final boolean isPastable = !this.clipboard.isEmpty(); + final boolean isArc = this.clickedElement != null && !this.clickedElement.isNode(); + final boolean isTransition = this.clickedElement != null && this.clickedElement.isTransition(); + final boolean isPlace = this.clickedElement != null && this.clickedElement.isPlace(); + final boolean isSourceAPlace = isArc && ((GraphicArc) this.clickedElement).getArc().isSourceAPlace(); + final boolean isReset = isArc && ((GraphicArc) this.clickedElement).getArc().isReset(); + + + this.cutAction.setEnabled(isCutable); + this.copyAction.setEnabled(isCopyable); + this.pasteAction.setEnabled(isPastable); + this.selectAllAction.setEnabled(true); + this.delete.setEnabled(isDeletable); + this.setArcMultiplicity.setEnabled(!isReset); + this.setArcInhibitory.setEnabled(isSourceAPlace); + this.setArcReset.setEnabled(isSourceAPlace); + this.setArcRegular.setEnabled(isArc); + this.setTokens.setEnabled(isPlace); + this.setLabel.setEnabled(isPlace || isTransition); + this.undo.setEnabled(getUndoManager().isUndoable()); + this.redo.setEnabled(getUndoManager().isRedoable()); + + } + + @Override + public void windowClosed(final WindowEvent e) { + } + + @Override + public void windowIconified(final WindowEvent e) { + } + + @Override + public void windowDeiconified(final WindowEvent e) { + } + + @Override + public void windowActivated(final WindowEvent e) { + } + + @Override + public void windowDeactivated(final WindowEvent e) { + } + + @Override + public void windowOpened(final WindowEvent e) { + } + + @Override + public void windowClosing(final WindowEvent e) { + quitApplication(); + } + + /** + * Terminates the application + */ + public void quitApplication() { + if (!this.isModified()) { + quitNow(); + } + this.mainFrame.setState(Frame.NORMAL); + this.mainFrame.setVisible(true); + final int answer = JOptionPane.showOptionDialog(this.getParentFrame(), + "Any unsaved changes will be lost. Really quit?", "Quit", JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, null, new String[] { "Quit", "Cancel" }, "Cancel"); + if (answer == JOptionPane.YES_OPTION) { + quitNow(); + } + } + + private void quitNow() { + savePreferences(); + System.exit(0); + } + + private final JToolBar toolBar = new JToolBar(); + + private void setupFrameIcons() { + final List<Image> icons = new LinkedList<>(); + icons.add(GraphicsTools.getBufferedImage(PNEConstantsConfiguration.ICON16)); + icons.add(GraphicsTools.getBufferedImage(PNEConstantsConfiguration.ICON32)); + icons.add(GraphicsTools.getBufferedImage(PNEConstantsConfiguration.ICON48)); + this.mainFrame.setIconImages(icons); + } + + private JMenu setupAndGetFileMenu() { + + final List<FileType> openSaveFiletypes = new LinkedList<>(); + openSaveFiletypes.add(new PflowFileType()); + + final List<FileType> importFiletypes = new LinkedList<>(); + importFiletypes.add(new ViptoolPnmlFileType()); + + final List<FileType> exportFiletypes = new LinkedList<>(); + exportFiletypes.add(new ViptoolPnmlFileType()); + exportFiletypes.add(new EpsFileType()); + exportFiletypes.add(new PngFileType()); + + final Action newFile = new NewFileAction(this); + final Action openFile = new OpenFileAction(this, openSaveFiletypes); + final Action saveFile = new SaveAction(this, openSaveFiletypes); + final Action saveFileAs = new SaveFileAsAction(this, openSaveFiletypes); + final Action importFile = new ImportAction(this, importFiletypes); + final Action exportFile = new ExportAction(this, exportFiletypes); + final Action quit = new QuitAction(this); + + this.toolBar.add(newFile); + this.toolBar.add(openFile); + this.toolBar.add(saveFile); + this.toolBar.add(importFile); + this.toolBar.add(exportFile); + this.toolBar.addSeparator(); + + final JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('F'); + + fileMenu.add(newFile); + fileMenu.add(openFile); + fileMenu.add(saveFile); + fileMenu.add(saveFileAs); + fileMenu.add(importFile); + fileMenu.add(exportFile); + fileMenu.addSeparator(); + fileMenu.add(quit); + + return fileMenu; + } + + private JMenu setupAndGetElementMenu() { + this.setLabel = new SetLabelAction(this); + this.setTokens = new SetTokensAction(this); + this.setArcMultiplicity = new SetArcMultiplicityAction(this); + this.setArcInhibitory = new SetArcInhibitoryAction(this); + this.setArcRegular = new SetArcRegularAction(this); + this.setArcReset = new SetArcResetAction(this); + + final JMenu elementMenu = new JMenu("PetriNet"); + elementMenu.setMnemonic('P'); + + elementMenu.add(this.setLabel); + elementMenu.addSeparator(); + elementMenu.add(this.setTokens); + elementMenu.addSeparator(); + elementMenu.add(this.setArcMultiplicity); + elementMenu.add(this.setArcInhibitory); + elementMenu.add(this.setArcReset); + elementMenu.add(this.setArcRegular); + + return elementMenu; + } + + private JMenu setupAndGetEditMenu() { + this.delete = new DeleteAction(this); + this.cutAction = new CutAction(this); + this.copyAction = new CopyAction(this); + this.pasteAction = new PasteAction(this); + this.selectAllAction = new SelectAllAction(this); + + this.toolBar.add(this.cutAction); + this.toolBar.add(this.copyAction); + this.toolBar.add(this.pasteAction); + this.toolBar.addSeparator(); + + this.toolBar.add(this.undo); + this.toolBar.add(this.redo); + this.toolBar.add(this.delete); + + final JMenu editMenu = new JMenu("Edit"); + editMenu.setMnemonic('E'); + + editMenu.add(this.undo); + editMenu.add(this.redo); + editMenu.addSeparator(); + editMenu.add(this.cutAction); + editMenu.add(this.copyAction); + editMenu.add(this.pasteAction); + editMenu.add(this.selectAllAction); + editMenu.add(this.delete); + + return editMenu; + } + + private JMenu setupAndGetDrawMenu() { + + final Action selectToolSelectionAction = new SelectionSelectToolAction(this); + final Action selectToolPlaceAction = new PlaceSelectToolAction(this); + final Action selectToolTransitionAction = new TransitionSelectToolAction(this); + final Action selectToolArcAction = new ArcSelectToolAction(this); + final Action selectToolTokenAction = new TokenSelectToolAction(this); + + this.select = new JToggleButton(selectToolSelectionAction); + this.select.setSelected(true); + this.place = new JToggleButton(selectToolPlaceAction); + this.transition = new JToggleButton(selectToolTransitionAction); + this.arc = new JToggleButton(selectToolArcAction); + this.token = new JToggleButton(selectToolTokenAction); + + this.select.setText(""); + this.place.setText(""); + this.transition.setText(""); + this.arc.setText(""); + this.token.setText(""); + + this.toolBar.addSeparator(); + this.toolBar.add(this.select); + this.toolBar.add(this.place); + this.toolBar.add(this.transition); + this.toolBar.add(this.arc); + this.toolBar.add(this.token); + this.toolBar.addSeparator(); + + final ButtonGroup drawGroup = new ButtonGroup(); + drawGroup.add(this.select); + drawGroup.add(this.place); + drawGroup.add(this.transition); + drawGroup.add(this.arc); + drawGroup.add(this.token); + + final JMenu drawMenu = new JMenu("Draw"); + drawMenu.setMnemonic('D'); + + drawMenu.add(selectToolSelectionAction); + drawMenu.addSeparator(); + drawMenu.add(selectToolPlaceAction); + drawMenu.add(selectToolTransitionAction); + drawMenu.add(selectToolArcAction); + drawMenu.add(selectToolTokenAction); + + return drawMenu; + + } + + private JMenu setupAndGetChangeMenu() { + final JMenu changeMenu = new JMenu("Change model"); + changeMenu.setMnemonic('C'); + String dirName = "src/org/pneditor/petrinet/adapters"; + final File folder = new File(dirName); + if (folder != null) { + for (final File modelPath : folder.listFiles()) { + Path path = modelPath.toPath(); + final String modelString = path.getName(path.getNameCount() - 1).toFile().getName(); + final JMenuItem modelItem = changeMenu.add(new ChangeModelAction(this,modelString)); + modelItem.setName(modelString); + if (modelString.equals(getCurrentModel())) { + modelItem.setEnabled(false); + } + this.modelsList.add(modelItem); + } + } + return changeMenu; + } + + private void setupMainFrame() { + this.toolBar.setFloatable(false); + + final JMenuBar menuBar = new JMenuBar(); + this.mainFrame.setJMenuBar(menuBar); + + // asus 2012 algorithms menu + final JMenu algorithmsMenu = new JMenu("Algorithms"); + algorithmsMenu.setMnemonic('A'); + + // asus 2012 algorithms submenu items + algorithmsMenu.add(new BoundednessAction(this)); + + final JMenu helpMenu = new JMenu("Help"); + helpMenu.add(new AboutAction(this)); + + menuBar.add(setupAndGetFileMenu()); + menuBar.add(setupAndGetEditMenu()); + menuBar.add(setupAndGetDrawMenu()); + menuBar.add(setupAndGetElementMenu()); + menuBar.add(algorithmsMenu); + menuBar.add(setupAndGetChangeMenu()); + menuBar.add(helpMenu); + + setupArcPopup(); + setupCanvasPopup(); + setupPlacePopup(); + setupTransitionPopup(); + + final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true); + splitPane.setDividerSize(6); + splitPane.setOneTouchExpandable(true); + splitPane.setRightComponent(this.drawingBoard); + splitPane.setDividerLocation(120); + + this.mainFrame.add(splitPane, BorderLayout.CENTER); + this.mainFrame.add(this.toolBar, BorderLayout.NORTH); + + this.mainFrame.addWindowListener(this); + this.mainFrame.setLocation(50, 50); + this.mainFrame.setSize(700, 450); + this.mainFrame.setVisible(true); + } + + private LocalClipboard clipboard = new LocalClipboard(); + + public LocalClipboard getClipboard() { + return this.clipboard; + } + + public void updateClipboard() { + final Set<GraphicElement> elementsCopied = this.clipboard.getContents(); + this.clipboard = new LocalClipboard(getCurrentModel()); + this.clipboard.setContents(elementsCopied); + } + + private boolean isModified; + + public boolean isModified() { + return this.isModified; + } + + public void setModified(final boolean isModified) { + this.isModified = isModified; + this.mainFrame.setTitle(getNewWindowTitle()); + } + + private String getNewWindowTitle() { + String windowTitle = ""; + if (getCurrentFile() != null) { + windowTitle += getCurrentFile().getName(); + } else { + windowTitle += "Untitled"; + } + if (isModified()) { + windowTitle += " [modified]"; + } + windowTitle += " - " + getAppShortName() + " - " + (this.model != null ? this.model : "initial"); // FIXME: why null at + // the start? + return windowTitle; + } + + private File currentFile; + + public File getCurrentFile() { + return this.currentFile; + } + + public void setCurrentFile(final File currentFile) { + this.currentFile = currentFile; + this.mainFrame.setTitle(getNewWindowTitle()); + } + + public String getAppShortName() { + return APP_NAME; + } + + public String getAppLongName() { + return APP_NAME + ", version " + APP_VERSION; + } + + public DrawingBoard getDrawingBoard() { + return this.drawingBoard; + } + + /** + * Scans all classloaders for the current thread for loaded jars, and then scans + * each jar for the package name in question, listing all classes directly under + * the package name in question. Assumes directory structure in jar file and class + * package naming follow java conventions (i.e. com.example.test.MyTest would be in + * /com/example/test/MyTest.class) + */ + public Collection<Class> getClassesForPackage(String packageName) throws Exception { + String packagePath = packageName.replace(".", "/"); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Set<URL> jarUrls = new HashSet<URL>(); + + while (classLoader != null) { + if (classLoader instanceof URLClassLoader) + for (URL url : ((URLClassLoader) classLoader).getURLs()) + if (url.getFile().endsWith(".jar")) // may want better way to detect jar files + jarUrls.add(url); + + classLoader = classLoader.getParent(); + } + + Set<Class> classes = new HashSet<Class>(); + + for (URL url : jarUrls) { + JarInputStream stream = new JarInputStream(url.openStream()); // may want better way to open url connections + JarEntry entry = stream.getNextJarEntry(); + + while (entry != null) { + String name = entry.getName(); + int i = name.lastIndexOf("/"); + + if (i > 0 && name.endsWith(".class") && name.substring(0, i).equals(packagePath)) + classes.add(Class.forName(name.substring(0, name.length() - 6).replace("/", "."))); + + entry = stream.getNextJarEntry(); + } + + stream.close(); + } + + return classes; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/UndoManager.java b/pne-editor/src/org/pneditor/editor/UndoManager.java new file mode 100644 index 0000000000000000000000000000000000000000..d52f09976181a169ff58fab09ae63ca7f8fe3430 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/UndoManager.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor; + +import java.util.ArrayList; +import java.util.List; +import javax.swing.AbstractAction; + +import org.pneditor.editor.actions.edit.RedoAction; +import org.pneditor.editor.actions.edit.UndoAction; +import org.pneditor.util.Command; + +/** + * UndoManager provides the basic undo-redo capability. + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class UndoManager { + + private List<Command> executedCommands = new ArrayList<>(); + private int currentCommandIndex = -1; + private final Root root; + private final UndoAction undoAction; + private final RedoAction redoAction; + + /** + * Constructs a new UndoManager + * + * @param root Root object + * @param undoAction action for undo button + * @param redoAction action for redo button + */ + public UndoManager(final Root root, final UndoAction undoAction, final RedoAction redoAction) { + this.root = root; + this.undoAction = undoAction; + this.redoAction = redoAction; + } + + /** + * Execute command in UndoManager. + * + * @param command command to be executed + */ + public void executeCommand(final Command command) { + final List<Command> nonRedoedCommands = new ArrayList<>(this.executedCommands.subList(this.currentCommandIndex + 1, this.executedCommands.size())); + this.executedCommands.removeAll(nonRedoedCommands); + this.executedCommands.add(command); + this.currentCommandIndex = this.executedCommands.size() - 1; + command.execute(); + refresh(); + this.root.setModified(true); + } + + /** + * Performs the undo action. + */ + public void undoCommand() { + if (isUndoable()) { + final Command command = this.executedCommands.get(this.currentCommandIndex); + command.undo(); + this.currentCommandIndex--; + refresh(); + } + this.root.setModified(true); + } + + /** + * Performs the redo action. + */ + public void redoNextCommand() { + if (isRedoable()) { + final Command command = this.executedCommands.get(this.currentCommandIndex + 1); + command.redo(); + this.currentCommandIndex++; + refresh(); + } + this.root.setModified(true); + } + + /** + * Determines if undo is possible. + * + * @return true if undo action is possible otherwise false + */ + public boolean isUndoable() { + return this.currentCommandIndex != -1; + } + + /** + * Determines if redo is possible. + * + * @return true if redo action is possible otherwise false + */ + public boolean isRedoable() { + return this.currentCommandIndex < this.executedCommands.size() - 1; + } + + /** + * Erases all commands from the undo manager. + */ + public void eraseAll() { + this.executedCommands = new ArrayList<>(); + this.currentCommandIndex = -1; + refresh(); + } + + private void refresh() { + this.root.refreshAll(); + if (isUndoable()) { + this.undoAction.putValue(AbstractAction.SHORT_DESCRIPTION, "Undo: " + this.executedCommands.get(this.currentCommandIndex).toString()); + } else { + this.undoAction.putValue(AbstractAction.SHORT_DESCRIPTION, "Undo"); + } + if (isRedoable()) { + this.redoAction.putValue(AbstractAction.SHORT_DESCRIPTION, "Redo: " + this.executedCommands.get(this.currentCommandIndex + 1).toString()); + } else { + this.redoAction.putValue(AbstractAction.SHORT_DESCRIPTION, "Redo"); + } + } + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/AboutAction.java b/pne-editor/src/org/pneditor/editor/actions/AboutAction.java new file mode 100644 index 0000000000000000000000000000000000000000..48451c7c8052282acb2bf01ef869b688011bad3b --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/AboutAction.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions; + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class AboutAction extends AbstractAction { + + private final Root root; + + public AboutAction(final Root root) { + super(); + this.root = root; + String name = "About..."; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.ABOUT16)); + putValue(SHORT_DESCRIPTION, name); + } + + @Override + public void actionPerformed(final ActionEvent e) { + JOptionPane.showOptionDialog( + this.root.getParentFrame(), + this.root.getAppLongName() + "\n" + + "http://www.pneditor.org/\n" + + "\n" + + "Author: Martin Riesz\n" + + "Contributors:\n" + + "Milka Knapereková (boundedness algorithm)\n" + + "Ján Tančibok (reset and inhibitor arc types)\n" + + "\n" + + "Contributions are welcome. Just send a pull request on GitHub." + + "\n" + + "This program is free software: you can redistribute it and/or modify\n" + + "it under the terms of the GNU General Public License as published by\n" + + "the Free Software Foundation, either version 3 of the License, or\n" + + "(at your option) any later version.\n" + + "\n" + + "This program is distributed in the hope that it will be useful,\n" + + "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" + + "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" + + "GNU General Public License for more details.\n" + + "You should have received a copy of the GNU General Public License\n" + + "along with this program. If not, see <http://www.gnu.org/licenses/>.", + "About", + JOptionPane.DEFAULT_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + new String[]{"OK"}, + "OK"); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/ChangeModelAction.java b/pne-editor/src/org/pneditor/editor/actions/ChangeModelAction.java new file mode 100644 index 0000000000000000000000000000000000000000..a9198bda6c25c598ec5573c7d896f0860036cf7d --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/ChangeModelAction.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions; + +import java.awt.event.ActionEvent; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.AbstractAction; + +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.petrinet.UnimplementedCaseException; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class ChangeModelAction extends AbstractAction { + + private final Root root; + private final String model; + + private final static String MODEL_PATH = "org.pneditor.petrinet.adapters."; + private final static String ADAPTER_PATH = ".PetriNetAdapter"; + + public ChangeModelAction(final Root root, final String model) { + super(); + this.model = model; + this.root = root; + putValue(NAME, model); + putValue(SHORT_DESCRIPTION, "Change model to " + model); + putValue(MNEMONIC_KEY, (int) (model.charAt(0))); // set the mnemonic key to the first character of the model + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.setCurrentModel(this.model); + + final Map<AbstractNode,AbstractNode> matchingNodes = new HashMap<>(); + try { + final PetriNetInterface petriNet = (PetriNetInterface) Class.forName(MODEL_PATH + this.model + ADAPTER_PATH).newInstance(); + for (final GraphicElement element : this.root.getGraphicPetriNet().getElements()) { + + if (element.isPlace()) { + final GraphicPlace gPlace = (GraphicPlace) element; + final AbstractPlace oldPlace = gPlace.getPlace(); + final AbstractPlace place = petriNet.addAbstractPlace(oldPlace.getId()); + place.setTokens(oldPlace.getTokens()); + place.setLabel(oldPlace.getLabel()); + gPlace.setPlace(place); + + matchingNodes.put(oldPlace, place); + } + + if (element.isTransition()) { + final GraphicTransition gTransition = (GraphicTransition) element; + final AbstractTransition oldTransition = gTransition.getTransition(); + final AbstractTransition transition = petriNet.addAbstractTransition(oldTransition.getId()); + transition.setLabel(oldTransition.getLabel()); + gTransition.setTransition(transition); + + matchingNodes.put(oldTransition, transition); + } + } + + for (final GraphicElement element : this.root.getGraphicPetriNet().getElements()) { + + if (!element.isNode()) { + final GraphicArc gArc = (GraphicArc) element; + final AbstractArc oldArc = gArc.getArc(); + try { + AbstractArc arc; + final AbstractNode source = matchingNodes.get(oldArc.getSource()); + final AbstractNode destination = matchingNodes.get(oldArc.getDestination()); + + if (oldArc.isReset()) { + arc = petriNet.addResArc((AbstractPlace) source, + (AbstractTransition) destination); + } else { + if (oldArc.isInhibitory()) { + arc = petriNet.addInhibArc((AbstractPlace) source, + (AbstractTransition) destination); + } else { + arc = petriNet.addRegArc(source, destination); + } + arc.setMultiplicity(oldArc.getMultiplicity()); + } + gArc.setArc(arc); + } catch (UnimplementedCaseException | ResetArcMultiplicityException e1) { + // ResetArcMultiplicityException should not happen + + } + } + } + this.root.getGraphicPetriNet().setPetriNet(petriNet); + this.root.updateClipboard(); + + } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e1) { + PNEditorLogger.severeLogs(e1.getMessage()); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/algorithms/BoundednessAction.java b/pne-editor/src/org/pneditor/editor/actions/algorithms/BoundednessAction.java new file mode 100644 index 0000000000000000000000000000000000000000..a5612bfe5e6ca203cc6b3871e6a0c6e6718e6515 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/algorithms/BoundednessAction.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 milka + * + * 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 org.pneditor.editor.actions.algorithms; + +import java.awt.HeadlessException; +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.petrinet.ResetArcMultiplicityException; + +import logger.PNEditorLogger; + +/** + * + * @author milka + */ +@SuppressWarnings("serial") +public class BoundednessAction extends AbstractAction { + + private final Root root; + + public BoundednessAction(final Root root) { + super(); + this.root = root; + String name = "Boundedness"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + setEnabled(true); + } + + @Override + public void actionPerformed(final ActionEvent e) { + try { + if (this.root.getPetriNet().isBounded()) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), "PetriNet is NOT bounded ", "Algorithm output", JOptionPane.INFORMATION_MESSAGE); + } else { + JOptionPane.showMessageDialog(this.root.getParentFrame(), "PetriNet is bounded", "Algorithm output", JOptionPane.INFORMATION_MESSAGE); + } + } catch (HeadlessException e1) { + PNEditorLogger.warningLogs(e1.getMessage()); + } catch (ResetArcMultiplicityException e2) { + PNEditorLogger.severeLogs(e2.getMessage()); + } + } + + + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/draw/ArcSelectToolAction.java b/pne-editor/src/org/pneditor/editor/actions/draw/ArcSelectToolAction.java new file mode 100644 index 0000000000000000000000000000000000000000..86c52fdd315ea60809bd433da46391c0f93b4830 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/draw/ArcSelectToolAction.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.draw; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class ArcSelectToolAction extends AbstractAction { + + private final Root root; + + public ArcSelectToolAction(final Root root) { + super(); + this.root = root; + String name = "Arc"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.ARC)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_A); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.selectToolArc(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/draw/PlaceSelectToolAction.java b/pne-editor/src/org/pneditor/editor/actions/draw/PlaceSelectToolAction.java new file mode 100644 index 0000000000000000000000000000000000000000..cac70e42af15a7c18df67ceeded98330156dd5a3 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/draw/PlaceSelectToolAction.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.draw; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class PlaceSelectToolAction extends AbstractAction { + + private final Root root; + + public PlaceSelectToolAction(final Root root) { + super(); + this.root = root; + String name = "Place"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.PLACE16)); + putValue(SHORT_DESCRIPTION, "Place"); + putValue(MNEMONIC_KEY, KeyEvent.VK_P); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.selectToolPlace(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/draw/SelectionSelectToolAction.java b/pne-editor/src/org/pneditor/editor/actions/draw/SelectionSelectToolAction.java new file mode 100644 index 0000000000000000000000000000000000000000..95aac29631320c94c814c2ffb9255e604c8b0491 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/draw/SelectionSelectToolAction.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.draw; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SelectionSelectToolAction extends AbstractAction { + + private final Root root; + + public SelectionSelectToolAction(final Root root) { + super(); + this.root = root; + String name = "Select"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.SELECT)); + putValue(SHORT_DESCRIPTION, "Select"); + putValue(MNEMONIC_KEY, KeyEvent.VK_S); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.selectToolSelect(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/draw/TokenSelectToolAction.java b/pne-editor/src/org/pneditor/editor/actions/draw/TokenSelectToolAction.java new file mode 100644 index 0000000000000000000000000000000000000000..2e562cc86b41da3697817a057688128870634743 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/draw/TokenSelectToolAction.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.draw; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class TokenSelectToolAction extends AbstractAction { + + private final Root root; + + public TokenSelectToolAction(final Root root) { + super(); + this.root = root; + String name = "Fire transitions / Edit tokens"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.TOKEN_AND_FIRE16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_F); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.selectToolToken(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/draw/TransitionSelectToolAction.java b/pne-editor/src/org/pneditor/editor/actions/draw/TransitionSelectToolAction.java new file mode 100644 index 0000000000000000000000000000000000000000..37f73144a45e75e94b22129b6e8e84b8eedbc2da --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/draw/TransitionSelectToolAction.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.draw; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class TransitionSelectToolAction extends AbstractAction { + + private final Root root; + + public TransitionSelectToolAction(final Root root) { + super(); + this.root = root; + String name = "Transition"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.TRANSITION16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_T); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.selectToolTransition(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/CopyAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/CopyAction.java new file mode 100644 index 0000000000000000000000000000000000000000..8b7ecf3d8a291fe08ea01be696ca96beb1e95815 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/CopyAction.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class CopyAction extends AbstractAction { + + private final Root root; + + public CopyAction(final Root root) { + super(); + this.root = root; + String name = "Copy"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.COPY16)); + putValue(SHORT_DESCRIPTION, name); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl C")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.getClipboard().setContents(this.root.getSelectedElementsWithClickedElement()); + this.root.refreshAll(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/CutAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/CutAction.java new file mode 100644 index 0000000000000000000000000000000000000000..ddaf1e00949302533d80d54233eb7045d51cfc74 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/CutAction.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.CutCommand; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class CutAction extends AbstractAction { + + private final Root root; + + public CutAction(final Root root) { + super(); + this.root = root; + String name = "Cut"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.CUT16)); + putValue(SHORT_DESCRIPTION, name); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl X")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.getClipboard().setContents(this.root.getSelectedElementsWithClickedElement()); + this.root.getUndoManager().executeCommand(new CutCommand(this.root.getSelectedElementsWithClickedElement(),this.root.getGraphicPetriNet())); + this.root.getSelection().clear(); + this.root.setClickedElement(null); + this.root.refreshAll(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/DeleteAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/DeleteAction.java new file mode 100644 index 0000000000000000000000000000000000000000..0d971a1a7c5a018aecdc364f66f59abeb6a9e471 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/DeleteAction.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.DeleteElementsCommand; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class DeleteAction extends AbstractAction { + + private final Root root; + + public DeleteAction(final Root root) { + super(); + this.root = root; + String name = "Delete"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.DELETE16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_D); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("DELETE")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final Set<GraphicElement> elements= this.root.getSelectedElementsWithClickedElement(); + + if (!elements.isEmpty()) { + this.root.getUndoManager().executeCommand(new DeleteElementsCommand(elements, this.root.getGraphicPetriNet())); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/PasteAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/PasteAction.java new file mode 100644 index 0000000000000000000000000000000000000000..711daaf2afd368b90aa849c95e70c3ca3ec80b66 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/PasteAction.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.PasteCommand; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class PasteAction extends AbstractAction { + + private final Root root; + + public PasteAction(final Root root) { + super(); + this.root = root; + String name = "Paste"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.PASTE16)); + putValue(SHORT_DESCRIPTION, name); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl V")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final GraphicPetriNet gPetriNet = this.root.getGraphicPetriNet(); + final Set<GraphicElement> copiedElements = this.root.getClipboard().getContents(); + this.root.setClickedElement(null); + this.root.getSelection().clear(); + this.root.getUndoManager().executeCommand(new PasteCommand(copiedElements, gPetriNet, this.root)); + //TODO: getViewTranslation() + this.root.refreshAll(); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/RedoAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/RedoAction.java new file mode 100644 index 0000000000000000000000000000000000000000..7869df9ac70beff85566b8636becae0ea7c9392f --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/RedoAction.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class RedoAction extends AbstractAction { + + private final Root root; + + public RedoAction(final Root root) { + super(); + this.root = root; + String name = "Redo"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.REDO16)); + putValue(MNEMONIC_KEY, KeyEvent.VK_R); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Y")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.getUndoManager().redoNextCommand(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/SelectAllAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/SelectAllAction.java new file mode 100644 index 0000000000000000000000000000000000000000..18599d40285dc65efc0dd05726f557f3caf4ffd5 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/SelectAllAction.java @@ -0,0 +1,42 @@ +package org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; + +import org.pneditor.editor.Root; +import org.pneditor.editor.canvas.Selection; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; + +/** + * + * @author matmas + */ +@SuppressWarnings("serial") +public class SelectAllAction extends AbstractAction { + + private final Root root; + + public SelectAllAction(final Root root) { + super(); + this.root = root; + String name = "Select All"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl A")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final GraphicPetriNet petriNet = this.root.getGraphicPetriNet(); + + final Selection selection = this.root.getSelection(); + selection.clear(); + selection.addAll(petriNet.getElements()); + + this.root.refreshAll(); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/edit/UndoAction.java b/pne-editor/src/org/pneditor/editor/actions/edit/UndoAction.java new file mode 100644 index 0000000000000000000000000000000000000000..44522bc7bb85ecd0e36875066b5e4c50cd88254c --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/edit/UndoAction.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.edit; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.io.File; + +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class UndoAction extends AbstractAction { + + private final Root root; + + public UndoAction(final Root root) { + super(); + this.root = root; + String name = "Undo"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.UNDO16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_U); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Z")); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.getUndoManager().undoCommand(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetArcInhibitoryAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetArcInhibitoryAction.java new file mode 100644 index 0000000000000000000000000000000000000000..2d0219d1d2e941f1bc9d95440268b5b476b8cd0e --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetArcInhibitoryAction.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; + +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetArcInhibitCommand; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Amodez + */ +@SuppressWarnings("serial") +public class SetArcInhibitoryAction extends AbstractAction { + + private final Root root; + + public SetArcInhibitoryAction(final Root root) { + super(); + this.root = root; + String name = "Set inhibitor arc type"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.CONVERTTRANSITIONTOSUBNET)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_I); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null && !this.root.getClickedElement().isNode()) { + final GraphicArc arc = (GraphicArc) this.root.getClickedElement(); + this.root.getUndoManager().executeCommand(new SetArcInhibitCommand(arc, this.root.getGraphicPetriNet())); + } + + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetArcMultiplicityAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetArcMultiplicityAction.java new file mode 100644 index 0000000000000000000000000000000000000000..7ca39c611c701645bc5343b2e58cea7aba995760 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetArcMultiplicityAction.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.DeleteArcCommand; +import org.pneditor.editor.commands.SetArcMultiplicityCommand; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SetArcMultiplicityAction extends AbstractAction { + + private final Root root; + + public SetArcMultiplicityAction(final Root root) { + super(); + this.root = root; + String name = "Set arc multiplicity"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.MULTIPLICITY)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_M); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null && !this.root.getClickedElement().isNode()) { + final GraphicArc arc = (GraphicArc) this.root.getClickedElement(); + int multiplicity = 0; // TODO !! + try { + multiplicity = arc.getArc().getMultiplicity(); + } catch (ResetArcMultiplicityException e1) { + PNEditorLogger.severeLogs(e1.getMessage()); + } + final String response = JOptionPane.showInputDialog(this.root.getParentFrame(), "Multiplicity:", + multiplicity); + if (response != null) { + try { + multiplicity = Integer.parseInt(response); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage() + " is not a number"); + } + } + + try { + if (arc.getArc().getMultiplicity() != multiplicity) { + if (multiplicity < 1) { + this.root.getUndoManager() + .executeCommand(new DeleteArcCommand(arc, this.root.getGraphicPetriNet())); + } else { + this.root.getUndoManager().executeCommand(new SetArcMultiplicityCommand(arc, multiplicity)); + } + } + } catch (ResetArcMultiplicityException e1) { + PNEditorLogger.severeLogs(e1.getMessage()); + } + + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetArcRegularAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetArcRegularAction.java new file mode 100644 index 0000000000000000000000000000000000000000..1ca33faf2b0fbb5bc8d1d80614a62e01df699431 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetArcRegularAction.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; + +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetArcRegularCommand; +import org.pneditor.editor.gpetrinet.GraphicArc; +//import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author jan.tancibok + */ +@SuppressWarnings("serial") +public class SetArcRegularAction extends AbstractAction { + + private final Root root; + + public SetArcRegularAction(final Root root) { + super(); + this.root = root; + String name = "Set regular arc type"; + putValue(NAME, name); + // putValue(SMALL_ICON, + // GraphicsTools.getIcon(PNEConstantsConfiguration.SETARCRESETACTION)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_R); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null && !this.root.getClickedElement().isNode()) { + final GraphicArc arc = (GraphicArc) this.root.getClickedElement(); + this.root.getUndoManager().executeCommand(new SetArcRegularCommand(arc, this.root.getGraphicPetriNet())); + } + + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetArcResetAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetArcResetAction.java new file mode 100644 index 0000000000000000000000000000000000000000..9652e2b5e1896d1b24c277573f073afedfdde351 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetArcResetAction.java @@ -0,0 +1,46 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; + +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetArcResetCommand; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author jan.tancibok + */ +@SuppressWarnings("serial") +public class SetArcResetAction extends AbstractAction { + + private final Root root; + + public SetArcResetAction(final Root root) { + super(); + this.root = root; + String name = "Set reset arc type"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.SETARCRESETACTION)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_R); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null && !this.root.getClickedElement().isNode()) { + final GraphicArc arc = (GraphicArc) this.root.getClickedElement(); + this.root.getUndoManager().executeCommand(new SetArcResetCommand(arc, this.root.getGraphicPetriNet())); + + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetLabelAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetLabelAction.java new file mode 100644 index 0000000000000000000000000000000000000000..bb267e9ab438e1c086d8c7d03f89859df45913e6 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetLabelAction.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetLabelCommand; +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SetLabelAction extends AbstractAction { + + private final Root root; + + public SetLabelAction(final Root root) { + super(); + this.root = root; + String name = "Set label"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.LABEL)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_L); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null + && this.root.getClickedElement().isNode()) { + final GraphicNode clickedNode = (GraphicNode) this.root.getClickedElement(); + final String newLabel = JOptionPane.showInputDialog(this.root.getParentFrame(), "New label:", clickedNode.getNode().getLabel()); + + if (newLabel != null && !newLabel.equals(clickedNode.getNode().getLabel())) { + this.root.getUndoManager().executeCommand(new SetLabelCommand(clickedNode, newLabel)); + } + + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/element/SetTokensAction.java b/pne-editor/src/org/pneditor/editor/actions/element/SetTokensAction.java new file mode 100644 index 0000000000000000000000000000000000000000..37b88f765ed3df4ba5f69325f6dce808087ede42 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/element/SetTokensAction.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.element; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; + +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetTokensCommand; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SetTokensAction extends AbstractAction { + + private final Root root; + + public SetTokensAction(final Root root) { + super(); + this.root = root; + String name = "Set tokens"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.TOKENS)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_T); + setEnabled(false); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (this.root.getClickedElement() != null && this.root.getClickedElement().isPlace()) { + final GraphicPlace place = (GraphicPlace) this.root.getClickedElement(); + int tokens = place.getPlace().getTokens(); + + final String response = JOptionPane.showInputDialog(this.root.getParentFrame(), "Tokens:", tokens); + if (response != null) { + try { + tokens = Integer.parseInt(response); + } catch (NumberFormatException exception) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), + exception.getMessage() + " is not a number"); + } + + if (tokens < 0) { + tokens = place.getPlace().getTokens(); // restore old value + JOptionPane.showMessageDialog(this.root.getParentFrame(), "Number of tokens must be non-negative"); + // TODO : check with model? + } + } + + if (place.getPlace().getTokens() != tokens) { + this.root.getUndoManager().executeCommand(new SetTokensCommand(place, tokens)); + } + + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/ExportAction.java b/pne-editor/src/org/pneditor/editor/actions/file/ExportAction.java new file mode 100644 index 0000000000000000000000000000000000000000..22f3775b751ae95604c77d4590131dfab95bce6b --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/ExportAction.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.filechooser.FileChooserDialog; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.util.GraphicsTools; +import org.pneditor.util.StringTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class ExportAction extends AbstractAction { + + private final Root root; + private final List<FileType> fileTypes; + + public ExportAction(final Root root, final List<FileType> fileTypes) { + super(); + this.root = root; + this.fileTypes = fileTypes; + String name = "Export..."; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.EXPORT)); + putValue(SHORT_DESCRIPTION, name); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final FileChooserDialog chooser = new FileChooserDialog(); + + if (this.root.getCurrentFile() != null) { + chooser.setSelectedFile(new File(StringTools.getExtensionCutOut(this.root.getCurrentFile().getName()))); + } + + for (final FileType fileType : this.fileTypes) { + chooser.addChoosableFileFilter(fileType); + } + chooser.setAcceptAllFileFilterUsed(false); + chooser.setCurrentDirectory(this.root.getCurrentDirectory()); + + if (chooser.showDialog(this.root.getParentFrame(), "Export") == JFileChooser.APPROVE_OPTION) { + final File file = chooser.getSelectedFile(); + final FileType chosenFileType = (FileType) chooser.getFileFilter(); + + if (!file.exists() || JOptionPane.showOptionDialog( + this.root.getParentFrame(), + "Selected file already exists. Overwrite?", + "Export to " + file.getName(), + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"Overwrite", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + try { + chosenFileType.save(this.root.getGraphicPetriNet(), file); + } catch (FileTypeException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage()); + } + } + this.root.setCurrentDirectory(chooser.getCurrentDirectory()); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/ImportAction.java b/pne-editor/src/org/pneditor/editor/actions/file/ImportAction.java new file mode 100644 index 0000000000000000000000000000000000000000..57e50885aedea1886291aecc44e28fe937387f34 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/ImportAction.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.filechooser.FileChooserDialog; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class ImportAction extends AbstractAction { + + private final Root root; + private final List<FileType> fileTypes; + + public ImportAction(final Root root, final List<FileType> fileTypes) { + super(); + this.root = root; + this.fileTypes = fileTypes; + String name = "Import..."; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.IMPORT)); + putValue(SHORT_DESCRIPTION, name); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (!this.root.isModified() || JOptionPane.showOptionDialog( + this.root.getParentFrame(), + "Any unsaved changes will be lost. Continue?", + "Import...", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"Import...", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + final FileChooserDialog chooser = new FileChooserDialog(); + + for (final FileType fileType : this.fileTypes) { + chooser.addChoosableFileFilter(fileType); + } + chooser.setAcceptAllFileFilterUsed(false); + chooser.setCurrentDirectory(this.root.getCurrentDirectory()); + + if (chooser.showDialog(this.root.getParentFrame(), "Import") == JFileChooser.APPROVE_OPTION) { + final File file = chooser.getSelectedFile(); + final FileType chosenFileType = (FileType) chooser.getFileFilter(); + try { + final GraphicPetriNet petriNet = chosenFileType.load(file, this.root.getCurrentModel()); + this.root.setGraphicPetriNet(petriNet); + } catch (FileTypeException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage()); + } + this.root.setCurrentFile(null); + this.root.setCurrentDirectory(chooser.getCurrentDirectory()); + } + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/NewFileAction.java b/pne-editor/src/org/pneditor/editor/actions/file/NewFileAction.java new file mode 100644 index 0000000000000000000000000000000000000000..0f01efbe8a3fef81f01fcffc8548262899a28f58 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/NewFileAction.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class NewFileAction extends AbstractAction { + + private final Root root; + + public NewFileAction(final Root root) { + super(); + this.root = root; + String name = "New"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.NEW16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_N); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (!this.root.isModified() || JOptionPane.showOptionDialog( + this.root.getParentFrame(), + "Any unsaved changes will be lost. Continue?", + "New file", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"New file", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + this.root.setGraphicPetriNet(new GraphicPetriNet(this.root.getCurrentModel())); + this.root.setClickedElement(null); + this.root.refreshAll(); + this.root.getUndoManager().eraseAll(); + this.root.setCurrentFile(null); + this.root.setModified(false); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/OpenFileAction.java b/pne-editor/src/org/pneditor/editor/actions/file/OpenFileAction.java new file mode 100644 index 0000000000000000000000000000000000000000..993fd6328108f2c96e91fb8069de77bd37ce4d09 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/OpenFileAction.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.editor.filechooser.FileChooserDialog; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class OpenFileAction extends AbstractAction { + + private final Root root; + private final List<FileType> fileTypes; + + public OpenFileAction(final Root root, final List<FileType> fileTypes) { + super(); + this.root = root; + this.fileTypes = fileTypes; + String name = "Open..."; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.OPEN16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_O); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (!this.root.isModified() || JOptionPane.showOptionDialog( + this.root.getParentFrame(), + "Any unsaved changes will be lost. Continue?", + "Open file...", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"Open...", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + final FileChooserDialog chooser = new FileChooserDialog(); + + for (final FileType fileType : this.fileTypes) { + chooser.addChoosableFileFilter(fileType); + } + chooser.setAcceptAllFileFilterUsed(false); + chooser.setCurrentDirectory(this.root.getCurrentDirectory()); + + if (chooser.showOpenDialog(this.root.getParentFrame()) == JFileChooser.APPROVE_OPTION) { + + final File file = chooser.getSelectedFile(); + final FileType chosenFileType = (FileType) chooser.getFileFilter(); + + try { + final GraphicPetriNet petriNet = chosenFileType.load(file, this.root.getCurrentModel()); + this.root.setGraphicPetriNet(petriNet); + this.root.setCurrentFile(file); + this.root.setModified(false); + } catch (FileTypeException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage()); + } + + } + this.root.setCurrentDirectory(chooser.getCurrentDirectory()); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/QuitAction.java b/pne-editor/src/org/pneditor/editor/actions/file/QuitAction.java new file mode 100644 index 0000000000000000000000000000000000000000..f8b3e5593e550f569100ade2d484475ef1264125 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/QuitAction.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class QuitAction extends AbstractAction { + + private final Root root; + + public QuitAction(final Root root) { + super(); + this.root = root; + String name = "Quit"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_Q); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl Q")); + } + + @Override + public void actionPerformed(final ActionEvent e) { + this.root.quitApplication(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/SaveAction.java b/pne-editor/src/org/pneditor/editor/actions/file/SaveAction.java new file mode 100644 index 0000000000000000000000000000000000000000..cb13cc231f12f07a2a396a6832039a611976ba86 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/SaveAction.java @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JOptionPane; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SaveAction extends AbstractAction { + + private final Root root; + private final List<FileType> fileTypes; + + public SaveAction(final Root root, final List<FileType> fileTypes) { + super(); + this.root = root; + this.fileTypes = fileTypes; + String name = "Save"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.SAVE16)); + putValue(SHORT_DESCRIPTION, name); + putValue(MNEMONIC_KEY, KeyEvent.VK_S); + putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke("ctrl S")); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final File file = this.root.getCurrentFile(); + if (file != null) { + try { + final FileType fileType = FileType.getAcceptingFileType(file, this.fileTypes); + fileType.save(this.root.getGraphicPetriNet(), file); + this.root.setModified(false); + } catch (FileTypeException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage()); + } + } else { + new SaveFileAsAction(this.root, this.fileTypes).actionPerformed(e); + } + + } + +} diff --git a/pne-editor/src/org/pneditor/editor/actions/file/SaveFileAsAction.java b/pne-editor/src/org/pneditor/editor/actions/file/SaveFileAsAction.java new file mode 100644 index 0000000000000000000000000000000000000000..fb29debb704e43c73e57b2c9609697d00855f59f --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/actions/file/SaveFileAsAction.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.actions.file; + +import java.awt.event.ActionEvent; +import java.io.File; +import java.util.List; +import javax.swing.AbstractAction; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import org.pneditor.editor.Root; +import org.pneditor.util.GraphicsTools; +import org.pneditor.editor.filechooser.FileChooserDialog; +import org.pneditor.editor.filechooser.FileType; +import org.pneditor.editor.filechooser.FileTypeException; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class SaveFileAsAction extends AbstractAction { + + private final Root root; + private final List<FileType> fileTypes; + + public SaveFileAsAction(final Root root, final List<FileType> fileTypes) { + super(); + this.root = root; + this.fileTypes = fileTypes; + String name = "Save as..."; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon(PNEConstantsConfiguration.SAVEAS16)); + putValue(SHORT_DESCRIPTION, name); + } + + @Override + public void actionPerformed(final ActionEvent e) { + final FileChooserDialog chooser = new FileChooserDialog(); + + if (this.root.getCurrentFile() != null) { + chooser.setSelectedFile(this.root.getCurrentFile()); + } + + for (final FileType fileType : this.fileTypes) { + chooser.addChoosableFileFilter(fileType); + } + chooser.setAcceptAllFileFilterUsed(false); + chooser.setCurrentDirectory(this.root.getCurrentDirectory()); + chooser.setDialogTitle("Save as..."); + + if (chooser.showSaveDialog(this.root.getParentFrame()) == JFileChooser.APPROVE_OPTION) { + final File file = chooser.getSelectedFile(); + final FileType chosenFileType = (FileType) chooser.getFileFilter(); + + if (!file.exists() || JOptionPane.showOptionDialog( + this.root.getParentFrame(), + "Selected file already exists. Overwrite?", + "Save as " + file.getName(), + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"Overwrite", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + try { + chosenFileType.save(this.root.getGraphicPetriNet(), file); + } catch (FileTypeException ex) { + JOptionPane.showMessageDialog(this.root.getParentFrame(), ex.getMessage()); + } + } + this.root.setCurrentFile(file); + this.root.setModified(false); + } + this.root.setCurrentDirectory(chooser.getCurrentDirectory()); + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/ArcFeature.java b/pne-editor/src/org/pneditor/editor/canvas/ArcFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..e72f6b4facd60a13db45b5e75d8ebaee5aa43f93 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/ArcFeature.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; + +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.AddArcCommand; +import org.pneditor.editor.gpetrinet.*; +import org.pneditor.util.Colors; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class ArcFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + private GraphicNode sourceElement; + private PreviewArc connectingArc; + private final List<GraphicElement> backgroundElements = new ArrayList<>(); + private boolean started; + private GraphicPetriNet graphicPetriNet; + + ArcFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + } + + @Override + public void mousePressed(final MouseEvent event) { + final int mouseButton = event.getButton(); + + if (mouseButton == MouseEvent.BUTTON1 && this.root.isSelectedToolArc() && this.root.getClickedElement() != null + && this.root.getClickedElement().isNode() && !this.started) { + + final int x = event.getX(); + final int y = event.getY(); + + this.graphicPetriNet = this.root.getGraphicPetriNet(); + this.sourceElement = (GraphicNode) this.graphicPetriNet.getElementByXY(x, y); + this.connectingArc = new PreviewArc(this.sourceElement); + this.backgroundElements.add(this.connectingArc); + this.started = true; + } + } + + @Override + public void mouseDragged(final int x, final int y) { + if (this.root.getGraphicPetriNet() != this.graphicPetriNet) { + cancelDragging(); + } + if (this.started) { + final GraphicElement element = this.root.getGraphicPetriNet().getElementByXY(x, y); + final GraphicNode targetElement = element != null && element.isNode() ? (GraphicNode) element : null; + + if (targetElement != null && (this.sourceElement.isPlace() && !targetElement.isPlace() + || !this.sourceElement.isPlace() && targetElement.isPlace())) { + this.connectingArc.setEnd(targetElement.getCenter().x, targetElement.getCenter().y); + this.connectingArc.setDestination(targetElement); + } else { + this.connectingArc.setEnd(x, y); + this.connectingArc.setSource(null); + this.connectingArc.setDestination(null); + } + this.root.repaintCanvas(); + } + } + + @Override + public void mouseMoved(final int x, final int y) { + mouseDragged(x, y); + } + + @Override + public void mouseReleased(final int x, final int y) { + if (this.root.getGraphicPetriNet() != this.graphicPetriNet) { + cancelDragging(); + } + + if (this.started) { + final GraphicElement element = this.root.getGraphicPetriNet().getElementByXY(x, y); + this.connectingArc.setEnd(x, y); + final GraphicNode targetElement = element != null && element.isNode() ? (GraphicNode) element : null; + + if (this.sourceElement != targetElement) { + if (targetElement != null) { + if (this.sourceElement.isPlace() && !targetElement.isPlace() + || !this.sourceElement.isPlace() && targetElement.isPlace()) { + + this.root.getUndoManager().executeCommand( + new AddArcCommand(this.root.getGraphicPetriNet(), this.sourceElement, targetElement)); + + // last element added to GraphicPetriNet is the arc + this.root.setClickedElement(this.root.getGraphicPetriNet().getLastArcAdded()); + + } + } + cancelDragging(); + } + } + } + + @Override + public void setHoverEffects(final int x, final int y) { + if (this.root.isSelectedToolArc()) { + final GraphicElement targetElement = this.root.getGraphicPetriNet().getElementByXY(x, y); + final List<GraphicElement> highlightedElements = canvas.getHighlightedElements(); + if (this.started) { // Connecting to something... + if (targetElement == null) { // Connecting to air + highlightedElements.add(this.sourceElement); + this.sourceElement.setHighlightColor(Colors.POINTING); + this.root.repaintCanvas(); + } else { // Connecting to solid element + if (this.sourceElement.isPlace() && targetElement.isTransition() + || this.sourceElement.isTransition() && targetElement.isPlace()) { + highlightedElements.add(this.sourceElement); + highlightedElements.add(targetElement); + this.sourceElement.setHighlightColor(Colors.CONNECTING); + targetElement.setHighlightColor(Colors.CONNECTING); + this.root.repaintCanvas(); + } else if (this.sourceElement == targetElement) { + highlightedElements.add(this.sourceElement); + this.sourceElement.setHighlightColor(Colors.POINTING); + this.root.repaintCanvas(); + } else if (targetElement.isNode()) { // Wrong combination + highlightedElements.add(this.sourceElement); + highlightedElements.add(targetElement); + this.sourceElement.setHighlightColor(Colors.DISALLOWED); + targetElement.setHighlightColor(Colors.DISALLOWED); + this.root.repaintCanvas(); + } + } + } else { + if (targetElement != null) { + highlightedElements.add(targetElement); + targetElement.setHighlightColor(Colors.POINTING); + this.root.repaintCanvas(); + } + } + } + } + + @Override + public void drawBackground(final Graphics g) { + for (final GraphicElement element : this.backgroundElements) { + element.draw(g, this.root.getPetriNet()); + } + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + private void cancelDragging() { + this.backgroundElements.remove(this.connectingArc); + this.started = false; + this.root.repaintCanvas(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/Canvas.java b/pne-editor/src/org/pneditor/editor/canvas/Canvas.java new file mode 100644 index 0000000000000000000000000000000000000000..c85797b2f7ad580559c9051d921cd011d3763e9c --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/Canvas.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Component; +import java.awt.Cursor; +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +import java.awt.event.*; +import java.util.ArrayList; +import java.util.List; +import javax.swing.*; +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Point; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class Canvas extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener { + + private final List<GraphicElement> highlightedElements = new ArrayList<>(); + private Cursor alternativeCursor; + public Cursor activeCursor; + public List<Feature> features = new ArrayList<>(); + private final Root root; + private final ScrollingFeature scrollingFeature; + private boolean scrollingFeatureInstalled; + + public Canvas(final Root root) { + super(); + this.root = root; + setBackground(Color.white); + addMouseListener(this); + addMouseMotionListener(this); + addMouseWheelListener(this); + + this.features.add(new ClickFeature(this)); + this.features.add(new PanningFeature(this)); + this.scrollingFeature = new ScrollingFeature(this); + this.features.add(this.scrollingFeature); + this.features.add(new DraggingFeature(this)); + this.features.add(new SelectionDrawingFeature(this)); + this.features.add(new TokenFeature(this)); + this.features.add(new EdgeZigzagFeature(this)); + this.features.add(new PlaceTransitionMakerFeature(this)); + this.features.add(new PopupMenuFeature(this)); + this.features.add(new ArcFeature(this)); + this.features.add(new PetriNetFeature(this)); + } + + public Root getRoot() { + return this.root; + } + + public int getTranslationX() { + return this.root.getGraphicPetriNet().getViewTranslation().x + getWidth() / 2; + } + + public int getTranslationY() { + return this.root.getGraphicPetriNet().getViewTranslation().y + getHeight() / 2; + } + + public Point getViewTranslation() { + return new Point(this.root.getGraphicPetriNet().getViewTranslation()); + } + + public void setViewTranslation(final Point newViewTranslation) { + this.root.getGraphicPetriNet().setViewTranslation(newViewTranslation.getPoint()); + } + + @Override + public void paintComponent(final Graphics g) { + if (!this.scrollingFeatureInstalled) { + this.root.getDrawingBoard().getHorizontalScrollBar().addAdjustmentListener(this.scrollingFeature); + this.root.getDrawingBoard().getVerticalScrollBar().addAdjustmentListener(this.scrollingFeature); + this.scrollingFeatureInstalled = true; + } + + final Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + super.paintComponent(g); + g.translate(getTranslationX(), getTranslationY()); + + for (final Feature f : this.features) { + f.drawBackground(g); + } + for (final Feature f : this.features) { + f.drawMainLayer(g); + } + for (final Feature f : this.features) { + f.drawForeground(g); + } + } + + @Override + public void mouseWheelMoved(final MouseWheelEvent e) { + if (e.getWheelRotation() == 1) { + if (this.root.isSelectedToolPlace()) { + this.root.selectToolTransition(); + } else if (this.root.isSelectedToolTransition()) { + this.root.selectToolArc(); + } else if (this.root.isSelectedToolArc()) { + this.root.selectToolToken(); + } else { + this.root.selectToolPlace(); // if selectToolToken is selected, or default case + } + } else if (e.getWheelRotation() == -1) { + if (this.root.isSelectedToolTransition()) { + this.root.selectToolPlace(); + } else if (this.root.isSelectedToolArc()) { + this.root.selectToolTransition(); + } else if (this.root.isSelectedToolToken()) { + this.root.selectToolArc(); + } else { + this.root.selectToolToken(); // if selectToolPlace is selected or default case + } + } + repaint(); + setHoverEffects(e.getX(), e.getY()); + } + + @Override + public void mousePressed(final MouseEvent event) { + final int x = event.getX() - getTranslationX(); + final int y = event.getY() - getTranslationY(); + final MouseEvent mouseEvent = new MouseEvent((Component) event.getSource(), event.getID(), event.getWhen(), + event.getModifiers(), x, y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), + event.isPopupTrigger(), event.getButton()); + + this.root.setClickedElement(this.root.getGraphicPetriNet().getElementByXY(x, y)); + + for (final Feature f : this.features) { + f.mousePressed(mouseEvent); + } + + if (mouseEvent.getButton() == MouseEvent.BUTTON3 && this.root.getClickedElement() == null) { + // The user did not click on a shape. + this.root.selectToolSelect(); + } + + setCursor(x, y); + setHoverEffects(x, y); + } + + @Override + public void mouseDragged(final MouseEvent event) { + final int x = event.getX() - getTranslationX(); + final int y = event.getY() - getTranslationY(); + + for (final Feature f : this.features) { + f.mouseDragged(x, y); + } + + setHoverEffects(x, y); + } + + @Override + public void mouseReleased(final MouseEvent evt) { + final int x = evt.getX() - getTranslationX(); + final int y = evt.getY() - getTranslationY(); + + for (final Feature f : this.features) { + f.mouseReleased(x, y); + } + + setHoverEffects(x, y); + setCursor(x, y); + } + + @Override + public void mouseMoved(final MouseEvent evt) { + final int x = evt.getX() - getTranslationX(); + final int y = evt.getY() - getTranslationY(); + + for (final Feature f : this.features) { + f.mouseMoved(x, y); + } + + setHoverEffects(x, y); + setCursor(x, y); + } + + void setHoverEffects(final int x, final int y) { + if (!this.highlightedElements.isEmpty()) { + for (final GraphicElement element : this.highlightedElements) { + element.setHighlightColor(null); + } + this.highlightedElements.clear(); + repaint(); + } + for (final Feature f : this.features) { + f.setHoverEffects(x, y); + } + } + + void setCursor(final int x, final int y) { + this.alternativeCursor = null; + + for (final Feature f : this.features) { + f.setCursor(x, y); + } + + Cursor cursor; + if (this.alternativeCursor != null) { + cursor = this.alternativeCursor; + } else { + cursor = this.activeCursor; + } + + if (getCursor() != cursor) { + setCursor(cursor); + } + } + + @Override + public void mouseEntered(final MouseEvent evt) { + } + + @Override + public void mouseExited(final MouseEvent evt) { + } + + @Override + public void mouseClicked(final MouseEvent evt) { + } + + Cursor getAlternativeCursor() { + return alternativeCursor; + } + + void setAlternativeCursor(final Cursor cursor) { + this.alternativeCursor = cursor; + } + + List<GraphicElement> getHighlightedElements() { + return highlightedElements; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/ClickFeature.java b/pne-editor/src/org/pneditor/editor/canvas/ClickFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..121cc57095c1f57b4e419175c301393e9c24d01d --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/ClickFeature.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Colors; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class ClickFeature implements Feature { + + private final Root root; + + private Color previousColor; + + ClickFeature(final Canvas canvas) { + this.root = canvas.getRoot(); + } + + + @Override + public void drawBackground(final Graphics g) { + final GraphicElement element = this.root.getClickedElement(); + if (element != null) { + this.previousColor = element.getColor(); + element.setColor(Colors.SINGLESELECTED); + } + } + + @Override + public void drawForeground(final Graphics g) { + final GraphicElement element = this.root.getClickedElement(); + if (element != null) { + element.setColor(this.previousColor); + } + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void mousePressed(final MouseEvent event) { + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/DraggingFeature.java b/pne-editor/src/org/pneditor/editor/canvas/DraggingFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..d5ac15bdb987700f6f7701cd52d3fe4fd213abe5 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/DraggingFeature.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; + +import java.awt.Cursor; +import java.awt.Point; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.MoveElementCommand; +import org.pneditor.editor.commands.MoveElementsCommand; +import org.pneditor.editor.gpetrinet.GraphicElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class DraggingFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + DraggingFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + } + + private GraphicElement draggedElement; + private Point deltaPosition; + private int prevDragX; // During dragging, these record the x and y coordinates of the + private int prevDragY; // previous position of the mouse. + + @Override + public void mousePressed(final MouseEvent event) { + final boolean doubleclick = event.getClickCount() == 2; + if (!doubleclick) { + final int mouseButton = event.getButton(); + if (mouseButton == MouseEvent.BUTTON1 + && this.root.getClickedElement() != null + && (this.root.isSelectedToolSelect() + || this.root.isSelectedToolPlace() + || this.root.isSelectedToolTransition()) + && this.root.getClickedElement().isNode()) { + if (!this.root.getSelection().contains(this.root.getClickedElement())) { + this.root.getSelection().clear(); + } + final int x = event.getX(); + final int y = event.getY(); + this.draggedElement = this.root.getGraphicPetriNet().getElementByXY(x, y); + this.deltaPosition = new Point(); + this.prevDragX = x; + this.prevDragY = y; + } + } + } + + @Override + public void mouseDragged(final int x, final int y) { + if (this.draggedElement != null) { + doTheMoving(x, y); + this.canvas.repaint(); // redraw canvas to show shape in new position + this.deltaPosition.translate(x - this.prevDragX, y - this.prevDragY); + this.prevDragX = x; + this.prevDragY = y; + } + } + + @Override + public void mouseReleased(final int x, final int y) { + if (this.draggedElement != null) { + doTheMoving(x, y); + this.deltaPosition.translate(x - this.prevDragX, y - this.prevDragY); + saveTheMoving(); + this.canvas.repaint(); + this.draggedElement = null; // Dragging is finished. + } + } + + private void doTheMoving(final int mouseX, final int mouseY) { + if (this.root.getSelection().isEmpty()) { + this.draggedElement.moveBy(mouseX - this.prevDragX, mouseY - this.prevDragY); + } else { + for (final GraphicElement selectedElement : this.root.getSelection()) { + selectedElement.moveBy(mouseX - this.prevDragX, mouseY - this.prevDragY); + } + } + } + + private void saveTheMoving() { + if (!this.deltaPosition.equals(new Point(0, 0))) { + if (this.root.getSelection().isEmpty()) { + this.draggedElement.moveBy(-this.deltaPosition.x, -this.deltaPosition.y); //move back to original position + this.root.getUndoManager().executeCommand(new MoveElementCommand(this.draggedElement, this.deltaPosition)); + } else { + for (final GraphicElement selectedElement : this.root.getSelection()) { + selectedElement.moveBy(-this.deltaPosition.x, -this.deltaPosition.y); //move back to original positions + } + this.root.getUndoManager().executeCommand(new MoveElementsCommand(this.root.getSelection().getElements(), this.deltaPosition)); + } + } + } + + @Override + public void setCursor(final int x, final int y) { + + if (this.root.isSelectedToolSelect() + || this.root.isSelectedToolPlace() + || this.root.isSelectedToolTransition()) { + + final GraphicElement element = this.root.getGraphicPetriNet().getElementByXY(x, y); + if (element != null && element.isNode()) { + this.canvas.setAlternativeCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } + } + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/EdgeZigzagFeature.java b/pne-editor/src/org/pneditor/editor/canvas/EdgeZigzagFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..15d9bdb84c7474167b48e611a43fa191b69f4fbd --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/EdgeZigzagFeature.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; + +import java.awt.Point; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.SetEdgeZigzagPointCommand; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Colors; +import org.pneditor.util.GraphicsTools; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class EdgeZigzagFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + private Point activeBreakPoint; + private boolean started; + private final VisualHandle visualHandle = new VisualHandle(); + private final List<VisualHandle> foregroundVisualElements = new ArrayList<>(); + + private Point startingMouseLocation; + private List<Point> oldBreakPoints; + private GraphicArc arc; + + EdgeZigzagFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + this.visualHandle.setColor(Colors.POINTING); + this.visualHandle.setSize(GraphicArc.NEARTOLERANCE, GraphicArc.NEARTOLERANCE); + } + + + @Override + public void mousePressed(final MouseEvent event) { + final int mouseButton = event.getButton(); + + if (mouseButton == MouseEvent.BUTTON1 + && this.root.getClickedElement() != null + && (this.root.isSelectedToolSelect() + || this.root.isSelectedToolPlace() + || this.root.isSelectedToolTransition() + || this.root.isSelectedToolArc() + || this.root.isSelectedToolToken() && !(this.root.getClickedElement().isPlace())) + && !this.root.getClickedElement().isNode()) { + if (!this.root.getSelection().contains(this.root.getClickedElement())) { + this.root.getSelection().clear(); + } + final int x = event.getX(); + final int y = event.getY(); + + this.arc = (GraphicArc) this.root.getGraphicPetriNet().getElementByXY(x, y); + + this.oldBreakPoints = this.arc.getBreakPointsCopy(); + this.startingMouseLocation = new Point(x, y); + this.activeBreakPoint = this.arc.addOrGetBreakPoint(new Point(this.startingMouseLocation)); + this.started = true; + } + } + + @Override + public void mouseDragged(final int x, final int y) { + if (this.started) { + this.activeBreakPoint.move(x, y); + this.canvas.repaint(); + } + } + + @Override + public void mouseReleased(final int x, final int y) { + if (this.started) { + this.arc.cleanupUnecessaryBreakPoints(); + + boolean change = false; + if (this.oldBreakPoints.size() != this.arc.getBreakPoints().size()) { + change = true; + } else { + for (int i = 0; i < this.arc.getBreakPoints().size(); i++) { + if (!this.arc.getBreakPoints().get(i).equals(this.oldBreakPoints.get(i))) { + change = true; + break; + } + } + } + if (change) { + this.arc.setBreakPoints(this.oldBreakPoints); + final Point targetLocation = new Point(x, y); + this.root.getUndoManager().executeCommand(new SetEdgeZigzagPointCommand(this.arc, this.startingMouseLocation, targetLocation)); + } + this.started = false; + } + } + + @Override + public void setHoverEffects(final int x, final int y) { + if (this.root.isSelectedToolSelect() + || this.root.isSelectedToolPlace() + || this.root.isSelectedToolTransition() + || this.root.isSelectedToolArc() + || this.root.isSelectedToolToken()) { + final GraphicElement element = this.root.getGraphicPetriNet().getElementByXY(x, y); + boolean drawHandle = false; + if (element != null && !element.isNode()) { + final GraphicArc anArc = (GraphicArc) element; + for (final Point breakPoint : anArc.getBreakPoints()) { + final Point mousePos = new Point(x, y); + if (GraphicsTools.isPointNearPoint(breakPoint, mousePos, GraphicArc.NEARTOLERANCE)) { + if (!this.foregroundVisualElements.contains(this.visualHandle)) { + this.foregroundVisualElements.add(this.visualHandle); + } + this.visualHandle.setCenter(breakPoint.x, breakPoint.y); + drawHandle = true; + + break; + } + } + } + if (!drawHandle) { + this.foregroundVisualElements.remove(this.visualHandle); + } + + if (element != null) { + this.canvas.getHighlightedElements().add(element); + element.setHighlightColor(Colors.POINTING); + this.canvas.repaint(); + } + } + } + + @Override + public void drawForeground(final Graphics g) { + for (final VisualHandle element : this.foregroundVisualElements) { + element.draw(g); + } + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/Feature.java b/pne-editor/src/org/pneditor/editor/canvas/Feature.java new file mode 100644 index 0000000000000000000000000000000000000000..2999a0f6af8e97142969c3e42fd1eaaeff9abeed --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/Feature.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public interface Feature { + + void drawForeground(Graphics g); + + void drawMainLayer(Graphics g); + + void drawBackground(Graphics g); + + void mousePressed(MouseEvent event); + + void mouseDragged(int x, int y); + + void mouseReleased(int x, int y); + + void mouseMoved(int x, int y); + + void setHoverEffects(int x, int y); + + void setCursor(int x, int y); +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/PanningFeature.java b/pne-editor/src/org/pneditor/editor/canvas/PanningFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..06889198e03fcc9d5348fde7cd82590ddb76dc53 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/PanningFeature.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class PanningFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + private int prevDragX; + private int prevDragY; + private boolean panning; + + PanningFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + } + + @Override + public void mousePressed(final MouseEvent event) { + + final int mouseButton = event.getButton(); + + if (mouseButton == MouseEvent.BUTTON2 + || mouseButton == MouseEvent.BUTTON1 && event.isControlDown()) { + + final int realX = event.getX() + this.canvas.getTranslationX(); + final int realY = event.getY() + this.canvas.getTranslationY(); + + this.prevDragX = realX; + this.prevDragY = realY; + this.panning = true; + } + } + + @Override + public void mouseDragged(final int x, final int y) { + if (this.panning) { + final int realX = x + this.canvas.getTranslationX(); + final int realY = y + this.canvas.getTranslationY(); + + doThePanning(realX, realY); + this.canvas.repaint(); + this.prevDragX = realX; + this.prevDragY = realY; + } + } + + @Override + public void mouseReleased(final int x, final int y) { + if (this.panning) { + final int realX = x + this.canvas.getTranslationX(); + final int realY = y + this.canvas.getTranslationY(); + + doThePanning(realX, realY); + this.canvas.repaint(); + this.panning = false; + } + } + + private void doThePanning(final int mouseX, final int mouseY) { + final Point viewTranslation = this.root.getGraphicPetriNet().getViewTranslation(); + viewTranslation.translate(mouseX - this.prevDragX, mouseY - this.prevDragY); + this.root.getGraphicPetriNet().setViewTranslation(viewTranslation); + } + + @Override + public void setCursor(final int x, final int y) { + if (this.panning) { + this.canvas.setAlternativeCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/PetriNetFeature.java b/pne-editor/src/org/pneditor/editor/canvas/PetriNetFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..9474f7ae4610e3a2734f1bf823261b4fc1f33767 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/PetriNetFeature.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; + + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PetriNetFeature implements Feature { + + private final Root root; + + public PetriNetFeature(final Canvas canvas) { + this.root = canvas.getRoot(); + } + + @Override + public void drawMainLayer(final Graphics g) { + this.root.getGraphicPetriNet().draw(g); + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void mousePressed(final MouseEvent event) { + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } + +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/PlaceTransitionMakerFeature.java b/pne-editor/src/org/pneditor/editor/canvas/PlaceTransitionMakerFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..ee909a242181a8fb7129834682c5bec412e06e97 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/PlaceTransitionMakerFeature.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.AddPlaceCommand; +import org.pneditor.editor.commands.AddTransitionCommand; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PlaceTransitionMakerFeature implements Feature { + + private final Root root; + + public PlaceTransitionMakerFeature(final Canvas canvas) { + this.root = canvas.getRoot(); + } + + @Override + public void mousePressed(final MouseEvent event) { + final int mouseButton = event.getButton(); + + if (mouseButton == MouseEvent.BUTTON1 && this.root.getClickedElement() == null) { + final int x = event.getX(); + final int y = event.getY(); + if (this.root.isSelectedToolPlace()) { + this.root.getSelection().clear(); + this.root.getUndoManager().executeCommand(new AddPlaceCommand(x, y, this.root.getGraphicPetriNet())); + this.root.setClickedElement(this.root.getGraphicPetriNet().getLastElementAdded()); + } else if (this.root.isSelectedToolTransition()) { + this.root.getSelection().clear(); + this.root.getUndoManager() + .executeCommand(new AddTransitionCommand(x, y, this.root.getGraphicPetriNet())); + this.root.setClickedElement(this.root.getGraphicPetriNet().getLastElementAdded()); + } + + } + + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/PopupMenuFeature.java b/pne-editor/src/org/pneditor/editor/canvas/PopupMenuFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..c334d4af6416919ecdadc71ae5622a9e62aab2e2 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/PopupMenuFeature.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import javax.swing.JPopupMenu; +import org.pneditor.editor.Root; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PopupMenuFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + public PopupMenuFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + } + + @Override + public void mousePressed(final MouseEvent event) { + final int mouseButton = event.getButton(); + if (mouseButton == MouseEvent.BUTTON3) { + final int realX = event.getX() + this.canvas.getTranslationX(); + final int realY = event.getY() + this.canvas.getTranslationY(); + + if (this.root.getClickedElement() != null + && (this.root.isSelectedToolSelect() + || this.root.isSelectedToolPlace() + || this.root.isSelectedToolTransition() + || this.root.isSelectedToolArc() + || (this.root.isSelectedToolToken() && !this.root.getClickedElement().isPlace()))) { + //if token selected, right click disallowed on Place (because it's removing tokens normally) + if (this.root.getClickedElement().isPlace()) { + showPopup(this.root.getPlacePopup(), realX, realY); + if (!this.root.getSelection().contains(this.root.getClickedElement())) { + this.root.getSelection().clear(); + } + } else if (this.root.getClickedElement().isTransition()) { + showPopup(this.root.getTransitionPopup(), realX, realY); + if (!this.root.getSelection().contains(this.root.getClickedElement())) { + this.root.getSelection().clear(); + } + } else if (!this.root.getClickedElement().isNode()) { + showPopup(this.root.getArcPopup(), realX, realY); + if (!this.root.getSelection().contains(this.root.getClickedElement())) { + this.root.getSelection().clear(); + } + } + } + + if (this.root.getClickedElement() == null + && this.root.isSelectedToolSelect()) { + showPopup(this.root.getCanvasPopup(), realX, realY); + } + } + } + + private void showPopup(final JPopupMenu popupMenu, final int clickedX, final int clickedY) { + popupMenu.show(this.canvas, clickedX - 10, clickedY - 2); + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } + +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/ScrollingFeature.java b/pne-editor/src/org/pneditor/editor/canvas/ScrollingFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..3a399aa81e7474fa7548a66846d726b29746e732 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/ScrollingFeature.java @@ -0,0 +1,162 @@ +package org.pneditor.editor.canvas; + +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.AdjustmentEvent; +import java.awt.event.AdjustmentListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import javax.swing.JScrollBar; + +import org.pneditor.editor.Root; +import org.pneditor.util.Point; + +/** + * + * @author matmas + */ +public class ScrollingFeature implements Feature, MouseListener, MouseMotionListener, AdjustmentListener { + + private final Canvas canvas; + private final Root root; + private int prevDragX; + private int prevDragY; + private boolean scrolling; + + public ScrollingFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + canvas.addMouseListener(this); + canvas.addMouseMotionListener(this); + } + + @Override + public void mousePressed(final MouseEvent e) { + if (e.getButton() == MouseEvent.BUTTON2 + || e.getButton() == MouseEvent.BUTTON1 && e.isControlDown()) { + this.prevDragX = e.getX(); + this.prevDragY = e.getY(); + this.scrolling = true; + } + } + + @Override + public void mouseDragged(final MouseEvent e) { + if (this.scrolling) { + doTheScrolling(e.getX(), e.getY()); + this.prevDragX = e.getX(); + this.prevDragY = e.getY(); + } + } + + @Override + public void mouseReleased(final MouseEvent e) { + if (this.scrolling) { + doTheScrolling(e.getX(), e.getY()); + this.scrolling = false; + } + } + + private void doTheScrolling(final int mouseX, final int mouseY) { + final Point viewTranslation = this.canvas.getViewTranslation(); + this.canvas.setViewTranslation(viewTranslation.getTranslated(mouseX - this.prevDragX, mouseY - this.prevDragY)); + this.canvas.repaint(); + } + + @Override + public void drawForeground(final Graphics g) { + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void drawMainLayer(final Graphics g) { + final Rectangle petriNetBounds = this.root.getGraphicPetriNet().getBounds(); + final Rectangle canvasBounds = this.canvas.getBounds(); + + final JScrollBar horizontalScrollBar = this.root.getDrawingBoard().getHorizontalScrollBar(); + final JScrollBar verticalScrollBar = this.root.getDrawingBoard().getVerticalScrollBar(); + + canvasBounds.translate(-this.canvas.getViewTranslation().getX(), -this.canvas.getViewTranslation().getY()); // to account for translation + petriNetBounds.translate(this.canvas.getWidth() / 2, this.canvas.getHeight() / 2); // [0, 0] is in center + + // Union of the two rectangles: + if (!petriNetBounds.isEmpty()) { + petriNetBounds.add(canvasBounds); + } + + horizontalScrollBar.setEnabled(false); + horizontalScrollBar.setMinimum(petriNetBounds.x); + horizontalScrollBar.setMaximum(petriNetBounds.x + petriNetBounds.width); + horizontalScrollBar.setVisibleAmount(canvasBounds.width); + horizontalScrollBar.setValue(-this.canvas.getViewTranslation().getX()); + horizontalScrollBar.setEnabled(true); + + verticalScrollBar.setEnabled(false); + verticalScrollBar.setMinimum(petriNetBounds.y); + verticalScrollBar.setMaximum(petriNetBounds.y + petriNetBounds.height); + verticalScrollBar.setVisibleAmount(canvasBounds.height); + verticalScrollBar.setValue(-this.canvas.getViewTranslation().getY()); + verticalScrollBar.setEnabled(true); + } + + @Override + public void mouseClicked(final MouseEvent e) { + } + + @Override + public void mouseEntered(final MouseEvent e) { + } + + @Override + public void mouseExited(final MouseEvent e) { + } + + @Override + public void mouseMoved(final MouseEvent e) { + } + + @Override + public void adjustmentValueChanged(final AdjustmentEvent e) { + final JScrollBar scrollBar = (JScrollBar) e.getSource(); + if (!this.scrolling && scrollBar.isEnabled()) { + final int value = e.getValue(); + Point viewTranslation = this.canvas.getViewTranslation(); + if (e.getSource() == this.root.getDrawingBoard().getHorizontalScrollBar()) { + viewTranslation = new Point(-value, viewTranslation.getY()); + } + if (e.getSource() == this.root.getDrawingBoard().getVerticalScrollBar()) { + viewTranslation = new Point(viewTranslation.getX(), -value); + } + this.canvas.setViewTranslation(viewTranslation); + this.canvas.repaint(); + } + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } + + @Override + public void setHoverEffects(final int x, final int y) { + } + + @Override + public void setCursor(final int x, final int y) { + if (this.scrolling) { + this.canvas.setAlternativeCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/Selection.java b/pne-editor/src/org/pneditor/editor/canvas/Selection.java new file mode 100644 index 0000000000000000000000000000000000000000..46cd06402759646da891cde62c304bf06468b5e7 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/Selection.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class Selection implements Iterable<GraphicElement> { + + private final Set<GraphicElement> selectedElements = new HashSet<>(); + private SelectionChangedListener selectionChangedListener; + + public void setSelectionChangedListener(final SelectionChangedListener selectionChangedListener) { + this.selectionChangedListener = selectionChangedListener; + } + + public void clear() { + this.selectedElements.clear(); + selectionChanged(); + } + + public void add(final GraphicElement element) { + this.selectedElements.add(element); + selectionChanged(); + } + + public void addAll(final Collection<? extends GraphicElement> elements) { + this.selectedElements.addAll(elements); + selectionChanged(); + } + + public boolean isEmpty() { + return this.selectedElements.isEmpty(); + } + + public boolean contains(final GraphicElement element) { + return this.selectedElements.contains(element); + } + + public void selectionChanged() { + if (this.selectionChangedListener != null) { + this.selectionChangedListener.selectionChanged(); + } + } + + @Override + public Iterator<GraphicElement> iterator() { + return this.selectedElements.iterator(); + } + + public Set<GraphicElement> getElements() { + return this.selectedElements; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/SelectionChangedListener.java b/pne-editor/src/org/pneditor/editor/canvas/SelectionChangedListener.java new file mode 100644 index 0000000000000000000000000000000000000000..420778f034c158fe045af39eb7a5d43e63f66c23 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/SelectionChangedListener.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public interface SelectionChangedListener { + + void selectionChanged(); +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/SelectionDrawingFeature.java b/pne-editor/src/org/pneditor/editor/canvas/SelectionDrawingFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..5c92200d9b7b4c3a295f5af0531a05bf79f0223e --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/SelectionDrawingFeature.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.Graphics; +import java.awt.event.MouseEvent; +import java.util.HashSet; +import java.util.Set; +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Colors; + + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class SelectionDrawingFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + private boolean selecting; + private final VisualSelection visualSelection = new VisualSelection(); + private final Set<GraphicElement> previousSelection = new HashSet<>(); + + SelectionDrawingFeature(Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + } + + @Override + public void mousePressed(final MouseEvent event) { + + final int mouseButton = event.getButton(); + + if (mouseButton == MouseEvent.BUTTON1 + && this.root.getClickedElement() == null + && this.root.isSelectedToolSelect()) { + final int x = event.getX(); + final int y = event.getY(); + this.selecting = true; + this.visualSelection.setStart(x, y); + this.visualSelection.setEnd(x, y); + this.canvas.repaint(); + if (event.isShiftDown()) { + this.previousSelection.addAll(this.root.getSelection().getElements()); + } else { + this.root.getSelection().clear(); + this.previousSelection.clear(); + } + } + } + + @Override + public void mouseDragged(final int x, final int y) { + if (this.selecting) { + this.visualSelection.setEnd(x, y); + this.canvas.repaint(); + } + } + + @Override + public void mouseReleased(final int x, final int y) { + if (this.selecting) { + this.selecting = false; + this.canvas.repaint(); + } + } + + @Override + public void setHoverEffects(final int x, final int y) { + for (final GraphicElement selectedElement : this.root.getSelection()) { + this.canvas.getHighlightedElements().add(selectedElement); + selectedElement.setHighlightColor(Colors.SELECTED); + } + + if (this.selecting) { + this.root.getSelection().clear(); + this.root.getSelection().addAll(this.previousSelection); + for (final GraphicElement visualElement : this.root.getGraphicPetriNet().getElements()) { + if (this.visualSelection.containsPoint(visualElement.getCenter().x, visualElement.getCenter().y)) { + addElementToSelection(visualElement); + } + } + this.canvas.repaint(); + } + } + + private void addElementToSelection(final GraphicElement element) { + this.canvas.getHighlightedElements().add(element); + element.setHighlightColor(Colors.SELECTED); + + this.root.getSelection().add(element); + } + + @Override + public void drawForeground(final Graphics g) { + if (this.selecting) { + this.visualSelection.draw(g); + } + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void setCursor(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/TokenFeature.java b/pne-editor/src/org/pneditor/editor/canvas/TokenFeature.java new file mode 100644 index 0000000000000000000000000000000000000000..a7dd0d8ce93b760d3eef4376a7dbace529e8dc6b --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/TokenFeature.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + +import java.awt.BasicStroke; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.event.MouseEvent; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.AddTokenCommand; +import org.pneditor.editor.commands.FireTransitionCommand; +import org.pneditor.editor.commands.RemoveTokenCommand; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.util.Colors; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +class TokenFeature implements Feature { + + private final Canvas canvas; + private final Root root; + + private final Cursor tokenCursor; + private final Cursor fireCursor; + + TokenFeature(final Canvas canvas) { + this.canvas = canvas; + this.root = canvas.getRoot(); + this.tokenCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.TOKEN, new Point(16, 0)); + this.fireCursor = GraphicsTools.getCursor(PNEConstantsConfiguration.FIRE, new Point(16, 0)); + } + + @Override + public void mousePressed(final MouseEvent event) { + + if (this.root.getClickedElement() != null && this.root.isSelectedToolToken()) { + final int x = event.getX(); + final int y = event.getY(); + final int mouseButton = event.getButton(); + final GraphicElement targetElement = this.root.getGraphicPetriNet().getElementByXY(x, y); + + if (targetElement.isPlace()) { + final GraphicPlace place = (GraphicPlace) targetElement; + if (mouseButton == MouseEvent.BUTTON1) { + this.root.getUndoManager().executeCommand(new AddTokenCommand(place)); + } else if (mouseButton == MouseEvent.BUTTON3 && place.getPlace().getTokens() > 0) { + this.root.getUndoManager().executeCommand(new RemoveTokenCommand(place)); + } + + } else if (targetElement.isTransition()) { + final GraphicTransition transition = (GraphicTransition) targetElement; + if (mouseButton == MouseEvent.BUTTON1) { + try { + final PetriNetInterface petriNet = this.root.getPetriNet(); + if (petriNet.isEnabled(transition.getTransition())) { + this.root.getUndoManager().executeCommand( + new FireTransitionCommand(transition, this.root.getGraphicPetriNet())); + } + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + } + } + } + + @Override + public void setHoverEffects(final int x, final int y) { + final GraphicElement targetElement = this.root.getGraphicPetriNet().getElementByXY(x, y); + + if (this.root.isSelectedToolToken() && targetElement != null) { + if (targetElement.isPlace()) { + this.canvas.getHighlightedElements().add(targetElement); + targetElement.setHighlightColor(Colors.POINTING); + this.canvas.repaint(); + } else if (targetElement.isTransition()) { + try { + final PetriNetInterface petriNet = this.root.getPetriNet(); + if (petriNet.isEnabled(((GraphicTransition) targetElement).getTransition())) { + this.canvas.getHighlightedElements().add(targetElement); + targetElement.setHighlightColor(Colors.PERMITTED); + this.canvas.repaint(); + } else { + this.canvas.getHighlightedElements().add(targetElement); + targetElement.setHighlightColor(Colors.DISALLOWED); + this.canvas.repaint(); + } + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + } + } + + @Override + public void drawForeground(final Graphics g) { + + if (this.root.isSelectedToolToken()) { + for (final GraphicElement element : this.root.getGraphicPetriNet().getElements()) { + if (element.isTransition()) { + final GraphicTransition transition = (GraphicTransition) element; + try { + final PetriNetInterface petriNet = this.root.getPetriNet(); + if (petriNet.isEnabled(transition.getTransition())) { + g.setColor(Colors.PERMITTED); + } else { + g.setColor(Colors.DISALLOWED); + } + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + ((Graphics2D) g).setStroke(new BasicStroke(2f)); + g.drawRect(transition.getStart().x + 1, transition.getStart().y + 1, transition.getWidth() - 3, + transition.getHeight() - 3); + ((Graphics2D) g).setStroke(new BasicStroke(1f)); + } + } + } + } + + @Override + public void setCursor(final int x, final int y) { + final GraphicElement targetElement = this.root.getGraphicPetriNet().getElementByXY(x, y); + + if (this.root.isSelectedToolToken() && targetElement != null) { + if (targetElement.isPlace()) { + this.canvas.setAlternativeCursor(this.tokenCursor); + } else if (targetElement.isTransition()) { + this.canvas.setAlternativeCursor(this.fireCursor); + } + } + + } + + @Override + public void drawBackground(final Graphics g) { + } + + @Override + public void mouseDragged(final int x, final int y) { + } + + @Override + public void mouseReleased(final int x, final int y) { + } + + @Override + public void drawMainLayer(final Graphics g) { + } + + @Override + public void mouseMoved(final int x, final int y) { + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/VisualHandle.java b/pne-editor/src/org/pneditor/editor/canvas/VisualHandle.java new file mode 100644 index 0000000000000000000000000000000000000000..c34976c50c668e804cc583551d2035153a49052f --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/VisualHandle.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.petrinet.PetriNetInterface; + +import java.awt.Graphics; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ + +class VisualHandle extends GraphicElement { + + public void draw(final Graphics g) { + g.setColor(this.color); + g.drawRect(Math.min(getStart().x, getEnd().x), Math.min(getStart().y, getEnd().y), getWidth(), getHeight()); + } + + @Override + public void draw(final Graphics g, final PetriNetInterface petriNet) { + draw(g); + } + + @Override + public boolean isNode() { + return false; + } + + @Override + public boolean isPlace() { + return false; + } + + @Override + public boolean isTransition() { + return false; + } +} diff --git a/pne-editor/src/org/pneditor/editor/canvas/VisualSelection.java b/pne-editor/src/org/pneditor/editor/canvas/VisualSelection.java new file mode 100644 index 0000000000000000000000000000000000000000..4412507bf16b129301497cf0791d22c3eec08b98 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/canvas/VisualSelection.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.canvas; + + +import java.awt.Graphics; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.util.GraphicsTools; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ + +class VisualSelection extends GraphicElement { + + + public void draw(final Graphics g) { + g.setColor(this.color); + GraphicsTools.setDashedStroke(g); + g.drawRect(Math.min(getStart().x, getEnd().x), Math.min(getStart().y, getEnd().y), getWidth(), getHeight()); + GraphicsTools.setDefaultStroke(g); + } + + @Override + public void draw(final Graphics g, final PetriNetInterface petriNet) { + draw(g); + } + + @Override + public boolean isNode() { + return false; + } + + @Override + public boolean isPlace() { + return false; + } + + @Override + public boolean isTransition() { + return false; + } +} diff --git a/pne-editor/src/org/pneditor/editor/commands/AddArcCommand.java b/pne-editor/src/org/pneditor/editor/commands/AddArcCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..25953e8b504766d3184675ffc2fc1b7a10e6e033 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/AddArcCommand.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.petrinet.UnimplementedCaseException; +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class AddArcCommand implements Command { + + final private GraphicPetriNet gPetriNet; + final private GraphicNode source; + final private GraphicNode destination; + private AbstractArc createdArc; + private GraphicArc representation; + + public AddArcCommand(final GraphicPetriNet gPetriNet, final GraphicNode source, final GraphicNode destination) { + this.gPetriNet = gPetriNet; + this.source = source; + this.destination = destination; + } + + @Override + public void execute() { + try { + this.createdArc = this.gPetriNet.getPetriNet().addRegArc(this.source.getNode(), this.destination.getNode()); + } catch (UnimplementedCaseException e) { + PNEditorLogger.infoLogs(e.getMessage()); + // do nothing, that means something is not implemented + // and that the rest should not happen + } + if (this.createdArc != null) { + this.representation = new GraphicArc(this.createdArc); + this.representation.setSource(this.source); + this.representation.setDestination(this.destination); + this.gPetriNet.addElement(this.representation); + } + } + + @Override + public void undo() { + new DeleteArcCommand(this.representation, this.gPetriNet).execute(); + } + + @Override + public void redo() { + int oldMultiplicity = 0; + try { + oldMultiplicity = this.createdArc.getMultiplicity(); // in case the initial multiplicity is the same in the actual model, + // we save the old one, and give it back when adding again the arc + execute(); + if (oldMultiplicity > 0) { + this.createdArc.setMultiplicity(oldMultiplicity); + } + + } catch (ResetArcMultiplicityException e) { + execute(); //forget about the multiplicity issue + } + } + + @Override + public String toString() { + return "Add arc"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/AddPlaceCommand.java b/pne-editor/src/org/pneditor/editor/commands/AddPlaceCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..f260eaab6e6873d65d8149af206183e9da0bce81 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/AddPlaceCommand.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class AddPlaceCommand implements Command { + + final private GraphicPetriNet gPetriNet ; + final private int x, y; + private AbstractPlace createdPlace; + private GraphicPlace representation; + + public AddPlaceCommand(final int x, final int y, final GraphicPetriNet gPetriNet) { + this.x = x; + this.y = y; + this.gPetriNet = gPetriNet; + } + + @Override + public void execute() { + this.createdPlace = this.gPetriNet.getPetriNet().addAbstractPlace(); + this.representation = new GraphicPlace(this.createdPlace, this.x, this.y); + this.gPetriNet.addElement(this.representation); + } + + @Override + public void undo() { + new DeletePlaceCommand(this.representation, this.gPetriNet).execute(); + } + + @Override + public void redo() { + final AbstractPlace newPlace = this.gPetriNet.getPetriNet().addAbstractPlace(); + newPlace.setLabel(this.createdPlace.getLabel()); // in case of a given name on construction, we put it back + newPlace.setTokens(this.createdPlace.getTokens()); // same as before, except with tokens + this.representation.setPlace(newPlace); + this.gPetriNet.addElement(this.representation); + } + + @Override + public String toString() { + return "Add place"; + } + + public AbstractPlace getCreatedPlace() { + return this.createdPlace; + } +} diff --git a/pne-editor/src/org/pneditor/editor/commands/AddTokenCommand.java b/pne-editor/src/org/pneditor/editor/commands/AddTokenCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..ae910d1d2e58be592b8ff1be324a414eef7e95bd --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/AddTokenCommand.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class AddTokenCommand implements Command { + + private AbstractPlace place; + final private GraphicPlace gPlace; + + public AddTokenCommand(GraphicPlace gPlace) { + this.gPlace = gPlace; + } + + @Override + public void execute() { + this.place = this.gPlace.getPlace(); + this.place.addToken(); + } + + @Override + public void undo() { + this.place = this.gPlace.getPlace(); + this.place.removeToken(); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Add token"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/AddTransitionCommand.java b/pne-editor/src/org/pneditor/editor/commands/AddTransitionCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..e8a87579e9ac1ed01a023c7eb01b6ff2c2f16eef --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/AddTransitionCommand.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class AddTransitionCommand implements Command { + + final private int x, y; + private AbstractTransition createdTransition; + final private GraphicPetriNet gPetriNet; + private GraphicTransition representation; + + public AddTransitionCommand(int x, int y, GraphicPetriNet gPetriNet) { + this.x = x; + this.y = y; + this.gPetriNet = gPetriNet; + } + + @Override + public void execute() { + this.createdTransition = this.gPetriNet.getPetriNet().addAbstractTransition(); + this.representation = new GraphicTransition(this.createdTransition, this.x, this.y); + this.gPetriNet.addElement(this.representation); + } + + @Override + public void undo() { + new DeleteTransitionCommand(this.representation, this.gPetriNet).execute(); + } + + @Override + public void redo() { + final AbstractTransition newTransition = this.gPetriNet.getPetriNet().addAbstractTransition(); + newTransition.setLabel(this.createdTransition.getLabel()); // in case of a given name on construction, + //we put it back (different models for instance) + this.representation.setTransition(newTransition); + this.gPetriNet.addElement(this.representation); + } + + @Override + public String toString() { + return "Add transition"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/CutCommand.java b/pne-editor/src/org/pneditor/editor/commands/CutCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..b5ba2eb90edf4200f8ac2696a0d5d0178378db6d --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/CutCommand.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class CutCommand implements Command { + + final private Command deleteElements; + + public CutCommand(final Set<GraphicElement> elementsToDelete, final GraphicPetriNet petriNet) { + this.deleteElements = new DeleteElementsCommand(elementsToDelete, petriNet); + } + + @Override + public void execute() { + this.deleteElements.execute(); + } + + @Override + public void undo() { + this.deleteElements.undo(); + } + + @Override + public void redo() { + this.deleteElements.redo(); + } + + @Override + public String toString() { + return "Cut"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/DeleteArcCommand.java b/pne-editor/src/org/pneditor/editor/commands/DeleteArcCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..b830a2e37fab34e774eb254014f180d60854e105 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/DeleteArcCommand.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DeleteArcCommand implements Command { + + final private GraphicArc gArc; + final private GraphicPetriNet gPetriNet; + private boolean isAlreadyDeleted; + + public DeleteArcCommand(final GraphicArc gArc, final GraphicPetriNet gPetriNet) { + this.gPetriNet = gPetriNet; + this.gArc = gArc; + } + + @Override + public void execute() { + this.isAlreadyDeleted = !this.gPetriNet.getArcs().contains(this.gArc); + if (!this.isAlreadyDeleted) { + this.gPetriNet.getPetriNet().removeAbstractArc(this.gArc.getArc()); + this.gPetriNet.removeElement(this.gArc); + } + } + + @Override + public void undo() { + if (!this.isAlreadyDeleted) { + AbstractNode source = gArc.getSource().getNode(); + AbstractNode destination = gArc.getDestination().getNode(); + this.gPetriNet.getPetriNet().addArcAgain(this.gArc.getArc(), source, destination); + this.gPetriNet.addElement(this.gArc); + } + } + + @Override + public void redo() { + this.isAlreadyDeleted = !this.gPetriNet.getArcs().contains(this.gArc); + if (!this.isAlreadyDeleted) { + this.gPetriNet.getPetriNet().removeAbstractArc(this.gArc.getArc()); + this.gPetriNet.removeElement(this.gArc); + } + } + + @Override + public String toString() { + return "Delete arc"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/DeleteElementCommand.java b/pne-editor/src/org/pneditor/editor/commands/DeleteElementCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..45edc871ee56656ac5b9baa233cb620b03215fb7 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/DeleteElementCommand.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DeleteElementCommand implements Command { + + private Command deleteElement; + + public DeleteElementCommand(final GraphicElement element, final GraphicPetriNet petriNet) { + if (element.isPlace()) { + this.deleteElement = new DeletePlaceCommand((GraphicPlace) element, petriNet); + } else if (element.isTransition()) { + this.deleteElement = new DeleteTransitionCommand((GraphicTransition) element, petriNet); + } else if (!element.isNode()) { + this.deleteElement = new DeleteArcCommand((GraphicArc) element, petriNet); + } + } + + @Override + public void execute() { + if (this.deleteElement != null) { + this.deleteElement.execute(); + } + } + + @Override + public void undo() { + if (this.deleteElement != null) { + this.deleteElement.undo(); + } + } + + @Override + public void redo() { + if (this.deleteElement != null) { + this.deleteElement.redo(); + } + } + + @Override + public String toString() { + return this.deleteElement.toString(); + } +} \ No newline at end of file diff --git a/pne-editor/src/org/pneditor/editor/commands/DeleteElementsCommand.java b/pne-editor/src/org/pneditor/editor/commands/DeleteElementsCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..092f783762e8aa2f8f826af16fd6b5152d4da401 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/DeleteElementsCommand.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.util.HashSet; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.Command; + +/** + * Delete clicked and selected elements + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DeleteElementsCommand implements Command { + + private Set<Command> deleteAllElements = new HashSet<>(); + + public DeleteElementsCommand(final Set<GraphicElement> elementsToDelete, final GraphicPetriNet petriNet) { + for (final GraphicElement element : elementsToDelete) { + this.deleteAllElements.add(new DeleteElementCommand(element, petriNet)); + } + } + + @Override + public void execute() { + for (final Command deleteElement : this.deleteAllElements) { + deleteElement.execute(); + } + } + + @Override + public void undo() { + for (final Command deleteElement : this.deleteAllElements) { + deleteElement.undo(); + } + } + + @Override + public void redo() { + for (final Command deleteElement : this.deleteAllElements) { + deleteElement.redo(); + } + } + + @Override + public String toString() { + if (this.deleteAllElements.size() == 1) { + return this.deleteAllElements.iterator().next().toString(); + } + return "Delete elements"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/DeletePlaceCommand.java b/pne-editor/src/org/pneditor/editor/commands/DeletePlaceCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..2df663de06f0f10d8bb71faf6b0481928f834d19 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/DeletePlaceCommand.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.util.HashSet; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DeletePlaceCommand implements Command { + + final private Set<Command> deleteAllArcEdges = new HashSet<>(); + final private GraphicPetriNet gPetriNet; + final private GraphicPlace gPlace; + final private Set<GraphicArc> connectedArcs; + + public DeletePlaceCommand(final GraphicPlace gPlace, final GraphicPetriNet gPetriNet) { + this.gPetriNet = gPetriNet; + this.gPlace = gPlace; + this.connectedArcs = gPetriNet.getConnectedGraphicArcs(gPlace); + for (final GraphicArc arc : this.connectedArcs) { + this.deleteAllArcEdges.add(new DeleteArcCommand(arc, gPetriNet)); + } + + } + + @Override + public void execute() { + for (final Command deleteArc : this.deleteAllArcEdges) { + deleteArc.execute(); + } + this.gPetriNet.removeElement(this.gPlace); + this.gPetriNet.getPetriNet().removeAbstractPlace(this.gPlace.getPlace()); + + } + + @Override + public void undo() { + final AbstractPlace place = this.gPetriNet.getPetriNet().addAbstractPlace(); + place.setLabel(this.gPlace.getLabel()); + place.setTokens(this.gPlace.getPlace().getTokens()); + this.deleteAllArcEdges.clear(); + this.gPetriNet.addElement(this.gPlace); + this.gPlace.setPlace(place); + for (final GraphicArc arc : this.connectedArcs) { + if (arc.getSource() == this.gPlace) { + this.deleteAllArcEdges.add(new AddArcCommand(this.gPetriNet, this.gPlace, arc.getDestination())); + } + else { + this.deleteAllArcEdges.add(new AddArcCommand(this.gPetriNet, arc.getSource(), this.gPlace)); + } + } + for (final Command addArc : this.deleteAllArcEdges) { + addArc.execute(); + } + } + + @Override + public void redo() { + for (final Command addArc : this.deleteAllArcEdges) { + addArc.undo(); + } + this.gPetriNet.removeElement(this.gPlace); + this.gPetriNet.getPetriNet().removeAbstractPlace(this.gPlace.getPlace()); + } + + @Override + public String toString() { + return "Delete place node"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/DeleteTransitionCommand.java b/pne-editor/src/org/pneditor/editor/commands/DeleteTransitionCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..0858599115600c320f4d15df2accbdefd6322547 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/DeleteTransitionCommand.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.util.HashSet; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DeleteTransitionCommand implements Command { + + final private GraphicTransition gTransition; + final private GraphicPetriNet gPetriNet; + final private Set<Command> deleteAllArcEdges = new HashSet<>(); + final private Set<GraphicArc> connectedArcs; + + public DeleteTransitionCommand(final GraphicTransition gTransition, final GraphicPetriNet gPetriNet) { + this.gTransition = gTransition; + this.gPetriNet = gPetriNet; + this.connectedArcs = gPetriNet.getConnectedGraphicArcs(gTransition); + for (final GraphicArc arc : this.connectedArcs) { + this.deleteAllArcEdges.add(new DeleteArcCommand(arc, gPetriNet)); + } + } + + @Override + public void execute() { + for (final Command deleteArc : this.deleteAllArcEdges) { + deleteArc.execute(); + } + this.gPetriNet.removeElement(this.gTransition); + this.gPetriNet.getPetriNet().removeAbstractTransition(this.gTransition.getTransition()); + } + + @Override + public void undo() { + final AbstractTransition transition = this.gPetriNet.getPetriNet().addAbstractTransition(); + transition.setLabel(this.gTransition.getLabel()); + this.deleteAllArcEdges.clear(); + this.gPetriNet.addElement(this.gTransition); + this.gTransition.setTransition(transition); + for (final GraphicArc arc : this.connectedArcs) { + if (arc.getSource() == this.gTransition) { + this.deleteAllArcEdges.add(new AddArcCommand(this.gPetriNet, this.gTransition, arc.getDestination())); + } + else { + this.deleteAllArcEdges.add(new AddArcCommand(this.gPetriNet, arc.getSource(), this.gTransition)); + } + } + for (final Command addArc : this.deleteAllArcEdges) { + addArc.execute(); + } + } + + @Override + public void redo() { + for (final Command addArc : this.deleteAllArcEdges) { + addArc.undo(); + } + this.gPetriNet.removeElement(this.gTransition); + this.gPetriNet.getPetriNet().removeAbstractTransition(this.gTransition.getTransition()); + } + + @Override + public String toString() { + return "Delete transition node"; + } +} diff --git a/pne-editor/src/org/pneditor/editor/commands/FireTransitionCommand.java b/pne-editor/src/org/pneditor/editor/commands/FireTransitionCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..6ea421ecabc0ae2ce0e96f233b0598fb4ee9a108 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/FireTransitionCommand.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class FireTransitionCommand implements Command { + + final private GraphicTransition transition; + final private GraphicPetriNet gPetriNet; + final private Map<GraphicPlace,Integer> firedPlaces = new HashMap<>(); + + public FireTransitionCommand(final GraphicTransition gTransition, final GraphicPetriNet gPetriNet) { + this.transition = gTransition; + this.gPetriNet = gPetriNet; + } + + @Override + public void execute() { //TODO: Temporary solution to remove the undoFire from the PetriNet + for (final GraphicPlace place : this.gPetriNet.getPlaces()) { + this.firedPlaces.put(place, place.getPlace().getTokens()); + } + try { + this.gPetriNet.getPetriNet().fire(this.transition.getTransition()); + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + + final Iterator<Entry<GraphicPlace, Integer>> iter = this.firedPlaces.entrySet().iterator(); //to avoid ConcurrentModificationExceptions + while (iter.hasNext()) { + final Map.Entry<GraphicPlace, Integer> pair = iter.next(); + if (pair.getKey().getPlace().getTokens() == pair.getValue()) { + iter.remove(); + } + } + } + + @Override + public void undo() { + for (final Map.Entry<GraphicPlace, Integer> entry : this.firedPlaces.entrySet()) { + entry.getKey().getPlace().setTokens(entry.getValue()); + } + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Fire transition"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/MoveElementCommand.java b/pne-editor/src/org/pneditor/editor/commands/MoveElementCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..fbe88c852cfa7e74697cac7db1edf303b384f305 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/MoveElementCommand.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.awt.Point; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class MoveElementCommand implements Command { + + private final GraphicElement element; + private final Point deltaPosition; + + public MoveElementCommand(final GraphicElement element, final Point deltaPosition) { + this.element = element; + this.deltaPosition = deltaPosition; + } + + @Override + public void execute() { + this.element.moveBy(this.deltaPosition.x, this.deltaPosition.y); + } + + @Override + public void undo() { + this.element.moveBy(-this.deltaPosition.x, -this.deltaPosition.y); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Move element"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/MoveElementsCommand.java b/pne-editor/src/org/pneditor/editor/commands/MoveElementsCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..5bdbe95c15b9cc9884e7003710e3bfff8cc10e59 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/MoveElementsCommand.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.awt.Point; +import java.util.HashSet; +import java.util.Set; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class MoveElementsCommand implements Command { + + private final Set<Command> moveElements = new HashSet<>(); + + public MoveElementsCommand(final Set<GraphicElement> elements, final Point deltaPosition) { + for (final GraphicElement element : elements) { + this.moveElements.add(new MoveElementCommand(element, deltaPosition)); + } + } + + @Override + public void execute() { + for (final Command moveElement : this.moveElements) { + moveElement.execute(); + } + } + + @Override + public void undo() { + for (final Command moveElement : this.moveElements) { + moveElement.undo(); + } + } + + @Override + public void redo() { + for (final Command moveElement : this.moveElements) { + moveElement.redo(); + } + } + + @Override + public String toString() { + if (this.moveElements.size() == 1) { + return this.moveElements.iterator().next().toString(); + } + return "Move elements"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/PasteCommand.java b/pne-editor/src/org/pneditor/editor/commands/PasteCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..841254136942f5d2a8bc58d148bbd7a6580e3d1b --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/PasteCommand.java @@ -0,0 +1,105 @@ +package org.pneditor.editor.commands; + +import java.awt.Point; +import java.awt.Rectangle; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.pneditor.editor.Root; +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PasteCommand implements Command { + + private final GraphicPetriNet gPetriNet; + private final Set<GraphicElement> elementsToCopy; + private Set<GraphicElement> elementsPasted; + private final Root root; + + public PasteCommand(final Set<GraphicElement> elementsToCopy, final GraphicPetriNet gPetriNet, final Root root) { + this.gPetriNet = gPetriNet; + this.elementsToCopy = elementsToCopy; + this.root = root; + } + + @Override + public void execute() { + this.elementsPasted = cloneElements(this.elementsToCopy); + this.gPetriNet.addAll(this.elementsPasted); + this.root.getSelection().addAll(this.elementsPasted); + final Point translation = calculateTranslationToCenter(this.elementsPasted, this.gPetriNet); + for (final GraphicElement element : this.elementsPasted) { + element.moveBy(translation.x, translation.y); + } + } + + @Override + public void undo() { + this.gPetriNet.removeAll(this.elementsPasted); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Paste"; + } + + private Point calculateTranslationToCenter(final Set<GraphicElement> elements, final GraphicPetriNet petriNet) { + final Point viewTranslation = petriNet.getViewTranslation(); + final GraphicPetriNet tempPetriNet = new GraphicPetriNet(this.root.getCurrentModel()); + tempPetriNet.addAll(elements); + final Rectangle bounds = tempPetriNet.getBounds(); + + final Point result = new Point(); + result.translate(Math.round(-(float) bounds.getCenterX()), Math.round(-(float) bounds.getCenterY())); + result.translate(-viewTranslation.x, -viewTranslation.y); + return result; + } + + + private Set<GraphicElement> cloneElements(final Set<GraphicElement> copiedElements) { + final PetriNetInterface petriNet = this.gPetriNet.getPetriNet(); + final Map<GraphicNode, GraphicNode> nodes = new HashMap<>(); + final Set<GraphicElement> pastedElements = new HashSet<>(); + + for (final GraphicElement element : copiedElements) { + if (element.isNode()) { + GraphicNode gNodeClone; + final GraphicNode gNode = (GraphicNode) element; + if (gNode.isPlace()) { + gNodeClone = ((GraphicPlace) gNode).getClone(petriNet.clonePlace(((GraphicPlace) gNode).getPlace())); + } else { + gNodeClone = ((GraphicTransition) gNode).getClone(petriNet.cloneTransition(((GraphicTransition) gNode).getTransition())); + } + pastedElements.add(gNodeClone); + nodes.put(gNode, gNodeClone); + } + } + for (final GraphicElement element : copiedElements) { + if (!element.isNode()) { + final GraphicArc gArc = (GraphicArc) element; + final GraphicNode source = nodes.get(gArc.getSource()); + final GraphicNode destination = nodes.get(gArc.getDestination()); + pastedElements.add(gArc.getClone(petriNet.cloneArc(gArc.getArc(), source.getNode(), destination.getNode()),source,destination)); + } + } + return pastedElements; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/RemoveTokenCommand.java b/pne-editor/src/org/pneditor/editor/commands/RemoveTokenCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..9b99cf21bee0a2ce2962d27fa6b6274524cd5b5e --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/RemoveTokenCommand.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class RemoveTokenCommand implements Command { + + final private GraphicPlace gPlace; + + public RemoveTokenCommand(final GraphicPlace gPlace) { + this.gPlace = gPlace; + } + + @Override + public void execute() { + this.gPlace.getPlace().removeToken(); + } + + @Override + public void undo() { + this.gPlace.getPlace().addToken(); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Remove token"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetArcInhibitCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetArcInhibitCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..ddcc518e33d7033f53d5faac7c2e08e138be6e7e --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetArcInhibitCommand.java @@ -0,0 +1,98 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.petrinet.UnimplementedCaseException; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +/** + * + * @author Amodez + */ +public class SetArcInhibitCommand implements Command { + + private final GraphicArc gArc; + private AbstractArc oldArc; + private AbstractArc newArc; + private final boolean isNotInhibitory; + private final GraphicPetriNet gPetriNet; + private PetriNetInterface petriNet; + + public SetArcInhibitCommand(final GraphicArc gArc, final GraphicPetriNet gPetriNet) { + this.gArc = gArc; + this.oldArc = gArc.getArc(); + this.gPetriNet = gPetriNet; + this.isNotInhibitory = !this.oldArc.isInhibitory(); + } + + @Override + public void execute() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotInhibitory) { + this.petriNet.removeAbstractArc(this.oldArc); + try { + if (this.oldArc.isReset()) { + this.newArc = this.petriNet.addInhibArc((AbstractPlace) this.oldArc.getSource(), + (AbstractTransition) this.oldArc.getDestination()); + } + if (this.oldArc.isRegular()) { + this.newArc = this.petriNet.addInhibArc((AbstractPlace) this.oldArc.getSource(), + (AbstractTransition) this.oldArc.getDestination()); + this.newArc.setMultiplicity(this.oldArc.getMultiplicity()); + } + } catch (ResetArcMultiplicityException e) { + // should not happen + PNEditorLogger.severeLogs(e.getMessage()); + } catch (UnimplementedCaseException e) { + // should not happen since we're manipulating new objects, except if a behavior + // is not implemented + PNEditorLogger.warningLogs(e.getMessage()); + } + this.gArc.setArc(this.newArc); + + } + + } + + @Override + public void undo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotInhibitory) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + oldArc = this.petriNet.addArcAgain(this.oldArc, source, destination); + this.gArc.setArc(this.oldArc); + } + } + + @Override + public void redo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotInhibitory) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + newArc = this.petriNet.addArcAgain(this.newArc, source, destination); + this.gArc.setArc(this.newArc); + } + } + + @Override + public String toString() { + return "Set arc type to inhibitor arc"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetArcMultiplicityCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetArcMultiplicityCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..3ec438596194b236ab6945158c01f8812e7e3c7a --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetArcMultiplicityCommand.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +/** + * Set multiplicity to clicked arc + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class SetArcMultiplicityCommand implements Command { + + private final GraphicArc gArc; + private final int newMultiplicity; + private int oldMultiplicity; + + public SetArcMultiplicityCommand(final GraphicArc gArc, final int newMultiplicity) { + this.gArc = gArc; + this.newMultiplicity = newMultiplicity; + } + + @Override + public void execute() { + try { + this.oldMultiplicity = this.gArc.getArc().getMultiplicity(); + this.gArc.getArc().setMultiplicity(this.newMultiplicity); + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + + @Override + public void undo() { + try { + this.gArc.getArc().setMultiplicity(this.oldMultiplicity); + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Set arc multiplicity"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetArcRegularCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetArcRegularCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..f1c1531a09d1447c1ec8feb9ed48dd7795cfd771 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetArcRegularCommand.java @@ -0,0 +1,86 @@ +package org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.petrinet.UnimplementedCaseException; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +public class SetArcRegularCommand implements Command { + + private final GraphicArc gArc; + private PetriNetInterface petriNet; + private AbstractArc oldArc; + private AbstractArc newArc; + private final boolean isNotRegular; + private final GraphicPetriNet gPetriNet; + + public SetArcRegularCommand(final GraphicArc gArc, final GraphicPetriNet gPetriNet) { + this.gArc = gArc; + this.gPetriNet = gPetriNet; + this.oldArc = gArc.getArc(); + this.isNotRegular = !this.oldArc.isRegular(); + } + + @Override + public void execute() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotRegular && this.oldArc.isSourceAPlace()) { + this.petriNet.removeAbstractArc(this.oldArc); + try { + if (this.oldArc.isReset()) { + this.newArc = this.petriNet.addRegArc(this.oldArc.getSource(), + this.oldArc.getDestination()); + } + if (this.oldArc.isInhibitory()) { + this.newArc = this.petriNet.addRegArc(this.oldArc.getSource(), + this.oldArc.getDestination()); + this.newArc.setMultiplicity(this.oldArc.getMultiplicity()); + } + } catch (ResetArcMultiplicityException e) { + // should not happen + PNEditorLogger.severeLogs(e.getMessage()); + } catch (UnimplementedCaseException e) { + // should not happen since we're manipulating new objects, except if a behavior + // is not implemented + PNEditorLogger.warningLogs(e.getMessage()); + } + this.gArc.setArc(this.newArc); + } + } + + @Override + public void undo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotRegular) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + oldArc = this.petriNet.addArcAgain(this.oldArc, source, destination); + this.gArc.setArc(this.oldArc); + } + } + + @Override + public void redo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotRegular) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + newArc = this.petriNet.addArcAgain(this.newArc, source, destination); + this.gArc.setArc(this.newArc); + } + } + + @Override + public String toString() { + return "Set arc type to reset arc"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetArcResetCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetArcResetCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..2894efe85e03a81c00b73eb3cfbe32a3b7e6ad85 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetArcResetCommand.java @@ -0,0 +1,81 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.UnimplementedCaseException; +import org.pneditor.util.Command; + +import logger.PNEditorLogger; + +/** + * + * @author jan.tancibok + */ +public class SetArcResetCommand implements Command { + + private final GraphicArc gArc; + private PetriNetInterface petriNet; + private AbstractArc oldArc; + private AbstractArc newArc; + private final boolean isNotReset; + private final GraphicPetriNet gPetriNet; + + + public SetArcResetCommand(final GraphicArc gArc, final GraphicPetriNet gPetriNet) { + this.gArc = gArc; + this.oldArc = gArc.getArc(); + this.gPetriNet = gPetriNet; + this.isNotReset = !this.oldArc.isReset(); + } + + @Override + public void execute() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotReset) { + this.petriNet.removeAbstractArc(this.oldArc); + try { + this.newArc = this.petriNet.addResArc((AbstractPlace) this.oldArc.getSource(), (AbstractTransition) this.oldArc.getDestination()); + } catch (UnimplementedCaseException e) { + PNEditorLogger.infoLogs(e.getMessage()); // should not happen + } + this.gArc.setArc(this.newArc); + } + } + + @Override + public void undo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotReset) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + oldArc = this.petriNet.addArcAgain(this.oldArc, source, destination); + this.gArc.setArc(this.oldArc); + } + } + + @Override + public void redo() { + this.petriNet = this.gPetriNet.getPetriNet(); + if (this.isNotReset) { + this.petriNet.removeAbstractArc(gArc.getArc()); + final AbstractNode source = gArc.getSource().getNode(); + final AbstractNode destination = gArc.getDestination().getNode(); + newArc = this.petriNet.addArcAgain(this.newArc, source, destination); + this.gArc.setArc(this.newArc); + } + } + @Override + public String toString() { + return "Set arc type to reset arc"; + } +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetEdgeZigzagPointCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetEdgeZigzagPointCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..bbaaceff9ace2b6d3d4260e3c99612337a15cd8c --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetEdgeZigzagPointCommand.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import java.awt.Point; +import java.util.List; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.util.Command; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class SetEdgeZigzagPointCommand implements Command { + + private final GraphicArc gArc; + private final Point startingLocation; + private final Point targetLocation; + private final List<Point> oldBreakPoints; + + public SetEdgeZigzagPointCommand(final GraphicArc gArc, final Point startingLocation, final Point targetLocation) { + this.gArc = gArc; + this.startingLocation = new Point(startingLocation); + this.targetLocation = new Point(targetLocation); + this.oldBreakPoints = this.gArc.getBreakPointsCopy(); + } + + @Override + public void execute() { + this.gArc.addOrGetBreakPoint(new Point(this.startingLocation)).setLocation(this.targetLocation); + this.gArc.cleanupUnecessaryBreakPoints(); + } + + @Override + public void undo() { + this.gArc.setBreakPoints(this.oldBreakPoints); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Set arc break point"; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetLabelCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetLabelCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..9e58c6a3fbf5f700773cdf007c61b75c38fd74d6 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetLabelCommand.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.util.Command; + +/** + * Set label to clicked element + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class SetLabelCommand implements Command { + + private AbstractNode node; + private String newLabel; + private String oldLabel; + private GraphicNode gNode; + + public SetLabelCommand(GraphicNode gNode, String newLabel) { + this.gNode = gNode; + this.newLabel = newLabel; + this.oldLabel = gNode.getLabel(); + } + + @Override + public void execute() { + this.node = this.gNode.getNode(); + this.node.setLabel(this.newLabel); + } + + @Override + public void undo() { + this.node = this.gNode.getNode(); + this.node.setLabel(this.oldLabel); + } + + @Override + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Set label to " + this.newLabel; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/commands/SetTokensCommand.java b/pne-editor/src/org/pneditor/editor/commands/SetTokensCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..f119038a74e305d3abe41a8f630d97442ac79ee7 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/commands/SetTokensCommand.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.commands; + +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.util.Command; + +/** + * Set tokens to clicked place node + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class SetTokensCommand implements Command { + + private final GraphicPlace gPlace; + + private final int newValue; + private final int oldValue; + + public SetTokensCommand(final GraphicPlace gPlace, final int tokens) { + this.gPlace = gPlace; + this.newValue = tokens; + this.oldValue = gPlace.getPlace().getTokens(); + } + + @Override + public void execute() { + this.gPlace.getPlace().setTokens(this.newValue); + } + + @Override + public void undo() { + this.gPlace.getPlace().setTokens(this.oldValue); + } + + @Override + public void redo() { + this.gPlace.getPlace().setTokens(this.newValue); + } + + @Override + public String toString() { + return "Set tokens"; + } +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/EpsFileType.java b/pne-editor/src/org/pneditor/editor/filechooser/EpsFileType.java new file mode 100644 index 0000000000000000000000000000000000000000..c2ac147c1a492304bcc434b958e35877a47bde1a --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/EpsFileType.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileNotFoundException; +import javax.swing.Icon; + +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.EPSGraphics2D; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class EpsFileType extends FileType { + + @Override + public String getExtension() { + return "eps"; + } + + @Override + public String getName() { + return "Encapsulated PostScript"; + } + + @Override + public Icon getIcon() { + return GraphicsTools.getIcon(PNEConstantsConfiguration.EPS); + } + + @Override + public GraphicPetriNet load(File file, String model) throws FileTypeException { + throw new UnsupportedOperationException("Loading not supported."); + } + + @Override + public BufferedImage getPreview(final File file) { + return null; + } + + @Override + public void save(final GraphicPetriNet petriNet, final File file) throws FileTypeException { + try { + final EPSGraphics2D epsGraphics2d = new EPSGraphics2D(); + for (final GraphicElement element : petriNet.getElements()) { + element.draw(epsGraphics2d, petriNet.getPetriNet()); + + } + epsGraphics2d.writeToFile(file); + } catch (FileNotFoundException ex) { + throw new FileTypeException(ex.getMessage()); + } + } + + +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/FileChooserDialog.java b/pne-editor/src/org/pneditor/editor/filechooser/FileChooserDialog.java new file mode 100644 index 0000000000000000000000000000000000000000..07c8a9d26011ad1670d432fee8e072c60111382d --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/FileChooserDialog.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.io.File; +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class FileChooserDialog extends JFileChooser { + + private final Sidebar sidebar = new Sidebar(this); + + public FileChooserDialog() { + super(); + setFileView(new FileIconView()); + setAccessory(this.sidebar); + } + + @Override + public File getSelectedFile() { + final File file = super.getSelectedFile(); + if (file == null) { + return null; + } else if (file.exists() && getFileFilter().getDescription().equals("All Files")) { + return file; + } else if (getFileFilter().accept(file)) { + return file; + } else { + return new File(file.getAbsolutePath() + "." + ((FileType) getFileFilter()).getExtension()); + } + } + + @Override + public void addChoosableFileFilter(final FileFilter filter) { + super.addChoosableFileFilter(filter); + if (getChoosableFileFilters().length > 1) { // first filter is always "All files" + setFileFilter(getChoosableFileFilters()[1]); + } + } + + public Sidebar getSidebar() { + return this.sidebar; + } +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/FileIconView.java b/pne-editor/src/org/pneditor/editor/filechooser/FileIconView.java new file mode 100644 index 0000000000000000000000000000000000000000..174670cc4d53abc10fa6aee7d5d01786f096a7c1 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/FileIconView.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.io.File; +import javax.swing.Icon; +import javax.swing.filechooser.FileView; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class FileIconView extends FileView { + + @Override + public Icon getIcon(final File file) { + if (file.isDirectory()) { + return super.getIcon(file); + } + final FileType fileType = FileType.getAcceptingFileType(file, FileType.getAllFileTypes()); + if (fileType != null) { + return fileType.getIcon(); + } + return super.getIcon(file); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/FileType.java b/pne-editor/src/org/pneditor/editor/filechooser/FileType.java new file mode 100644 index 0000000000000000000000000000000000000000..0b5b9065af8b880bb639c085ccc545efb73e99da --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/FileType.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import javax.swing.Icon; +import javax.swing.filechooser.FileFilter; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.StringTools; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class FileType extends FileFilter { + + public static Set<FileType> getAllFileTypes() { + final Set<FileType> allFileTypes = new HashSet<>(); + allFileTypes.add(new EpsFileType()); + allFileTypes.add(new PflowFileType()); + allFileTypes.add(new PngFileType()); + allFileTypes.add(new ViptoolPnmlFileType()); + return allFileTypes; + } + + public abstract String getExtension(); + + public abstract String getName(); + + public abstract void save(GraphicPetriNet petriNet, File file) throws FileTypeException; + + public abstract GraphicPetriNet load(File file, String model) throws FileTypeException; + + public abstract Icon getIcon(); + + public BufferedImage getPreview(File file) { + try { + final GraphicPetriNet gPetriNet = load(file, null); //TODO: may need to add the model for the load if models are different + return gPetriNet.getPreview(); + } catch (FileTypeException ex) { + return null; + } + } + + @Override + public String getDescription() { + return getName() + " (*." + getExtension() + ")"; + } + + @Override + public boolean accept(final File file) { + if (file.isDirectory()) { //Show also directories in the filters + return true; + } + + final String extension = StringTools.getExtension(file); + return extension != null && extension.equals(getExtension()); + } + + public static FileType getAcceptingFileType(final File file, final Collection<FileType> fileTypes) { + for (final FileType fileType : fileTypes) { + if (fileType.accept(file)) { + return fileType; + } + } + return null; + } +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/FileTypeException.java b/pne-editor/src/org/pneditor/editor/filechooser/FileTypeException.java new file mode 100644 index 0000000000000000000000000000000000000000..6f875083b389697b96d6eef2bd695d3aae481cc0 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/FileTypeException.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class FileTypeException extends Exception { + + public FileTypeException(final String message) { + super(message); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/PflowFileType.java b/pne-editor/src/org/pneditor/editor/filechooser/PflowFileType.java new file mode 100644 index 0000000000000000000000000000000000000000..d48edeae8d974502269181a2c4e79f425211542c --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/PflowFileType.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.io.File; +import java.io.IOException; +import javax.swing.Icon; +import javax.xml.bind.JAXBException; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.save.xml.DocumentExporter; +import org.pneditor.save.xml.DocumentImporter; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PflowFileType extends FileType { + + @Override + public String getName() { + return "PetriFlow"; + } + + @Override + public String getExtension() { + return "pflow"; + } + + @Override + public Icon getIcon() { + return GraphicsTools.getIcon(PNEConstantsConfiguration.PFLOW); + } + + + @Override + public void save(final GraphicPetriNet petriNet, final File file) throws FileTypeException { + try { + new DocumentExporter(petriNet).writeToFile(file); + } catch (JAXBException ex) { + if (!file.exists()) { + throw new FileTypeException("File not found."); + } else if (file.canRead()) { + throw new FileTypeException("Selected file is not compatible."); + } else { + throw new FileTypeException("File can not be read."); + } + } + } + + @Override + public GraphicPetriNet load(final File file, final String model) throws FileTypeException { + try { + final GraphicPetriNet petriNet = new DocumentImporter().readFromFile(file, model); + petriNet.setViewTranslationToCenter(); + return petriNet; + } catch (JAXBException ex) { + if (!file.exists()) { + throw new FileTypeException("File not found."); + } else if (file.canRead()) { + throw new FileTypeException("Selected file is not compatible."); + } else { + throw new FileTypeException("File can not be read."); + } + } catch (IOException ex) { + throw new FileTypeException(ex.getMessage()); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/PngFileType.java b/pne-editor/src/org/pneditor/editor/filechooser/PngFileType.java new file mode 100644 index 0000000000000000000000000000000000000000..eef2190c8bd2922f6ff4df76281d3889ce7eced3 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/PngFileType.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import javax.imageio.ImageIO; +import javax.swing.Icon; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PngFileType extends FileType { + + @Override + public String getExtension() { + return "png"; + } + + @Override + public String getName() { + return "Portable Network Graphics"; + } + + @Override + public Icon getIcon() { + return GraphicsTools.getIcon(PNEConstantsConfiguration.PNG); + } + + @Override + public GraphicPetriNet load(final File file, final String model) throws FileTypeException { + throw new UnsupportedOperationException("Loading not supported."); + } + + @Override + public BufferedImage getPreview(final File file) { + BufferedImage image = null; + try { + image = ImageIO.read(file); + } catch (IOException ex) { + } + return image; + } + + @Override + public void save(final GraphicPetriNet petriNet, final File file) throws FileTypeException { + try { + final BufferedImage bufferedImage = petriNet.getPreview(); + ImageIO.write(bufferedImage, "png", file); + } catch (IOException ex) { + throw new FileTypeException(ex.getMessage()); + } + } + +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/Preview.java b/pne-editor/src/org/pneditor/editor/filechooser/Preview.java new file mode 100644 index 0000000000000000000000000000000000000000..427664bb4a5472aa7925f98046640096c57f51d2 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/Preview.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.SystemColor; +import java.awt.image.BufferedImage; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import javax.swing.ImageIcon; +import javax.swing.JFileChooser; +import javax.swing.JPanel; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class Preview extends JPanel implements PropertyChangeListener { + + /** + * + */ + private static final long serialVersionUID = 6657841190121747227L; + private ImageIcon thumbnail; + private File file; + public static final int PREFERRED_WIDTH = 200; + public static final int PREFERRED_HEIGHT = 200; + + public Preview(final JFileChooser fileChooser) { + super(); + setPreferredSize(new Dimension(Preview.PREFERRED_WIDTH, Preview.PREFERRED_HEIGHT)); + fileChooser.addPropertyChangeListener(this); + } + + @Override + public void propertyChange(final PropertyChangeEvent e) { + final String propertyName = e.getPropertyName(); + boolean update = false; + + //If the directory changed, don't show an image. + if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(propertyName)) { + this.file = null; + update = true; + + //If a file became selected, find out which one. + } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(propertyName)) { + this.file = (File) e.getNewValue(); + update = true; + } + + //Update the preview accordingly. + if (update) { + this.thumbnail = null; + if (isShowing()) { + loadImage(); + repaint(); + } + } + } + + private void loadImage() { + if (this.file == null) { + this.thumbnail = null; + return; + } + final FileType fileType = FileType.getAcceptingFileType(this.file, FileType.getAllFileTypes()); + if (fileType == null) { + this.thumbnail = null; + return; + } + final BufferedImage image = fileType.getPreview(this.file); + if (image == null) { + this.thumbnail = null; + return; + } + if (image.getWidth() > image.getHeight()) { + this.thumbnail = new ImageIcon(image.getScaledInstance(Preview.PREFERRED_WIDTH, -1, Image.SCALE_SMOOTH), ""); + } else { + this.thumbnail = new ImageIcon(image.getScaledInstance(-1, Preview.PREFERRED_HEIGHT, Image.SCALE_SMOOTH), ""); + } + + } + + @Override + protected void paintComponent(final Graphics g) { + if (this.thumbnail == null) { + loadImage(); + setBackground(SystemColor.control); + super.paintComponent(g); + } else { + setBackground(Color.white); + super.paintComponent(g); + int x = getWidth() / 2 - this.thumbnail.getIconWidth() / 2; + int y = getHeight() / 2 - this.thumbnail.getIconHeight() / 2; + + if (y < 0) { + y = 0; + } + if (x < 0) { + x = 0; + } + this.thumbnail.paintIcon(this, g, x, y); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/Sidebar.java b/pne-editor/src/org/pneditor/editor/filechooser/Sidebar.java new file mode 100644 index 0000000000000000000000000000000000000000..e233d827d497d021bef5c43511c84c87336865de --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/Sidebar.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +@SuppressWarnings("serial") +public class Sidebar extends JPanel implements ActionListener, PropertyChangeListener { + + private final JFileChooser fileChooser; + private final JButton delete = new JButton("Delete file", GraphicsTools.getIcon(PNEConstantsConfiguration.DELETE16)); + + public Sidebar(final JFileChooser fileChooser) { + super(); + this.fileChooser = fileChooser; + final Preview preview = new Preview(fileChooser); + setLayout(new BorderLayout()); + add(preview, BorderLayout.CENTER); + add(this.delete, BorderLayout.NORTH); + this.delete.addActionListener(this); + fileChooser.addPropertyChangeListener(this); + } + + @Override + public void actionPerformed(final ActionEvent e) { + if (e.getSource() == this.delete) { + final File selectedFile = this.fileChooser.getSelectedFile(); + if (selectedFile != null && JOptionPane.showOptionDialog( + this.fileChooser, + "Delete " + selectedFile.getName() + "?\nThis action is irreversible!", + "Delete", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, + new String[]{"Delete permanently", "Cancel"}, + "Cancel") == JOptionPane.YES_OPTION) { + selectedFile.delete(); + this.fileChooser.setSelectedFile(new File("")); + this.fileChooser.rescanCurrentDirectory(); + } + } + } + + @Override + public void propertyChange(final PropertyChangeEvent evt) { + this.delete.setEnabled(this.fileChooser.getSelectedFile() != null); + } + +} diff --git a/pne-editor/src/org/pneditor/editor/filechooser/ViptoolPnmlFileType.java b/pne-editor/src/org/pneditor/editor/filechooser/ViptoolPnmlFileType.java new file mode 100644 index 0000000000000000000000000000000000000000..764ffa2eb875ecca72184ab27f73d6ff25486eca --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/filechooser/ViptoolPnmlFileType.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.filechooser; + +import java.io.File; +import java.io.IOException; +import javax.swing.Icon; +import javax.xml.bind.JAXBException; + +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.save.xml.DocumentExporter; +import org.pneditor.save.xml.DocumentImporter; +import org.pneditor.util.GraphicsTools; +import org.pneditor.PNEConstantsConfiguration; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class ViptoolPnmlFileType extends FileType { + + @Override + public String getName() { + return "PNML Viptool dialect"; + } + + @Override + public String getExtension() { + return "pnml"; + } + + @Override + public Icon getIcon() { + return GraphicsTools.getIcon(PNEConstantsConfiguration.PNML); + } + + + @Override + public void save(final GraphicPetriNet petriNet, final File file) throws FileTypeException { + try { + new DocumentExporter(petriNet).writeToFile(file); + } catch (JAXBException ex) { + if (!file.exists()) { + throw new FileTypeException("File not found."); + } else if (file.canRead()) { + throw new FileTypeException("Selected file is not compatible."); + } else { + throw new FileTypeException("File can not be read."); + } + } + } + + @Override + public GraphicPetriNet load(final File file, final String model) throws FileTypeException { + try { + final GraphicPetriNet petriNet = new DocumentImporter().readFromFile(file, model); + petriNet.setViewTranslationToCenter(); + return petriNet; + } catch (JAXBException ex) { + if (!file.exists()) { + throw new FileTypeException("File not found."); + } else if (file.canRead()) { + throw new FileTypeException("Selected file is not compatible."); + } else { + throw new FileTypeException("File can not be read."); + } + } catch (IOException ex) { + throw new FileTypeException(ex.getMessage()); + } + } +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicArc.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicArc.java new file mode 100644 index 0000000000000000000000000000000000000000..bfa17fe48a35427017ff17d54048c945aedb086f --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicArc.java @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.util.GraphicsTools; +import org.pneditor.util.GraphicsTools.HorizontalAlignment; +import org.pneditor.util.GraphicsTools.VerticalAlignment; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class GraphicArc extends GraphicElement { + + private AbstractArc arc; + private final List<Point> breakPoints = new LinkedList<>(); + private GraphicNode destination; + private GraphicNode source; + + public GraphicArc() { + super(); + } + + public GraphicArc(final AbstractArc arc) { + super(); + this.arc = arc; + } + + public GraphicArc getClone(final AbstractArc arcToClone, final GraphicNode newSource, final GraphicNode newDestination) { + final GraphicArc gArcClone = new GraphicArc(arcToClone); + gArcClone.source = newSource; + gArcClone.destination = newDestination; + return gArcClone; + } + + public AbstractArc getArc() { + return this.arc; + } + + @Override + public boolean isNode() { + return false; + } + + public List<Point> getBreakPoints() { + return Collections.unmodifiableList(this.breakPoints); + } + + public List<Point> getBreakPointsCopy() { + final List<Point> newBreakPoints = new LinkedList<>(); + for (final Point breakPoint : this.breakPoints) { + newBreakPoints.add(breakPoint.getLocation()); // getLocation because Point is mutable + } + return newBreakPoints; + } + + public void setBreakPoints(final List<Point> breakPoints) { + this.breakPoints.clear(); + for (final Point breakPoint : breakPoints) { + this.breakPoints.add(breakPoint.getLocation()); // getLocation because Point is mutable + } + } + + public void draw(final Graphics g) { + this.color = Color.BLACK; + g.setColor(this.color); + drawSegmentedLine(g); + final Point arrowTip = computeArrowTipPoint(); + if (this.arc.isReset()) { + drawArrowDouble(g, arrowTip); + } else { + try { + if (this.arc.getMultiplicity() >= 2) { + drawMultiplicityLabel(g, arrowTip, this.arc.getMultiplicity()); + } + } catch (ResetArcMultiplicityException e) { + // not happening + } + if (this.arc.isInhibitory()) { + drawCircle(g, arrowTip); + } else { + drawArrow(g, arrowTip); + } + } + + } + + @Override + public void draw(final Graphics g, final PetriNetInterface petriNet) { + draw(g); + } + + protected void drawArrow(final Graphics g, final Point arrowTip) { + final Point lastBreakPoint = getLastBreakPoint(); + GraphicsTools.drawArrow(g, lastBreakPoint.x, lastBreakPoint.y, arrowTip.x, arrowTip.y); + } + + protected void drawArrowDouble(final Graphics g, final Point arrowTip) { + final Point lastBreakPoint = getLastBreakPoint(); + /* + * int dx =lastBreakPoint.x - arrowTip.x; int dy =lastBreakPoint.y - arrowTip.y; + * int px = 8; int py = (int) ((dy/dx) * px); GraphicsTools.drawArrow(g, + * lastBreakPoint.x, lastBreakPoint.y, arrowTip.x, arrowTip.y); + */ + GraphicsTools.drawArrowDouble(g, lastBreakPoint.x, lastBreakPoint.y, arrowTip.x, arrowTip.y); + } + + protected void drawCircle(final Graphics g, final Point arrowTip) { + final Point lastBreakPoint = getLastBreakPoint(); + GraphicsTools.drawCircle(g, lastBreakPoint.x, lastBreakPoint.y, arrowTip.x, arrowTip.y); + } + + protected void drawMultiplicityLabel(final Graphics g, final Point arrowTip, final int multiplicity) { + final Point labelPoint = getLabelPoint(arrowTip); + GraphicsTools.drawString(g, Integer.toString(multiplicity), labelPoint.x, labelPoint.y, + HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM); + } + + protected void drawSegmentedLine(final Graphics g) { + g.setColor(this.color); + Point previous = getStart(); + for (final Point breakPoint : getBreakPoints()) { + g.drawLine(previous.x, previous.y, breakPoint.x, breakPoint.y); + previous = breakPoint; + } + g.drawLine(previous.x, previous.y, getEnd().x, getEnd().y); + } + + protected final Point computeArrowTipPoint() { + Point arrowTip = new Point(getEnd()); + if (getDestination() != null) { // Thanks to http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html + int x0 = getLastBreakPoint().x; + int y0 = getLastBreakPoint().y; + final int x1 = getEnd().x; + final int y1 = getEnd().y; + + int dy = y1 - y0; + int dx = x1 - x0; + int stepx, stepy; + + if (dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + if (dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + dy <<= 1; + dx <<= 1; + + if (dx > dy) { + int fraction = dy - (dx >> 1); + while (x0 != x1) { + if (fraction >= 0) { + y0 += stepy; + fraction -= dx; + } + x0 += stepx; + fraction += dy; + if (getDestination().containsPoint(x0, y0)) { + return arrowTip; + } + arrowTip = new Point(x0, y0); + } + } else { + int fraction = dx - (dy >> 1); + while (y0 != y1) { + if (fraction >= 0) { + x0 += stepx; + fraction -= dy; + } + y0 += stepy; + fraction += dx; + if (getDestination().containsPoint(x0, y0)) { + return arrowTip; + } + arrowTip = new Point(x0, y0); + } + } + } + return arrowTip; + } + + protected Point getLastBreakPoint() { + Point last = getStart(); + for (final Point breakPoint : this.breakPoints) { + last = breakPoint; + } + return last; + } + + protected Point getLabelPoint(final Point arrowTip) { + final Point labelPoint = new Point(); + if (this.breakPoints.isEmpty()) { + labelPoint.x = getStart().x + (arrowTip.x - getStart().x) * 2 / 3; + labelPoint.y = getStart().y + (arrowTip.y - getStart().y) * 2 / 3 - 3; + } else { + final Point lastBreakPoint = this.breakPoints.get(this.breakPoints.size() - 1); + labelPoint.x = lastBreakPoint.x + (arrowTip.x - lastBreakPoint.x) * 1 / 2; + labelPoint.y = lastBreakPoint.y + (arrowTip.y - lastBreakPoint.y) * 1 / 2 - 3; + } + return labelPoint; + } + + public GraphicNode getDestination() { + return this.destination; + } + + public void setDestination(final GraphicNode destination) { + this.destination = destination; + } + + public GraphicNode getSource() { + return this.source; + } + + public void setSource(final GraphicNode source) { + this.source = source; + } + + public static final int NEARTOLERANCE = 10; + + @Override + public boolean containsPoint(final int x, final int y) { + final Point testPos = new Point(x, y); + Point previous = getStart(); + for (final Point breakPoint : this.breakPoints) { + if (GraphicsTools.isPointNearSegment(previous, breakPoint, testPos, NEARTOLERANCE)) { + return true; + } + previous = breakPoint; + } + return GraphicsTools.isPointNearSegment(previous, getEnd(), testPos, NEARTOLERANCE); + } + + public Point addOrGetBreakPoint(final Point newPoint) { + for (final Point breakPoint : this.breakPoints) { + if (GraphicsTools.isPointNearPoint(newPoint, breakPoint, NEARTOLERANCE)) { + return breakPoint; + } + } + + if (this.breakPoints.isEmpty()) { + this.breakPoints.add(newPoint); + } else { + Point previous = getStart(); + for (int i = 0; i < this.breakPoints.size(); i++) { + if (GraphicsTools.isPointNearSegment(previous, this.breakPoints.get(i), newPoint, NEARTOLERANCE)) { + this.breakPoints.add(i, newPoint); + return newPoint; + } + previous = this.breakPoints.get(i); + } + if (GraphicsTools.isPointNearSegment(previous, getEnd(), newPoint, NEARTOLERANCE)) { + this.breakPoints.add(newPoint); + } + } + return newPoint; + } + + public void addDistantBreakPointToEnd(final Point newPoint) { + this.breakPoints.add(newPoint); + } + + public void addDistantBreakPointToBeginning(final Point newPoint) { + this.breakPoints.add(0, newPoint); + } + + public void cleanupUnecessaryBreakPoints() { + Point previous = getStart(); + for (int i = 0; i < this.breakPoints.size(); i++) { + final Point current = this.breakPoints.get(i); + final Point next = i < (this.breakPoints.size() - 1) ? this.breakPoints.get(i + 1) : getEnd(); + final int tolerance = Math.round(0.1f * (float) previous.distance(next)); + if (GraphicsTools.isPointNearSegment(previous, next, current, tolerance)) { + this.breakPoints.remove(i--); + } else { + previous = this.breakPoints.get(i); + } + } + } + + @Override + public Point getStart() { + return getSource() == null ? super.getStart() : getSource().getCenter(); + } + + @Override + public Point getEnd() { + return getDestination() == null ? super.getEnd() : getDestination().getCenter(); + } + + @Override + public boolean isPlace() { + return false; + } + + @Override + public boolean isTransition() { + return false; + } + + public void setArc(final AbstractArc arc) { + this.arc = arc; + } + +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicElement.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicElement.java new file mode 100644 index 0000000000000000000000000000000000000000..bb7f85e35ae3a72bb74eb26fbdee3747dc625f95 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicElement.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.*; + +import org.pneditor.petrinet.PetriNetInterface; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class GraphicElement { + + private Point start = new Point(); + private Point end = new Point(); + private Point center = new Point(); + + protected Color color = Color.black; + protected Color highlightColor; + + + public Point getStart() { + if (this.start == null) { + this.start = new Point(); + } + return this.start; + } + + public Point getEnd() { + if (this.end == null) { + this.end = new Point(); + } + return this.end; + } + + public void setStart(final int x, final int y) { + if (this.start == null) { + this.start = new Point(); + } + this.start.x = x; + this.start.y = y; + } + + public void setEnd(final int x, final int y) { + if (this.end == null) { + this.end = new Point(); + } + this.end.x = x; + this.end.y = y; + } + + public int getWidth() { + return Math.abs(getEnd().x - getStart().x); + } + + public int getHeight() { + return Math.abs(getEnd().y - getStart().y); + } + + private int getCenterX() { + return getStart().x + (getEnd().x - getStart().x) / 2; + } + + private int getCenterY() { + return getStart().y + (getEnd().y - getStart().y) / 2; + } + + public Point getCenter() { + if (this.center == null) { + this.center = new Point(); + } + if (this.center.x != getCenterX()) { + this.center.x = getCenterX(); + } + if (this.center.y != getCenterY()) { + this.center.y = getCenterY(); + } + return this.center; + } + + public void setCenter(final int x, final int y) { + moveBy(x - getCenter().x, y - getCenter().y); + } + + public void setCenter(final Point center) { + setCenter(center.x, center.y); + } + + public void setSize(final int width, final int height) { + final Point prevCenter = getCenter(); + setEnd(getStart().x + width, getStart().y + height); + setCenter(prevCenter.x, prevCenter.y); + } + + public void moveBy(final int dx, final int dy) { + setStart(getStart().x + dx, getStart().y + dy); + setEnd(getEnd().x + dx, getEnd().y + dy); + } + + public void setColor(final Color color) { + this.color = color; + } + + public Color getColor() { + return this.color; + } + + public void setHighlightColor(final Color color) { + this.highlightColor = color; + } + + public Color getHighlightColor() { + return highlightColor; + } + + public boolean containsPoint(final int x, final int y) { + final int l = Math.min(getStart().x, getEnd().x); + final int t = Math.min(getStart().y, getEnd().y); + final int w = Math.abs(getWidth()); + final int h = Math.abs(getHeight()); + return x >= l && x < l + w && y >= t && y < t + h; + + } + + public abstract void draw(Graphics g, PetriNetInterface petriNet); + + public abstract boolean isNode(); + + public abstract boolean isPlace(); + + public abstract boolean isTransition(); + +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicNode.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicNode.java new file mode 100644 index 0000000000000000000000000000000000000000..1651ced9bb685688a2157cdbf1357a1157a095d3 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicNode.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.Graphics; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.util.GraphicsTools; +import org.pneditor.util.GraphicsTools.HorizontalAlignment; +import org.pneditor.util.GraphicsTools.VerticalAlignment; + +/** + * Transition, Place, ReferencePlace, Subnet are subclasses of Node + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class GraphicNode extends GraphicElement { + + + public GraphicNode() { + super(); + setSize(32, 32); + } + + protected void drawLabel(final Graphics g) { + if (getLabel() != null && !getLabel().equals("")) { + GraphicsTools.drawString(g, getLabel(), getCenter().x, getEnd().y, + HorizontalAlignment.CENTER, VerticalAlignment.TOP); + } + } + + public abstract String getLabel(); + + public abstract AbstractNode getNode(); + + @Override + public boolean isNode() { + return true; + } +} + diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPetriNet.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPetriNet.java new file mode 100644 index 0000000000000000000000000000000000000000..2ce44135ca7e915a602654331098385f5d34475b --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPetriNet.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import org.pneditor.util.CachedGraphics2D; + +import logger.PNEditorLogger; + +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.PetriNetInterface; + +/** + * PetriNet class stores reference to the root subnet and manages a view of + * currently opened subnet in form of a stack. Default view is only the root + * subnet opened. Opening and closing subnets does not influence anything other + * and serves only for informational purposes. + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class GraphicPetriNet { + + private final List<GraphicElement> elements = new LinkedList<>(); + private Point viewTranslation = new Point(0, 0); + private PetriNetInterface petriNet; + private final String modelPath = "org.pneditor.petrinet.adapters."; + private String model = "initial"; + private final String modelAdapterPath = ".PetriNetAdapter"; + + /** + * Constructor. Creates a new Petri net with empty root subnet. + */ + public GraphicPetriNet() { + try { + this.petriNet = (PetriNetInterface) Class.forName(this.modelPath + this.model + this.modelAdapterPath) + .newInstance(); + } catch (InstantiationException e) { + PNEditorLogger.severeLogs("Cannot instantiate this class"); + } catch (IllegalAccessException e) { + PNEditorLogger.severeLogs("Cannot access this class"); + } catch (ClassNotFoundException e) { + PNEditorLogger.severeLogs("Cannot find this class"); + } + } + + public GraphicPetriNet(final String model) { + if (model != null) { + this.model = model; + } + try { + this.petriNet = (PetriNetInterface) Class.forName(this.modelPath + this.model + this.modelAdapterPath) + .newInstance(); + } catch (InstantiationException e) { + PNEditorLogger.severeLogs("Cannot instantiate this class"); + } catch (IllegalAccessException e) { + PNEditorLogger.severeLogs("Cannot access this class"); + } catch (ClassNotFoundException e) { + PNEditorLogger.severeLogs("Cannot find this class"); + } + } + + public Point getViewTranslation() { + return new Point(this.viewTranslation); + } + + public void setViewTranslation(final Point viewTranslation) { + this.viewTranslation = new Point(viewTranslation); + } + + public void setViewTranslationToCenter() { + final int centerX = Math.round((float) getBounds().getCenterX()); + final int centerY = Math.round((float) getBounds().getCenterY()); + final Point center = new Point(-centerX, -centerY); + setViewTranslation(center); + } + + public List<GraphicElement> getElements() { + return Collections.unmodifiableList(this.elements); + } + + public GraphicElement getElementByXY(final int x, final int y) { + for (int i = this.elements.size() - 1; i >= 0; i--) { // Check elements from front to back. + final GraphicElement element = this.elements.get(i); + if (element.containsPoint(x, y)) { + return element; + } + } + return null; + } + + public void addElement(final GraphicElement element) { + if (!element.isNode()) { + this.elements.add(0, element); // background + } else { + this.elements.add(element); + } + } + + public void removeElement(final GraphicElement element) { + this.elements.remove(element); + } + + public void removeElements() { + this.elements.clear(); + } + + public void addAll(final Set<GraphicElement> elementsToAdd) { + for (final GraphicElement element : elementsToAdd) { + addElement(element); + } + } + + public void removeAll(final Set<GraphicElement> elementsToRemove) { + for (final GraphicElement element : elementsToRemove) { + removeElement(element); + } + } + + public Set<GraphicArc> getArcs() { + final Set<GraphicArc> arcs = new HashSet<>(); + for (final GraphicElement element : this.elements) { + if (!element.isNode()) { + final GraphicArc arc = (GraphicArc) element; + arcs.add(arc); + } + } + return arcs; + } + + public Set<GraphicPlace> getPlaces() { + final Set<GraphicPlace> places = new HashSet<>(); + for (final GraphicElement element : this.elements) { + if (element.isPlace()) { + final GraphicPlace place = (GraphicPlace) element; + places.add(place); + } + } + return places; + } + + public Rectangle getBounds() { + Rectangle bounds = null; + + for (final GraphicElement element : this.elements) { + if (bounds == null) { + bounds = new Rectangle(element.getStart().x, element.getStart().y, element.getWidth(), + element.getHeight()); + } + bounds.add(element.getStart().x, element.getStart().y); + bounds.add(element.getEnd().x, element.getEnd().y); + bounds.add(element.getStart().x, element.getEnd().y); + bounds.add(element.getEnd().x, element.getStart().y); + if (!element.isNode()) { + final GraphicArc arc = (GraphicArc) element; + for (final Point breakPoint : arc.getBreakPoints()) { + bounds.add(breakPoint); + } + } + } + if (bounds == null) { + bounds = new Rectangle(); + } + bounds.width++; + bounds.height++; + return bounds; + } + + public void draw(final Graphics g) { + + for (final GraphicElement element : this.elements) { + if (element.highlightColor != null) { + final Color previousColor = element.getColor(); + + element.setColor(element.highlightColor); + element.draw(g, this.petriNet); // TODO + + element.setColor(previousColor); + } else { + element.draw(g, this.petriNet); // TODO + } + } + } + + public PetriNetInterface getPetriNet() { + return this.petriNet; + } + + public void setPetriNet(final PetriNetInterface petriNet) { + this.petriNet = petriNet; + } + + public Set<GraphicArc> getConnectedGraphicArcs(final GraphicNode node) { + final Set<GraphicArc> graphicArcs = new HashSet<>(); + for (final GraphicElement element : this.elements) { + if (!element.isNode()) { + final AbstractArc arc = ((GraphicArc) element).getArc(); + if (arc.getSource().equals(node.getNode()) || arc.getDestination().equals(node.getNode())) { + graphicArcs.add((GraphicArc) element); + } + } + } + return graphicArcs; + } + + /** + * Returns an preview image of the subnet with specified marking. Scale image: + * image.getScaledInstance(preferredWidth, preferredHeight, Image.SCALE_SMOOTH) + * Save image: ImageIO.write(image, "png", file); + */ + + public BufferedImage getPreview() { + final CachedGraphics2D cachedGraphics = new CachedGraphics2D(); + cachedGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + for (final GraphicElement element : getElements()) { + element.draw(cachedGraphics, getPetriNet()); + } + final Rectangle bounds = cachedGraphics.getIntegerBounds(); + int width = bounds.width; + int height = bounds.height; + width = Math.max(width, 1); + height = Math.max(height, 1); + final BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + final Graphics2D imageGraphics = (Graphics2D) bufferedImage.getGraphics(); + imageGraphics.fillRect(0, 0, width, height); // paint the background white + imageGraphics.translate(-bounds.x, -bounds.y); + cachedGraphics.applyToGraphics(imageGraphics); + return bufferedImage; + } + + public GraphicElement getLastElementAdded() { + return ((LinkedList<GraphicElement>) this.elements).getLast(); + } + + public GraphicElement getLastArcAdded() { + return ((LinkedList<GraphicElement>) this.elements).getFirst(); + } +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPlace.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPlace.java new file mode 100644 index 0000000000000000000000000000000000000000..f29959bf78e81f55a434ea78d177d3fcf73d6823 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicPlace.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.*; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.util.GraphicsTools; +import org.pneditor.util.GraphicsTools.HorizontalAlignment; +import org.pneditor.util.GraphicsTools.VerticalAlignment; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class GraphicPlace extends GraphicNode { + + AbstractPlace place; + + public GraphicPlace(final AbstractPlace place, final int x, final int y) { + super(); + this.place = place; + setCenter(x,y); + } + + public GraphicPlace() { + super(); + } + + @Override + public boolean containsPoint(final int x, final int y) { + // Check whether (x,y) is inside this oval, using the + // mathematical equation of an ellipse. + final double rx = getWidth() / 2.0; // horizontal radius of ellipse + final double ry = getHeight() / 2.0; // vertical radius of ellipse + final double cx = getStart().x + rx; // x-coord of center of ellipse + final double cy = getStart().y + ry; // y-coord of center of ellipse + return (ry * (x - cx)) * (ry * (x - cx)) + (rx * (y - cy)) * (rx * (y - cy)) <= rx * rx * ry * ry; + } + + + public AbstractPlace getPlace() { + return this.place; + } + + @Override + public AbstractNode getNode() { + return this.place; + } + + @Override + public void draw(final Graphics g, final PetriNetInterface petriNet) { + drawPlaceBackground(g); + drawPlaceBorder(g); + drawLabel(g); + drawTokens(g, this.place.getTokens()); + } + + protected void drawPlaceBackground(final Graphics g) { + g.setColor(Color.white); + g.fillOval(getStart().x, getStart().y, getWidth(), getHeight()); + } + + protected void drawPlaceBorder(final Graphics g) { + g.setColor(this.color); + g.drawOval(getStart().x, getStart().y, getWidth() - 1, getHeight() - 1); + } + + protected void drawTokens(final Graphics g, final int tokens) { + g.setColor(this.color); + final int x = getCenter().x; + final int y = getCenter().y; + final int tokenSpacing = getWidth() / 5; + + if (tokens > 9) { + GraphicsTools.drawString(g, Integer.toString(tokens), x, y, HorizontalAlignment.CENTER, + VerticalAlignment.CENTER); + } else { + + if (tokens % 2 == 1) { + drawTokenAsDot(g, x, y); + if (tokens > 2) { + drawTokenAsDot(g, x - tokenSpacing, y + tokenSpacing); + drawTokenAsDot(g, x + tokenSpacing, y - tokenSpacing); + } + if (tokens > 4) { + drawTokenAsDot(g, x - tokenSpacing, y - tokenSpacing); + drawTokenAsDot(g, x + tokenSpacing, y + tokenSpacing); + } + if (tokens > 6) { + drawTokenAsDot(g, x - tokenSpacing, y); + drawTokenAsDot(g, x + tokenSpacing, y); + } + if (tokens > 8) { + drawTokenAsDot(g, x, y - tokenSpacing); + drawTokenAsDot(g, x, y + tokenSpacing); + } + + } else { + if (tokens > 1) { + drawTokenAsDot(g, x - tokenSpacing, y + tokenSpacing); + drawTokenAsDot(g, x + tokenSpacing, y - tokenSpacing); + } + if (tokens > 3) { + drawTokenAsDot(g, x - tokenSpacing, y - tokenSpacing); + drawTokenAsDot(g, x + tokenSpacing, y + tokenSpacing); + } + if (tokens > 5) { + drawTokenAsDot(g, x - tokenSpacing, y); + drawTokenAsDot(g, x + tokenSpacing, y); + } + if (tokens == 8) { + drawTokenAsDot(g, x, y - tokenSpacing); + drawTokenAsDot(g, x, y + tokenSpacing); + } + } + } + } + + private void drawTokenAsDot(final Graphics g, final int x, final int y) { + final int tokenSize = getWidth() / 6; + g.fillOval(x - tokenSize / 2, y - tokenSize / 2, tokenSize, tokenSize); + } + + @Override + public String getLabel() { + return this.place.getLabel(); + } + + @Override + public boolean isPlace() { + return true; + } + + public void setPlace(final AbstractPlace place) { + this.place = place; + } + + public GraphicPlace getClone(final AbstractPlace placeCloned) { + final GraphicPlace clone = new GraphicPlace(); + clone.setCenter(this.getCenter()); + clone.setPlace(placeCloned); + return clone; + } + + @Override + public boolean isTransition() { + return false; + } +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicTransition.java b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicTransition.java new file mode 100644 index 0000000000000000000000000000000000000000..ca3cce46fc7705e4350cefdb3d72c9a8e197a979 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/GraphicTransition.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.Color; +import java.awt.Graphics; + +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.petrinet.PetriNetInterface; +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class GraphicTransition extends GraphicNode { + + AbstractTransition transition; + + public GraphicTransition(final AbstractTransition transition , final int x, final int y){ + this.transition = transition; + setCenter(x,y); + } + + public GraphicTransition() { + // TODO Auto-generated constructor stub + } + + public AbstractTransition getTransition() { + return this.transition; + } + + @Override + public AbstractNode getNode() { + return this.transition; + } + + public void draw(final Graphics g) { + g.setColor(Color.white); + g.fillRect(getStart().x, getStart().y, getWidth(), getHeight()); + g.setColor(this.color); + g.drawRect(getStart().x, getStart().y, getWidth() - 1, getHeight() - 1); + drawLabel(g); + } + + @Override + public void draw(final Graphics g, final PetriNetInterface petriNet) { + draw(g); + } + + @Override + public String getLabel() { + return this.transition.getLabel(); + } + + @Override + public boolean isPlace() { + return false; + } + + public void setTransition(final AbstractTransition transition) { + this.transition = transition; + } + + public GraphicTransition getClone(final AbstractTransition transitionCloned) { + final GraphicTransition clone = new GraphicTransition(); + clone.setCenter(this.getCenter()); + clone.setTransition(transitionCloned); + return clone; + } + + @Override + public boolean isTransition() { + return true; + } +} diff --git a/pne-editor/src/org/pneditor/editor/gpetrinet/PreviewArc.java b/pne-editor/src/org/pneditor/editor/gpetrinet/PreviewArc.java new file mode 100644 index 0000000000000000000000000000000000000000..f377a5d814095b5699631a844870d9ebdc04f088 --- /dev/null +++ b/pne-editor/src/org/pneditor/editor/gpetrinet/PreviewArc.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.editor.gpetrinet; + +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Point; + +import org.pneditor.petrinet.PetriNetInterface; +import org.pneditor.util.GraphicsTools; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class PreviewArc extends GraphicElement { + + private GraphicNode destination; + private GraphicNode source; + + public PreviewArc(GraphicNode source) { + setSource(source); + setStart(source.getCenter().x, source.getCenter().y); + setEnd(source.getCenter().x, source.getCenter().y); + } + + @Override + public final boolean isNode() { + return false; + } + + public final void draw(Graphics g) { + this.color = Color.BLACK; + g.setColor(this.color); + drawSegmentedLine(g); + Point arrowTip = computeArrowTipPoint(); + drawArrow(g, arrowTip); + + } + + @Override + public final void draw(Graphics g, PetriNetInterface petriNet) { + draw(g); + } + + protected final void drawArrow(Graphics g, Point arrowTip) { + GraphicsTools.drawArrow(g, getStart().x, getStart().y, arrowTip.x, arrowTip.y); + } + + protected final void drawSegmentedLine(Graphics g) { + g.setColor(this.color); + Point previous = getStart(); + g.drawLine(previous.x, previous.y, getEnd().x, getEnd().y); + } + + protected final Point computeArrowTipPoint() { + Point arrowTip = new Point(getEnd()); + if (getDestination() != null) { // Thanks to http://www.cs.unc.edu/~mcmillan/comp136/Lecture6/Lines.html + int x0 = getStart().x; + int y0 = getStart().y; + int x1 = getEnd().x; + int y1 = getEnd().y; + + int dy = y1 - y0; + int dx = x1 - x0; + int stepx, stepy; + + if (dy < 0) { + dy = -dy; + stepy = -1; + } else { + stepy = 1; + } + if (dx < 0) { + dx = -dx; + stepx = -1; + } else { + stepx = 1; + } + dy <<= 1; + dx <<= 1; + + if (dx > dy) { + int fraction = dy - (dx >> 1); + while (x0 != x1) { + if (fraction >= 0) { + y0 += stepy; + fraction -= dx; + } + x0 += stepx; + fraction += dy; + if (getDestination().containsPoint(x0, y0)) { + return arrowTip; + } + arrowTip = new Point(x0, y0); + } + } else { + int fraction = dx - (dy >> 1); + while (y0 != y1) { + if (fraction >= 0) { + x0 += stepx; + fraction -= dy; + } + y0 += stepy; + fraction += dx; + if (getDestination().containsPoint(x0, y0)) { + return arrowTip; + } + arrowTip = new Point(x0, y0); + } + } + } + return arrowTip; + } + + public final GraphicNode getDestination() { + return this.destination; + } + + public final void setDestination(GraphicNode destination) { + this.destination = destination; + } + + public final GraphicNode getSource() { + return this.source; + } + + public final void setSource(GraphicNode source) { + this.source = source; + } + + @Override + public final Point getStart() { + return getSource() != null ? getSource().getCenter() : super.getStart(); + } + + @Override + public final Point getEnd() { + return getDestination() != null ? getDestination().getCenter() : super.getEnd(); + } + + @Override + public final boolean isPlace() { + return false; + } + + @Override + public final boolean isTransition() { + return false; + } + +} diff --git a/pne-editor/src/org/pneditor/petrinet/AbstractArc.java b/pne-editor/src/org/pneditor/petrinet/AbstractArc.java new file mode 100644 index 0000000000000000000000000000000000000000..551ae2ddca95f69878d966f8521e25e6f5ffb0e1 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/AbstractArc.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.petrinet; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class AbstractArc { + + public abstract AbstractNode getSource(); + + public abstract AbstractNode getDestination(); + + public boolean isSourceAPlace() { + return getSource().isPlace(); + } + + public abstract boolean isReset(); + + public abstract boolean isRegular(); + + public abstract boolean isInhibitory(); + + public abstract int getMultiplicity() throws ResetArcMultiplicityException; + + public abstract void setMultiplicity(int multiplicity) throws ResetArcMultiplicityException; + +} diff --git a/pne-editor/src/org/pneditor/petrinet/AbstractNode.java b/pne-editor/src/org/pneditor/petrinet/AbstractNode.java new file mode 100644 index 0000000000000000000000000000000000000000..d2f364c403d559825d848016a85e5c4004cc87b4 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/AbstractNode.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.petrinet; + +/** + * Transition, Place, ReferencePlace, Subnet are subclasses of Node + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class AbstractNode { + + private int id; + private String label; + + public AbstractNode(final String label) { + this.label = label; + } + + public final int getId() { + return this.id; + } + + protected final void setId(final int id) { + this.id = id; + } + + public String getLabel() { + return this.label; + } + + public void setLabel(final String label) { + this.label = label; + } + + public abstract boolean isPlace(); + +} diff --git a/pne-editor/src/org/pneditor/petrinet/AbstractPlace.java b/pne-editor/src/org/pneditor/petrinet/AbstractPlace.java new file mode 100644 index 0000000000000000000000000000000000000000..7ee36e7c5cdf70f7deef719c3a0d2e2ae30f396a --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/AbstractPlace.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.petrinet; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class AbstractPlace extends AbstractNode { + + public AbstractPlace(final String label) { + super(label); + } + + public abstract void addToken(); + + public abstract void removeToken(); + + public abstract int getTokens(); + + public abstract void setTokens(int tokens); + + @Override + public boolean isPlace() { + return true; + } + +} \ No newline at end of file diff --git a/pne-editor/src/org/pneditor/petrinet/AbstractTransition.java b/pne-editor/src/org/pneditor/petrinet/AbstractTransition.java new file mode 100644 index 0000000000000000000000000000000000000000..12f8e83fdb06d44242177692e748b7ad6327cfe0 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/AbstractTransition.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.petrinet; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public abstract class AbstractTransition extends AbstractNode { + + public AbstractTransition(final String label) { + super(label); + } + + @Override + public boolean isPlace() { + return false; + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/Boundedness.java b/pne-editor/src/org/pneditor/petrinet/Boundedness.java new file mode 100644 index 0000000000000000000000000000000000000000..b25135feea3fd4cca44370dae10cc1a15c135b82 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/Boundedness.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2012 milka + * + * 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 org.pneditor.petrinet; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * + * @author milka + */ +public class Boundedness { + + final private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); + final private PetriNetInterface petriNet; + private Stack<Map<AbstractPlace, Integer>> markingsStack; + private boolean isUnboundedness; + + public Boundedness(final PetriNetInterface petriNet) { + this.petriNet = petriNet; + } + + public boolean isBounded() throws ResetArcMultiplicityException { + + this.isUnboundedness = false; + + final Map<AbstractPlace, Integer> initMap = initFill(); + this.markingsStack = new Stack<>(); + this.markingsStack.push(initMap); + + final Set<AbstractTransition> executableTransitions = getAllEnabledTransitions(initMap); + for (final AbstractTransition t : executableTransitions) { + if (checkBranchBoundedness(initMap, t)) { + this.markingsStack.pop(); + } + } + return this.isUnboundedness; + } + + private boolean checkBranchBoundedness(final Map<AbstractPlace, Integer> marking, + final AbstractTransition transition) throws ResetArcMultiplicityException { + + if (this.isUnboundedness) { + return false; + } + + final Map<AbstractPlace, Integer> newMarking = new ConcurrentHashMap<>(marking); + fire(newMarking, transition); + + for (final Map<AbstractPlace, Integer> oldMarking : this.markingsStack) { + if (isOmega(newMarking, oldMarking)) { + this.isUnboundedness = true; + return false; + } + } + + if (!this.markingsStack.contains(newMarking)) { + this.markingsStack.push(newMarking); + final Set<AbstractTransition> executableTransitions = getAllEnabledTransitions(newMarking); + for (final AbstractTransition t : executableTransitions) { + if (checkBranchBoundedness(newMarking, t)) { + this.markingsStack.pop(); + } + } + return true; + } + + return false; + + } + + private boolean isOmega(final Map<AbstractPlace, Integer> newMarking, + final Map<AbstractPlace, Integer> oldMarking) { + + boolean isOneSharplyHigher = false; + + for (final AbstractPlace newMarkingAbstractPlace : newMarking.keySet()) { + + final int newTokens = newMarking.get(newMarkingAbstractPlace); + + AbstractPlace oldMarkingAbstractPlace = null; + for (final AbstractPlace place : oldMarking.keySet()) { + if (place.equals(newMarkingAbstractPlace)) { + oldMarkingAbstractPlace = place; + break; + } + } + + final int oldTokens = oldMarking.get(oldMarkingAbstractPlace); + + if (newTokens < oldTokens) { + return false; + } else if (newTokens > oldTokens) { + isOneSharplyHigher = true; + } + + } + return isOneSharplyHigher; + } + + private Map<AbstractPlace, Integer> initFill() { + final Map<AbstractPlace, Integer> marking = new ConcurrentHashMap<>(); + for (final AbstractPlace place : this.petriNet.getPlaces()) { + marking.put(place, place.getTokens()); + } + return marking; + } + + private boolean fire(final Map<AbstractPlace, Integer> marking, final AbstractTransition transition) + throws ResetArcMultiplicityException { + boolean success; + this.lock.writeLock().lock(); + try { + if (isEnabled(marking, transition)) { + for (final AbstractArc arc : this.petriNet.getConnectedArcs(transition)) { + if (arc.isSourceAPlace()) { + if (arc.isReset()) { // reset arc consumes them all + marking.put((AbstractPlace) arc.getSource(), 0); + } + if (arc.isRegular()) { + marking.put((AbstractPlace) arc.getSource(), + marking.get(arc.getSource()) - arc.getMultiplicity()); + } + + } + } + for (final AbstractArc arc : this.petriNet.getConnectedArcs(transition)) { + if (!arc.isSourceAPlace()) { + marking.put((AbstractPlace) arc.getDestination(), + marking.get(arc.getDestination()) + arc.getMultiplicity()); + } + } + success = true; + } else { + success = false; + } + } finally { + this.lock.writeLock().unlock(); + } + return success; + } + + private boolean isEnabled(final Map<AbstractPlace, Integer> marking, final AbstractTransition transition) + throws ResetArcMultiplicityException { + boolean isEnabled = true; + this.lock.readLock().lock(); + try { + for (final AbstractArc arc : this.petriNet.getConnectedArcs(transition)) { + if (arc.isSourceAPlace() && !arc.isReset()) { + // reset arc is always fireable + // but can be blocked by other arcs + + if (arc.isRegular()) { + if (marking.get(arc.getSource()) < arc.getMultiplicity()) {// normal arc + isEnabled = false; + break; + } + } else { + if (marking.get(arc.getSource()) >= arc.getMultiplicity()) {// inhibitory arc + isEnabled = false; + break; + } + } + + } + } + } finally { + this.lock.readLock().unlock(); + } + return isEnabled; + } + + public Set<AbstractTransition> getAllEnabledTransitions(final Map<AbstractPlace, Integer> marking) + throws ResetArcMultiplicityException { + final Set<AbstractTransition> enabledTransitions = new HashSet<>(); + this.lock.readLock().lock(); + try { + for (final AbstractTransition transition : this.petriNet.getTransitions()) { + if (isEnabled(marking, transition)) { + enabledTransitions.add(transition); + } + } + } finally { + this.lock.readLock().unlock(); + } + return enabledTransitions; + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/PetriNetInterface.java b/pne-editor/src/org/pneditor/petrinet/PetriNetInterface.java new file mode 100644 index 0000000000000000000000000000000000000000..99c1976da0a3061d5c8bb3752a2490aab3273c63 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/PetriNetInterface.java @@ -0,0 +1,207 @@ +package org.pneditor.petrinet; + +import java.util.HashSet; +import java.util.Set; + +import logger.PNEditorLogger; + +public abstract class PetriNetInterface { + + /* + * Stocking the elements of the PetriNet, used for the Boundedness algorithm. + * The id is used for saving petriNets + */ + private final Set<AbstractPlace> places = new HashSet<>(); + private final Set<AbstractTransition> transitions = new HashSet<>(); + private final Set<AbstractArc> arcs = new HashSet<>(); + private int nextId = 1; + + /* + * Interface that adapters must implement (+ the element specific methods) + */ + + public abstract AbstractPlace addPlace(); + + public abstract AbstractTransition addTransition(); + + public abstract AbstractArc addRegularArc(AbstractNode source, AbstractNode destination) + throws UnimplementedCaseException; + + public abstract AbstractArc addInhibitoryArc(AbstractPlace place, AbstractTransition transition) + throws UnimplementedCaseException; + + public abstract AbstractArc addResetArc(AbstractPlace place, AbstractTransition transition) + throws UnimplementedCaseException; + + public abstract void removePlace(AbstractPlace place); + + public abstract void removeTransition(AbstractTransition transition); + + public abstract void removeArc(AbstractArc arc); + + public abstract boolean isEnabled(AbstractTransition transition) throws ResetArcMultiplicityException; + + public abstract void fire(AbstractTransition transition) throws ResetArcMultiplicityException; + + /* + * Methods used by the software, not defined by the models. It mostly concerns + * stocking the elements, and adding the ID + */ + + public final AbstractPlace addAbstractPlace() { // template pattern + final AbstractPlace place = addPlace(); + this.places.add(place); + place.setId(this.nextId++); + return place; + } + + public final AbstractPlace addAbstractPlace(final int id) { // template pattern + final AbstractPlace place = addPlace(); + this.places.add(place); + place.setId(id); + if (id >= this.nextId) { + this.nextId = id + 1; + } + return place; + } + + public final AbstractTransition addAbstractTransition() { // template pattern + final AbstractTransition transition = addTransition(); + this.transitions.add(transition); + transition.setId(this.nextId++); + return transition; + } + + public final AbstractTransition addAbstractTransition(final int id) { // template pattern + final AbstractTransition transition = addTransition(); + this.transitions.add(transition); + transition.setId(id); + if (id >= this.nextId) { + this.nextId = id + 1; + } + return transition; + } + + public final AbstractArc addArcAgain(final AbstractArc arc, final AbstractNode source, final AbstractNode destination) { + AbstractArc newArc = null; + try { + if (arc.isReset()) { + newArc = addResArc((AbstractPlace) source, (AbstractTransition) destination); + } else { + if (arc.isInhibitory()) { + newArc = addInhibArc((AbstractPlace) source, (AbstractTransition) destination); + } else { + newArc = addRegArc(source, destination); + } + + newArc.setMultiplicity(arc.getMultiplicity()); + } + } catch (ResetArcMultiplicityException e) { + // should not happen + PNEditorLogger.severeLogs(e.getMessage()); + } catch (UnimplementedCaseException e) { + // should not happen since we're manipulating new objects, except if a behavior + // is not implemented + PNEditorLogger.warningLogs(e.getMessage()); + } + return newArc; + } + + public final AbstractArc addRegArc(final AbstractNode source, final AbstractNode destination) + throws UnimplementedCaseException { + final AbstractArc arc = addRegularArc(source, destination); + this.arcs.add(arc); + return arc; + } + + public final AbstractArc addInhibArc(final AbstractPlace place, final AbstractTransition transition) + throws UnimplementedCaseException { + final AbstractArc arc = addInhibitoryArc(place, transition); + this.arcs.add(arc); + return arc; + } + + public final AbstractArc addResArc(final AbstractPlace place, final AbstractTransition transition) + throws UnimplementedCaseException { + final AbstractArc arc = addResetArc(place, transition); + this.arcs.add(arc); + return arc; + } + + public final void removeAbstractPlace(final AbstractPlace place) { + removePlace(place); + this.places.remove(place); + } + + public final void removeAbstractTransition(final AbstractTransition transition) { + removeTransition(transition); + this.transitions.remove(transition); + } + + public final void removeAbstractArc(final AbstractArc arc) { + removeArc(arc); + this.arcs.remove(arc); + } + + public final boolean isBounded() throws ResetArcMultiplicityException { + return new Boundedness(this).isBounded(); + } + + public final AbstractPlace clonePlace(final AbstractPlace place) { + final AbstractPlace placeClone = addAbstractPlace(); + placeClone.setLabel(place.getLabel()); + placeClone.setTokens(place.getTokens()); + return placeClone; + } + + public final AbstractTransition cloneTransition(final AbstractTransition transition) { + final AbstractTransition transitionClone = addAbstractTransition(); + transitionClone.setLabel(transition.getLabel()); + return transitionClone; + } + + public final AbstractArc cloneArc(final AbstractArc arc, final AbstractNode source, final AbstractNode destination) { + AbstractArc newArc = null; + try { + if (arc.isReset()) { + newArc = addResArc((AbstractPlace) source, (AbstractTransition) destination); + } else { + if (arc.isInhibitory()) { + newArc = addInhibArc((AbstractPlace) source, (AbstractTransition) destination); + } else { + newArc = addRegArc(source, destination); + } + newArc.setMultiplicity(arc.getMultiplicity()); + } + } catch (UnimplementedCaseException | ResetArcMultiplicityException e) { + // should never happen because source and destination are new objects + // and ResetArcMultiplicity sould not happen as well + PNEditorLogger.severeLogs(e.getMessage()); + } + return newArc; + } + + /* + * Methods for the Boundedness algorithm + * + */ + + public Set<AbstractPlace> getPlaces() { + return this.places; + } + + public Set<AbstractTransition> getTransitions() { + return this.transitions; + } + + public Set<AbstractArc> getConnectedArcs(final AbstractTransition transition) { + final Set<AbstractArc> connectedArcs = new HashSet<>(); + for (final AbstractArc arc : this.arcs) { + if (arc.getSource().equals(transition) || arc.getDestination().equals(transition)) { + connectedArcs.add(arc); + } + } + return connectedArcs; + } + +} diff --git a/pne-editor/src/org/pneditor/petrinet/ResetArcMultiplicityException.java b/pne-editor/src/org/pneditor/petrinet/ResetArcMultiplicityException.java new file mode 100644 index 0000000000000000000000000000000000000000..deeada87ef4e286c5a4b8ee6e24c46c111a495e1 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/ResetArcMultiplicityException.java @@ -0,0 +1,9 @@ +package org.pneditor.petrinet; + +@SuppressWarnings("serial") +public class ResetArcMultiplicityException extends Exception { + + public ResetArcMultiplicityException() { + super("A reset arc can not have multiplicity. This exception should never happen"); + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/UnimplementedCaseException.java b/pne-editor/src/org/pneditor/petrinet/UnimplementedCaseException.java new file mode 100644 index 0000000000000000000000000000000000000000..c09892141fc7d3a6149f9760c04251486ea5ed9b --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/UnimplementedCaseException.java @@ -0,0 +1,9 @@ +package org.pneditor.petrinet; + +@SuppressWarnings("serial") +public class UnimplementedCaseException extends Exception { + + public UnimplementedCaseException(String msg) { + super(msg); + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/ArcAdapter.java b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/ArcAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..3b7da0ad9c370624410cc54abf61d4b09462bb8e --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/ArcAdapter.java @@ -0,0 +1,60 @@ +package org.pneditor.petrinet.adapters.Bouzazi; + +import org.petriNet.Arc; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractNode; +import org.pneditor.petrinet.ResetArcMultiplicityException; + +public class ArcAdapter extends AbstractArc { + + private Arc arc; + + public ArcAdapter(Arc arc) { + this.arc = arc; + } + + @Override + public AbstractNode getSource() { + return new PlaceAdapter(arc.getPlace()); + } + + @Override + public AbstractNode getDestination() { + return new TransitionAdapter(null, arc.getTransition()); + } + + @Override + public boolean isReset() { + return arc instanceof org.petriNet.IncomingArc_Videur; + } + + @Override + public boolean isRegular() { + return arc instanceof org.petriNet.IncomingArc_Simple; + } + + @Override + public boolean isInhibitory() { + return arc instanceof org.petriNet.IncomingArc_Zero; + } + + @Override + public int getMultiplicity() throws ResetArcMultiplicityException { + if (isReset()) { + throw new ResetArcMultiplicityException(); + } + return arc.getWeight(); + } + + @Override + public void setMultiplicity(int multiplicity) throws ResetArcMultiplicityException { + if (isReset()) { + throw new ResetArcMultiplicityException(); + } + arc.setWeight(multiplicity); + } + + public Arc getArc() { + return arc; + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PetriNetAdapter.java b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PetriNetAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..04377ab684d6eafcc7fb8cefbbf84fff62516d71 --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PetriNetAdapter.java @@ -0,0 +1,113 @@ +package org.pneditor.petrinet.adapters.Bouzazi; + +import org.petriNet.*; +import org.pneditor.petrinet.*; + +public class PetriNetAdapter extends PetriNetInterface { + + private PetriNet pn = new PetriNet(); + + @Override + public AbstractPlace addPlace() { + Place newPlace = new Place(0, pn.generateId(1)); // Initializing with 0 tokens + pn.addPlace(newPlace); // Adding to the underlying PetriNet + return new PlaceAdapter(newPlace); + } + + @Override + public AbstractTransition addTransition() { + Transition t = new Transition("Transition", pn.generateId(2)); + pn.addTransition(t); // Adding to the underlying PetriNet + return new TransitionAdapter(pn, t); + } + + @Override + public AbstractArc addRegularArc(AbstractNode source, AbstractNode destination) { + if (source instanceof PlaceAdapter && destination instanceof TransitionAdapter) { + Place place = ((PlaceAdapter) source).getPlace(); + Transition transition = ((TransitionAdapter) destination).getTransition(); + Arc arc = new IncomingArc_Simple(transition, place, 1, pn.generateId(3)); + pn.addArc(arc); // Add to the PetriNet + return new ArcAdapter(arc); + } else if (source instanceof TransitionAdapter && destination instanceof PlaceAdapter) { + Transition transition = ((TransitionAdapter) source).getTransition(); + Place place = ((PlaceAdapter) destination).getPlace(); + Arc arc = new OutgoingArc(transition, place, 1, pn.generateId(3)); + pn.addArc(arc); // Add to the PetriNet + return new ArcAdapter(arc); + } else { + // Handle invalid case without throwing exception, just return null or log + System.out.println("Invalid source and destination for regular arc."); + return null; + } + } + + @Override + public AbstractArc addInhibitoryArc(AbstractPlace place, AbstractTransition transition) { + if (place instanceof PlaceAdapter && transition instanceof TransitionAdapter) { + Place p = ((PlaceAdapter) place).getPlace(); + Transition t = ((TransitionAdapter) transition).getTransition(); + Arc arc = new IncomingArc_Zero(t, p, 1, pn.generateId(3)); + pn.addArc(arc); // Add to the PetriNet + return new ArcAdapter(arc); + } else { + System.out.println("Invalid place or transition for inhibitory arc."); + return null; + } + } + + @Override + public AbstractArc addResetArc(AbstractPlace place, AbstractTransition transition) { + if (place instanceof PlaceAdapter && transition instanceof TransitionAdapter) { + Place p = ((PlaceAdapter) place).getPlace(); + Transition t = ((TransitionAdapter) transition).getTransition(); + Arc arc = new IncomingArc_Videur(t, p, 1, pn.generateId(3)); + pn.addArc(arc); // Add to the PetriNet + return new ArcAdapter(arc); + } else { + System.out.println("Invalid place or transition for reset arc."); + return null; + } + } + + @Override + public void removePlace(AbstractPlace place) { + if (place instanceof PlaceAdapter) { + Place p = ((PlaceAdapter) place).getPlace(); + pn.removePlace(p); // Remove the place from the PetriNet + } + } + + @Override + public void removeTransition(AbstractTransition transition) { + if (transition instanceof TransitionAdapter) { + Transition t = ((TransitionAdapter) transition).getTransition(); + pn.removeTransition(t); // Remove the transition from the PetriNet + } + } + + @Override + public void removeArc(AbstractArc arc) { + if (arc instanceof ArcAdapter) { + Arc a = ((ArcAdapter) arc).getArc(); + pn.removeArc(a); // Remove the arc from the PetriNet + } + } + + @Override + public boolean isEnabled(AbstractTransition transition) { + if (transition instanceof TransitionAdapter) { + Transition t = ((TransitionAdapter) transition).getTransition(); + return t.canFire(); + } + return false; + } + + @Override + public void fire(AbstractTransition transition) { + if (transition instanceof TransitionAdapter) { + Transition t = ((TransitionAdapter) transition).getTransition(); + t.fire(); // Execute the transition in the underlying PetriNet + } + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PlaceAdapter.java b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PlaceAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..8623bcc54befa0162f768cefbe09c0f3d27b746c --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/PlaceAdapter.java @@ -0,0 +1,38 @@ +package org.pneditor.petrinet.adapters.Bouzazi; + +import org.petriNet.Place; +import org.pneditor.petrinet.AbstractPlace; + +public class PlaceAdapter extends AbstractPlace { + + private Place place; + + public PlaceAdapter(Place place) { + super("Place " + place.getId()); // Using the ID for a unique name + this.place = place; + } + + @Override + public void addToken() { + place.addTokens(1); // Add a single token to the place + } + + @Override + public void removeToken() { + place.removeTokens(1); // Remove a single token from the place + } + + @Override + public int getTokens() { + return place.getTokenCount(); // Return the current token count + } + + @Override + public void setTokens(int tokens) { + place.setTokenCount(tokens); // Update the token count in the place + } + + public Place getPlace() { + return place; // Expose the adapted Place object + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/TransitionAdapter.java b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/TransitionAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..94ab367f6993883e47114c3df1f8ca62efe8e75b --- /dev/null +++ b/pne-editor/src/org/pneditor/petrinet/adapters/Bouzazi/TransitionAdapter.java @@ -0,0 +1,30 @@ +package org.pneditor.petrinet.adapters.Bouzazi; + +import org.petriNet.PetriNet; +import org.petriNet.Transition; +import org.pneditor.petrinet.AbstractTransition; + +public class TransitionAdapter extends AbstractTransition { + + private final Transition transition; + + public TransitionAdapter(PetriNet pn, Transition t) { + super(t.getName()); // Initialize the AbstractTransition with the name from Transition + this.transition = t; + } + + // Expose the wrapped Transition + public Transition getTransition() { + return transition; + } + + @Override + public String getLabel() { + return transition.getName(); + } + + @Override + public void setLabel(String label) { + transition.setName(label); + } +} diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/imta/.trick b/pne-editor/src/org/pneditor/petrinet/adapters/imta/.trick new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pne-editor/src/org/pneditor/petrinet/adapters/initial/.trick b/pne-editor/src/org/pneditor/petrinet/adapters/initial/.trick new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pne-editor/src/org/pneditor/petrinet/models/imta/.trick b/pne-editor/src/org/pneditor/petrinet/models/imta/.trick new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pne-editor/src/org/pneditor/petrinet/models/initial/.trick b/pne-editor/src/org/pneditor/petrinet/models/initial/.trick new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/pne-editor/src/org/pneditor/save/xml/DocumentExporter.java b/pne-editor/src/org/pneditor/save/xml/DocumentExporter.java new file mode 100644 index 0000000000000000000000000000000000000000..bc6ac2b4e6c74ecf3e21ef2ab5626d18fb37c607 --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/DocumentExporter.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import java.awt.Point; +import java.awt.Rectangle; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicElement; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.ResetArcMultiplicityException; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public final class DocumentExporter { + + private final XmlDocument xmlDocument = new XmlDocument(); + + public DocumentExporter(final GraphicPetriNet petriNet) { + this.xmlDocument.petriNet = getXmlPetriNet(petriNet); + final Rectangle bounds = petriNet.getBounds(); + this.xmlDocument.left = bounds.x; + this.xmlDocument.top = bounds.y; + } + + public void writeToFile(final File file) throws JAXBException { + final JAXBContext ctx = JAXBContext.newInstance(XmlDocument.class); + final Marshaller marshaller = ctx.createMarshaller(); + marshaller.setProperty("jaxb.formatted.output", true); + try { + marshaller.marshal(this.xmlDocument, Files.newOutputStream(Paths.get(file.toURI()))); + } catch (IOException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + + public XmlPetriNet getXmlPetriNet(final GraphicPetriNet petriNet) { + final XmlPetriNet xmlPetriNet = new XmlPetriNet(); + xmlPetriNet.label = "PetriNet"; + for (final GraphicElement element : petriNet.getElements()) { + if (element.isTransition()) { + xmlPetriNet.addTransition(getXmlTransition((GraphicTransition) element)); + } else if (element.isPlace()) { + xmlPetriNet.addPlace(getXmlPlace((GraphicPlace) element)); + } else if (!element.isNode()) { + xmlPetriNet.addArc(getXmlArc((GraphicArc) element)); + } + } + return xmlPetriNet; + } + + private XmlPlace getXmlPlace(final GraphicPlace place) { + final XmlPlace xmlPlace = new XmlPlace(); + xmlPlace.id = place.getPlace().getId(); + xmlPlace.x = place.getCenter().x; + xmlPlace.y = place.getCenter().y; + xmlPlace.label = place.getLabel(); + xmlPlace.tokens = place.getPlace().getTokens(); + return xmlPlace; + } + + private XmlTransition getXmlTransition(final GraphicTransition transition) { + final XmlTransition xmlTransition = new XmlTransition(); + xmlTransition.id = transition.getTransition().getId(); + xmlTransition.x = transition.getCenter().x; + xmlTransition.y = transition.getCenter().y; + xmlTransition.label = transition.getLabel(); + return xmlTransition; + } + + private XmlArc getXmlArc(final GraphicArc gArc) { + final AbstractArc arc = gArc.getArc(); + final XmlArc xmlArc = new XmlArc(); + xmlArc.sourceId = arc.getSource().getId(); + xmlArc.destinationId = arc.getDestination().getId(); + xmlArc.type = arc.isRegular() ? "regular" : arc.isInhibitory() ? "inhibitory" : "reset"; + if (!arc.isReset()) { + try { + xmlArc.multiplicity = arc.getMultiplicity(); + } catch (ResetArcMultiplicityException e) { + PNEditorLogger.severeLogs(e.getMessage()); + } + } + final List<Point> breakPoints = gArc.getBreakPoints(); + for (final Point point : breakPoints) { + final XmlPoint xmlPoint = new XmlPoint(); + xmlPoint.x = point.x; + xmlPoint.y = point.y; + xmlArc.breakPoints.add(xmlPoint); + } + return xmlArc; + } +} diff --git a/pne-editor/src/org/pneditor/save/xml/DocumentImporter.java b/pne-editor/src/org/pneditor/save/xml/DocumentImporter.java new file mode 100644 index 0000000000000000000000000000000000000000..545d92b8d22c674ba6143b288c2297b9459c3294 --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/DocumentImporter.java @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import java.awt.Point; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; + +import org.pneditor.editor.gpetrinet.GraphicArc; +import org.pneditor.editor.gpetrinet.GraphicNode; +import org.pneditor.editor.gpetrinet.GraphicPetriNet; +import org.pneditor.editor.gpetrinet.GraphicPlace; +import org.pneditor.editor.gpetrinet.GraphicTransition; +import org.pneditor.petrinet.AbstractArc; +import org.pneditor.petrinet.AbstractPlace; +import org.pneditor.petrinet.AbstractTransition; +import org.pneditor.petrinet.ResetArcMultiplicityException; +import org.pneditor.petrinet.UnimplementedCaseException; + +import logger.PNEditorLogger; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class DocumentImporter { + + private XmlDocument xmlDocument; + final private Map<Integer, GraphicNode> nodeReferences = new HashMap<>(); + + public GraphicPetriNet readFromFile(final File file, final String model) + throws JAXBException, FileNotFoundException, IOException { + final JAXBContext ctx = JAXBContext.newInstance(XmlDocument.class); + final Unmarshaller unmarshaller = ctx.createUnmarshaller(); + final InputStream fileInputStream = Files.newInputStream(Paths.get(file.toURI())); + this.xmlDocument = (XmlDocument) unmarshaller.unmarshal(fileInputStream); + fileInputStream.close(); + return getPetriNet(model); + } + + private GraphicPetriNet getPetriNet(final String model) { + return getNewPetriNet(this.xmlDocument.petriNet, model); + } + + private GraphicPetriNet getNewPetriNet(final XmlPetriNet xmlPetriNet, final String model) { + final GraphicPetriNet gPetriNet = new GraphicPetriNet(model); + for (final XmlPlace xmlPlace : xmlPetriNet.places) { + addNewPlace(xmlPlace, gPetriNet); + } + for (final XmlTransition xmlTransition : xmlPetriNet.transitions) { + addNewTransition(xmlTransition, gPetriNet); + } + for (final XmlArc xmlArc : xmlPetriNet.arcs) { + addNewArc(xmlArc, gPetriNet); + } + return gPetriNet; + } + + private void addNewArc(final XmlArc xmlArc, final GraphicPetriNet gPetriNet) { + AbstractArc arc = null; + try { + if ("regular".equals(xmlArc.type)) { + arc = gPetriNet.getPetriNet().addRegArc(this.nodeReferences.get(xmlArc.sourceId).getNode(), + this.nodeReferences.get(xmlArc.destinationId).getNode()); + arc.setMultiplicity(xmlArc.multiplicity); + } else if ("reset".equals(xmlArc.type)) { + arc = gPetriNet.getPetriNet().addResArc( + ((GraphicPlace) this.nodeReferences.get(xmlArc.sourceId)).getPlace(), + ((GraphicTransition) this.nodeReferences.get(xmlArc.destinationId)).getTransition()); + } else if ("inhibitory".equals(xmlArc.type)) { + arc = gPetriNet.getPetriNet().addInhibArc( + ((GraphicPlace) this.nodeReferences.get(xmlArc.sourceId)).getPlace(), + ((GraphicTransition) this.nodeReferences.get(xmlArc.destinationId)).getTransition()); + arc.setMultiplicity(xmlArc.multiplicity); + } + + + final GraphicArc gArc = new GraphicArc(arc); + gArc.setDestination(this.nodeReferences.get(xmlArc.destinationId)); + gArc.setSource(this.nodeReferences.get(xmlArc.sourceId)); + final List<Point> breakPoints = new LinkedList<>(); + for (final XmlPoint xmlPoint : xmlArc.breakPoints) { + breakPoints.add(new Point(xmlPoint.x, xmlPoint.y)); + } + gArc.setBreakPoints(breakPoints); + gPetriNet.addElement(gArc); + } catch (ResetArcMultiplicityException | UnimplementedCaseException e) { + // should not happen since we're manipulating new objects, except if a behavior + // is not implemented, which would return UnimplementedCaseException + PNEditorLogger.severeLogs(e.getMessage()); + } + + } + + private void addNewPlace(final XmlPlace xmlPlace, final GraphicPetriNet gPetriNet) { + final AbstractPlace createdPlace = gPetriNet.getPetriNet().addAbstractPlace(xmlPlace.id); + createdPlace.setLabel(xmlPlace.label); + createdPlace.setTokens(xmlPlace.tokens); + final GraphicPlace representation = new GraphicPlace(createdPlace, xmlPlace.x, xmlPlace.y); + representation.setPlace(createdPlace); + gPetriNet.addElement(representation); + + this.nodeReferences.put(xmlPlace.id, representation); + } + + private void addNewTransition(final XmlTransition xmlTransition, final GraphicPetriNet gPetriNet) { + final AbstractTransition createdTransition = gPetriNet.getPetriNet().addAbstractTransition(xmlTransition.id); + createdTransition.setLabel(xmlTransition.label); + final GraphicTransition representation = new GraphicTransition(createdTransition, xmlTransition.x, xmlTransition.y); + representation.setTransition(createdTransition); + gPetriNet.addElement(representation); + + this.nodeReferences.put(xmlTransition.id, representation); + } +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlArc.java b/pne-editor/src/org/pneditor/save/xml/XmlArc.java new file mode 100644 index 0000000000000000000000000000000000000000..d0cefd8e4f69720289d903f93d8e2b309771b7cf --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlArc.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import java.util.LinkedList; +import java.util.List; +import javax.xml.bind.annotation.XmlElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlArc { + + @XmlElement(name = "sourceId") + public int sourceId; + + @XmlElement(name = "destinationId") + public int destinationId; + + @XmlElement(name = "breakPoint") + public List<XmlPoint> breakPoints = new LinkedList<>(); + + @XmlElement(name = "type") + public String type; + + @XmlElement(name = "multiplicity") + public int multiplicity; +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlDocument.java b/pne-editor/src/org/pneditor/save/xml/XmlDocument.java new file mode 100644 index 0000000000000000000000000000000000000000..4d843b954b8b15d917527a1c35684a6dbb9d9cbd --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlDocument.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ + +@XmlRootElement(name = "document") +public class XmlDocument { + + @XmlElement(name = "left") + public int left; + + @XmlElement(name = "top") + public int top; + + @XmlElement(name = "petriNet") + public XmlPetriNet petriNet; + +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlNode.java b/pne-editor/src/org/pneditor/save/xml/XmlNode.java new file mode 100644 index 0000000000000000000000000000000000000000..313e3bb63354c6a463d938e2593cded782a39f04 --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlNode.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import javax.xml.bind.annotation.XmlElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlNode { + + @XmlElement(name = "id") + public int id; + + @XmlElement(name = "label") + public String label; + + @XmlElement(name = "x") + public int x; + + @XmlElement(name = "y") + public int y; +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlPetriNet.java b/pne-editor/src/org/pneditor/save/xml/XmlPetriNet.java new file mode 100644 index 0000000000000000000000000000000000000000..809736bb3b1ba4beeedab58a9537974a24e6a1f7 --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlPetriNet.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import java.util.LinkedList; +import java.util.List; +import javax.xml.bind.annotation.XmlElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlPetriNet { + + @XmlElement(name = "label") + public String label; + + @XmlElement(name = "place") + public List<XmlPlace> places = new LinkedList<>(); + + @XmlElement(name = "transition") + public List<XmlTransition> transitions = new LinkedList<>(); + + @XmlElement(name = "arc") + public List<XmlArc> arcs = new LinkedList<>(); + + + public void addPlace(final XmlPlace place) { + places.add(place); + } + + public void addArc(final XmlArc arc) { + arcs.add(arc); + } + + public void addTransition(final XmlTransition transition) { + transitions.add(transition); + } + +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlPlace.java b/pne-editor/src/org/pneditor/save/xml/XmlPlace.java new file mode 100644 index 0000000000000000000000000000000000000000..de812f3b6f386a50f9f645972e64d70f1193e2ab --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlPlace.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import javax.xml.bind.annotation.XmlElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlPlace extends XmlNode { + + @XmlElement(name = "tokens") + public int tokens; + +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlPoint.java b/pne-editor/src/org/pneditor/save/xml/XmlPoint.java new file mode 100644 index 0000000000000000000000000000000000000000..545acb5a961f98d9fd3d55e789a062e8e90bd0ab --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlPoint.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + +import javax.xml.bind.annotation.XmlElement; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlPoint { + + @XmlElement(name = "y") + public int y; + + @XmlElement(name = "x") + public int x; + +} diff --git a/pne-editor/src/org/pneditor/save/xml/XmlTransition.java b/pne-editor/src/org/pneditor/save/xml/XmlTransition.java new file mode 100644 index 0000000000000000000000000000000000000000..7aeeee176c2513c20c39ed0dc68c105378817c94 --- /dev/null +++ b/pne-editor/src/org/pneditor/save/xml/XmlTransition.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.save.xml; + + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class XmlTransition extends XmlNode { + +} diff --git a/pne-editor/src/org/pneditor/util/CachedGraphics2D.java b/pne-editor/src/org/pneditor/util/CachedGraphics2D.java new file mode 100644 index 0000000000000000000000000000000000000000..2863ac9326f54b897333ac124ebd57d9df0693ec --- /dev/null +++ b/pne-editor/src/org/pneditor/util/CachedGraphics2D.java @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.text.AttributedCharacterIterator; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class CachedGraphics2D extends Graphics2D { + + final private Graphics graphics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics(); + private Font currentFont = new Font(null); + private Color currentColor = Color.white; + final private List<Drawable> toBeDrawn = new ArrayList<>(); + private float currentLineWidth = 1; + final private Rectangle integerBounds = new Rectangle(-1, -1); + final private Rectangle2D realBounds = new Rectangle2D.Float(0, 0, -1, -1); + + public Rectangle getIntegerBounds() { + Rectangle result = new Rectangle(this.integerBounds); + result.width++; + result.height++; + return result; + } + + public Rectangle2D getRealBounds() { + return this.realBounds; + } + + public void applyToGraphics(final Graphics2D g) { + for (final Drawable drawable : this.toBeDrawn) { + drawable.draw(g); + } + } + + private void addPointToBounds(final int x, final int y) { + final int excess = (int) Math.ceil(this.currentLineWidth / 2 - 0.5f); + this.integerBounds.add(x + excess, y + excess); + this.integerBounds.add(x - excess, y - excess); + this.integerBounds.add(x + excess, y - excess); + this.integerBounds.add(x - excess, y + excess); + final double realExcess = this.currentLineWidth / 2; + addPointToRectangle2D(this.realBounds, x + realExcess, y + realExcess); + addPointToRectangle2D(this.realBounds, x - realExcess, y - realExcess); + addPointToRectangle2D(this.realBounds, x + realExcess, y - realExcess); + addPointToRectangle2D(this.realBounds, x - realExcess, y + realExcess); + } + + private void addPointToRectangle2D(final Rectangle2D rectangle, final double x, final double y) { + if (rectangle.getWidth() < 0 || rectangle.getHeight() < 0) { + rectangle.setRect(x, y, 0, 0); + } else { + rectangle.add(x, y); + } + } + + private void addRectangleToBounds(final int x, final int y, final int width, final int height) { + addPointToBounds(x, y); + addPointToBounds(x + width, y + height); + addPointToBounds(x, y + height); + addPointToBounds(x + width, y); + } + + private interface Drawable { + + void draw(Graphics2D g); + } + + @Override + public void drawLine(final int x1, final int y1, final int x2, final int y2) { + addPointToBounds(x1, y1); + addPointToBounds(x2, y2); + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.drawLine(x1, y1, x2, y2); + } + }); + } + + @Override + public void fillRect(final int x, final int y, final int width, final int height) { + addRectangleToBounds(x, y, width - 1, height - 1); + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.fillRect(x, y, width, height); + } + }); + } + + @Override + public void drawPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { + for (int i = 0; i < nPoints; i++) { + addPointToBounds(xPoints[i], yPoints[i]); + } + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.drawPolygon(xPoints, yPoints, nPoints); + } + }); + } + + @Override + public void fillPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { + for (int i = 0; i < nPoints; i++) { + addPointToBounds(xPoints[i], yPoints[i]); + } + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.fillPolygon(xPoints, yPoints, nPoints); + } + }); + } + + @Override + public Color getColor() { + return this.currentColor; + } + + @Override + public void setColor(final Color c) { + this.currentColor = c; + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.setColor(c); + } + }); + } + + @Override + public void drawOval(final int x, final int y, final int width, final int height) { + addRectangleToBounds(x, y, width, height); + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.drawOval(x, y, width, height); + } + }); + } + + @Override + public void fillOval(final int x, final int y, final int width, final int height) { + addRectangleToBounds(x, y, width - 1, height - 1); + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.fillOval(x, y, width, height); + } + }); + } + + @Override + public void setStroke(final Stroke s) { + if (s instanceof BasicStroke) { + final BasicStroke stroke = (BasicStroke) s; + this.currentLineWidth = stroke.getLineWidth(); + } + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.setStroke(s); + } + }); + } + + @Override + public void drawString(final String str, final int x, final int y) { + final Rectangle stringBounds = getFontMetrics(this.currentFont).getStringBounds(str, this.graphics).getBounds(); + addRectangleToBounds(x, y - stringBounds.height, stringBounds.width, stringBounds.height); + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.drawString(str, x, y); + } + }); + } + + @Override + public Font getFont() { + return this.currentFont; + } + + @Override + public void setFont(final Font font) { + this.currentFont = font; + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.setFont(font); + } + }); + } + + @Override + public FontMetrics getFontMetrics(final Font f) { + return this.graphics.getFontMetrics(f); + } + + @Override + public void setRenderingHint(final Key hintKey, final Object hintValue) { + this.toBeDrawn.add(new Drawable() { + @Override + public void draw(final Graphics2D g) { + g.setRenderingHint(hintKey, hintValue); + } + }); + } + + //########################// NOT SUPPORTED YET //#########################// + + @Override + public void draw(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final AffineTransform xform, final ImageObserver obs) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawImage(final BufferedImage img, final BufferedImageOp op, final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRenderedImage(final RenderedImage img, final AffineTransform xform) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRenderableImage(final RenderableImage img, final AffineTransform xform) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final String str, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final AttributedCharacterIterator iterator, final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final AttributedCharacterIterator iterator, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawGlyphVector(final GlyphVector g, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fill(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean hit(final Rectangle rect, final Shape s, final boolean onStroke) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public GraphicsConfiguration getDeviceConfiguration() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setComposite(final Composite comp) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setPaint(final Paint paint) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Object getRenderingHint(final Key hintKey) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setRenderingHints(final Map<?, ?> hints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void addRenderingHints(final Map<?, ?> hints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public RenderingHints getRenderingHints() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void translate(final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void translate(final double tx, final double ty) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void rotate(final double theta) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void rotate(final double theta, final double x, final double y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void scale(final double sx, final double sy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void shear(final double shx, final double shy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void transform(final AffineTransform tx) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setTransform(final AffineTransform tx) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public AffineTransform getTransform() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Paint getPaint() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Composite getComposite() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setBackground(final Color color) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Color getBackground() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Stroke getStroke() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clip(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public FontRenderContext getFontRenderContext() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Graphics create() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setPaintMode() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXORMode(final Color c1) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Rectangle getClipBounds() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clipRect(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setClip(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Shape getClip() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setClip(final Shape clip) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void copyArea(final int x, final int y, final int width, final int height, final int dx, final int dy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clearRect(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fillRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fillArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawPolyline(final int[] xPoints, final int[] yPoints, final int nPoints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void dispose() { + throw new UnsupportedOperationException("Not supported yet."); + } + +} diff --git a/pne-editor/src/org/pneditor/util/Colors.java b/pne-editor/src/org/pneditor/util/Colors.java new file mode 100644 index 0000000000000000000000000000000000000000..48f58976ef9276a3b34cfba39752ad134bf80487 --- /dev/null +++ b/pne-editor/src/org/pneditor/util/Colors.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +import java.awt.Color; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class Colors { + + public static final Color CONNECTING = Color.GREEN; + public static final Color DISALLOWED = Color.RED; + public static final Color PERMITTED = Color.GREEN; + public static final Color SELECTED = Color.LIGHT_GRAY; + public static final Color SINGLESELECTED = Color.GRAY; + public static final Color POINTING = Color.BLUE; +} diff --git a/pne-editor/src/org/pneditor/util/Command.java b/pne-editor/src/org/pneditor/util/Command.java new file mode 100644 index 0000000000000000000000000000000000000000..17d7a958abe582d88bb38ea1abe26f441b4fd86e --- /dev/null +++ b/pne-editor/src/org/pneditor/util/Command.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public interface Command { + + void execute(); + + void undo(); + + void redo(); +} diff --git a/pne-editor/src/org/pneditor/util/EPSGraphics2D.java b/pne-editor/src/org/pneditor/util/EPSGraphics2D.java new file mode 100644 index 0000000000000000000000000000000000000000..5aef4a504d233d96fbb6fa84a2b8083552ba2c09 --- /dev/null +++ b/pne-editor/src/org/pneditor/util/EPSGraphics2D.java @@ -0,0 +1,635 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.RenderingHints.Key; +import java.awt.Shape; +import java.awt.Stroke; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; +import java.awt.image.renderable.RenderableImage; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.PrintStream; +import java.text.AttributedCharacterIterator; +import java.util.Map; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class EPSGraphics2D extends Graphics2D { + + private static final String APP_NAME = "PNEditor"; + private final Graphics graphics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics(); + private Font currentFont = new Font(null); + private final ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); + private final PrintStream out = new PrintStream(this.arrayOutputStream); + private final CachedGraphics2D cachedGraphics = new CachedGraphics2D(); + private Color currentColor = Color.black; + + public void writeToFile(final File file) throws FileNotFoundException { + final PrintStream fileOut = new PrintStream(file); + fileOut.println("%!PS-Adobe-3.0 EPSF-3.0"); + fileOut.println("%%Creator: " + APP_NAME); + fileOut.println("%%Pages: 1"); + fileOut.println("%%Orientation: Portrait"); + final Rectangle2D bounds = xy(this.cachedGraphics.getRealBounds()); + fileOut.println("%%BoundingBox: " + + (long) Math.floor(bounds.getMinX()) + " " + + (long) Math.floor(bounds.getMinY()) + " " + + (long) Math.ceil(bounds.getMaxX()) + " " + + (long) Math.ceil(bounds.getMaxY())); + fileOut.println("%%HiResBoundingBox: " + + bounds.getMinX() + " " + + bounds.getMinY() + " " + + bounds.getMaxX() + " " + + bounds.getMaxY()); + fileOut.println("%%EndComments"); + fileOut.println("%%Page: 1 1"); + fileOut.println("0 0 0 setrgbcolor"); + fileOut.println("[] 0 setdash"); + fileOut.println("1 setlinewidth"); + fileOut.println("0 setlinejoin"); + fileOut.println("0 setlinecap"); + fileOut.println("gsave [1 0 0 1 0 0] concat"); + fileOut.println("/Times-Bold findfont"); + fileOut.println("12 scalefont"); + fileOut.println("setfont"); + fileOut.print(this.arrayOutputStream.toString()); + fileOut.println("grestore"); + fileOut.println("showpage"); + fileOut.println("%%EOF"); + fileOut.close(); + } + + private double x(final double x) { + return x; + } + + private double y(final double y) { + return -y; + } + + private Rectangle2D xy(final Rectangle2D rectangle) { + final Rectangle2D result = new Rectangle2D.Double(); + final double x1 = x(rectangle.getX()); + final double y1 = y(rectangle.getY()); + final double x2 = x(rectangle.getMaxX()); + final double y2 = y(rectangle.getMaxY()); + result.setFrameFromDiagonal(x1, y1, x2, y2); + return result; + } + + private void newPath() { + this.out.println("newpath"); + } + + private void closePath() { + this.out.println("closepath"); + } + + private void stroke() { + this.out.println("stroke"); + } + + private void fill() { + this.out.println("fill"); + } + + private void moveTo(final double x, final double y) { + this.out.println(x(x) + " " + y(y) + " moveto"); + } + + private void lineTo(final double x, final double y) { + this.out.println(x(x) + " " + y(y) + " lineto"); + } + + private void curveTo(final double x1, final double y1, final double x2, final double y2, final double x3, final double y3) { + this.out.println(x(x1) + " " + y(y1) + " " + x(x2) + " " + y(y2) + " " + x(x3) + " " + y(y3) + " curveto"); + } + + private void circle(final double centerX, final double centerY, final double radius) { + this.out.println(x(centerX) + " " + y(centerY) + " " + radius + " 0 360 arc"); + } + + private void setColor(final double red, final double green, final double blue) { + this.out.println(red + " " + green + " " + blue + " setrgbcolor"); + } + + @Override + public void drawLine(final int x1, final int y1, final int x2, final int y2) { + this.cachedGraphics.drawLine(x1, y1, x2, y2); + this.out.println(); + this.out.println("% begin drawLine"); + newPath(); + moveTo(x1, y1); + lineTo(x2, y2); + stroke(); + this.out.println("% end drawLine"); + this.out.println(); + } + + private void makeRectanglePath(final int x, final int y, final int width, final int height) { + newPath(); + moveTo(x, y); + lineTo(x + width, y); + lineTo(x + width, y + height); + lineTo(x, y + height); + closePath(); + } + + @Override + public void drawRect(final int x, final int y, final int width, final int height) { + this.cachedGraphics.drawRect(x, y, width, height); + this.out.println(); + this.out.println("% begin drawRect"); + makeRectanglePath(x, y, width + 1, height + 1); + stroke(); + this.out.println("% end drawRect"); + this.out.println(); + } + + @Override + public void fillRect(final int x, final int y, final int width, final int height) { + this.cachedGraphics.fillRect(x, y, width, height); + this.out.println(); + this.out.println("% begin fillRect"); + makeRectanglePath(x, y, width, height); + fill(); + this.out.println("% end fillRect"); + this.out.println(); + } + + private void makePolygonPath(final int[] xPoints, final int[] yPoints, final int nPoints) { + newPath(); + moveTo(xPoints[0], yPoints[0]); + for (int i = 1; i < nPoints; i++) { + lineTo(xPoints[i], yPoints[i]); + } + closePath(); + } + + @Override + public void drawPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { + this.cachedGraphics.drawPolygon(xPoints, yPoints, nPoints); + this.out.println(); + this.out.println("% begin drawPolygon"); + makePolygonPath(xPoints, yPoints, nPoints); + stroke(); + this.out.println("% end drawPolygon"); + this.out.println(); + } + + @Override + public void fillPolygon(final int[] xPoints, final int[] yPoints, final int nPoints) { + this.cachedGraphics.fillPolygon(xPoints, yPoints, nPoints); + this.out.println(); + this.out.println("% begin fillPolygon"); + makePolygonPath(xPoints, yPoints, nPoints); + fill(); + this.out.println("% end fillPolygon"); + this.out.println(); + } + + @Override + public Color getColor() { + return this.currentColor; + } + + @Override + public void setColor(final Color c) { + final double red = (double) c.getRed() / 255; + final double green = (double) c.getGreen() / 255; + final double blue = (double) c.getBlue() / 255; + setColor(red, green, blue); + this.currentColor = c; + } + + private void makeOvalPath(final int x, final int y, final int width, final int height) { + newPath(); + if (width == height) { + final double radius = (double) width / 2; + final double centerX = x + radius; + final double centerY = y + radius; + circle(centerX, centerY, radius); + closePath(); + } else { + final double kappa = 0.552_284_749_8; + final double lHorizontal = kappa * width / 2; + final double lVertical = kappa * height / 2; + final double halfWidth = (double) width / 2; + final double halfHeight = (double) height / 2; + moveTo(x + halfWidth, y); + curveTo(x + halfWidth + lHorizontal, y, + x + width, y + lVertical, + x + width, y + halfHeight); + curveTo(x + width, y + halfHeight + lVertical, + x + halfWidth + lHorizontal, y + height, + x + halfWidth, y + height); + curveTo(x + lHorizontal, y + height, + x, y + halfHeight + lVertical, + x, y + halfHeight); + curveTo(x, y + lVertical, + x + lHorizontal, y, + x + halfWidth, y); + closePath(); + } + } + + @Override + public void drawOval(final int x, final int y, final int width, final int height) { + this.cachedGraphics.drawOval(x, y, width, height); + this.out.println(); + this.out.println("% begin drawOval"); + makeOvalPath(x, y, width + 1, height + 1); + stroke(); + this.out.println("% end drawOval"); + this.out.println(); + } + + @Override + public void fillOval(final int x, final int y, final int width, final int height) { + this.cachedGraphics.fillOval(x, y, width, height); + this.out.println(); + this.out.println("% begin fillOval"); + makeOvalPath(x, y, width, height); + fill(); + this.out.println("% end fillOval"); + this.out.println(); + } + + @Override + public void setStroke(final Stroke s) { + this.cachedGraphics.setStroke(s); + if (s instanceof BasicStroke) { + final BasicStroke stroke = (BasicStroke) s; + final double currentLineWidth = stroke.getLineWidth(); + final float[] dashArray = stroke.getDashArray(); + final int lineCap = stroke.getEndCap(); + final int lineJoin = stroke.getLineJoin(); + this.out.println(currentLineWidth + " setlinewidth"); + this.out.println(lineCap + " setlinecap"); + this.out.println(lineJoin + " setlinejoin"); + if (dashArray != null) { + final float dashPhase = stroke.getDashPhase(); + this.out.print("["); + for (final float d : dashArray) { + this.out.print(d + " "); + } + this.out.println("] " + dashPhase + " setdash"); + } else { + this.out.println("[] 0 setdash"); + } + } else { + throw new UnsupportedOperationException("Not supported yet."); + } + } + + @Override + public void drawString(final String str, final int x, final int y) { + this.cachedGraphics.drawString(str, x, y); + final String fileStr = str.replace("(", "\\(").replace(")", "\\)"); + moveTo(x, y); + this.out.println("(" + fileStr + ") show"); + } + + @Override + public Font getFont() { + return this.currentFont; + } + + @Override + public FontMetrics getFontMetrics(final Font f) { + return this.graphics.getFontMetrics(f); + } + + @Override + public void setFont(final Font font) { + this.cachedGraphics.setFont(font); + this.out.println("/Times-Bold findfont"); +// System.out.println("/" + font.getFamily() + "-" + font.getStyle() + " findfont"); + this.out.println(font.getSize() + (2 * font.getSize() / 12) + " scalefont"); + this.out.println("setfont"); + this.currentFont = font; + } + + //########################// NOT SUPPORTED YET //#########################// + @Override + public void draw(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final AffineTransform xform, final ImageObserver obs) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawImage(final BufferedImage img, final BufferedImageOp op, final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRenderedImage(final RenderedImage img, final AffineTransform xform) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRenderableImage(final RenderableImage img, final AffineTransform xform) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final String str, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final AttributedCharacterIterator iterator, final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawString(final AttributedCharacterIterator iterator, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawGlyphVector(final GlyphVector g, final float x, final float y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fill(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean hit(final Rectangle rect, final Shape s, final boolean onStroke) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public GraphicsConfiguration getDeviceConfiguration() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setComposite(final Composite comp) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setPaint(final Paint paint) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setRenderingHint(final Key hintKey, final Object hintValue) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Object getRenderingHint(final Key hintKey) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setRenderingHints(final Map<?, ?> hints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void addRenderingHints(final Map<?, ?> hints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public RenderingHints getRenderingHints() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void translate(final int x, final int y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void translate(final double tx, final double ty) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void rotate(final double theta) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void rotate(final double theta, final double x, final double y) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void scale(final double sx, final double sy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void shear(final double shx, final double shy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void transform(final AffineTransform tx) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setTransform(final AffineTransform tx) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public AffineTransform getTransform() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Paint getPaint() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Composite getComposite() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setBackground(final Color color) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Color getBackground() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Stroke getStroke() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clip(final Shape s) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public FontRenderContext getFontRenderContext() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Graphics create() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setPaintMode() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setXORMode(final Color c1) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Rectangle getClipBounds() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clipRect(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setClip(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Shape getClip() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void setClip(final Shape clip) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void copyArea(final int x, final int y, final int width, final int height, final int dx, final int dy) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void clearRect(final int x, final int y, final int width, final int height) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fillRoundRect(final int x, final int y, final int width, final int height, final int arcWidth, final int arcHeight) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void fillArc(final int x, final int y, final int width, final int height, final int startAngle, final int arcAngle) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void drawPolyline(final int[] xPoints, final int[] yPoints, final int nPoints) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int x, final int y, final int width, final int height, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean drawImage(final Image img, final int dx1, final int dy1, final int dx2, final int dy2, final int sx1, final int sy1, final int sx2, final int sy2, final Color bgcolor, final ImageObserver observer) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void dispose() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/pne-editor/src/org/pneditor/util/GraphicsTools.java b/pne-editor/src/org/pneditor/util/GraphicsTools.java new file mode 100644 index 0000000000000000000000000000000000000000..5642e379ba37eb0b72d52c1681b9e71a542c84b1 --- /dev/null +++ b/pne-editor/src/org/pneditor/util/GraphicsTools.java @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Cursor; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.imageio.ImageIO; +import javax.swing.ImageIcon; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class GraphicsTools { + + //PNEConstantsConfiguration.RESOURCESDIR already ends with a File.separator + //private final static String RESOURCESDIR = File.separator+org.pneditor.PNEConstantsConfiguration.RESOURCESDIR; + + public static ImageIcon getIcon(final String fileName) { + return new ImageIcon(GraphicsTools.class.getResource(fileName)); + //return new ImageIcon(GraphicsTools.class.getResource(RESOURCESDIR + fileName)); + } + + public static Cursor getCursor(final String fileName, final Point center) { + final Toolkit tk = Toolkit.getDefaultToolkit(); + //final Image image = tk.getImage(GraphicsTools.class.getResource(RESOURCESDIR + fileName)); + final Image image = tk.getImage(GraphicsTools.class.getResource(fileName)); + return tk.createCustomCursor(image, center, fileName); + } + + public static BufferedImage getBufferedImage(final String fileName) { + try { + return ImageIO.read(GraphicsTools.class.getResource(fileName)); + } catch (IOException ex) { + Logger.getLogger(GraphicsTools.class.getName()).log(Level.SEVERE, null, ex); //TODO: change this + return new BufferedImage(1, 1, IndexColorModel.TRANSLUCENT); + } + } + + public static void setDashedStroke(final Graphics g) { + final float dash1[] = {4.0f}; + final BasicStroke dashed = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 4.0f, dash1, 0.0f); + ((Graphics2D) g).setStroke(dashed); + } + + public static void setDefaultStroke(final Graphics g) { + final BasicStroke defaultStroke = new BasicStroke(); + ((Graphics2D) g).setStroke(defaultStroke); + } + + + public enum HorizontalAlignment { + + LEFT, + RIGHT, + CENTER + } + + public enum VerticalAlignment { + + TOP, + CENTER, + BOTTOM + } + + public static void drawString(final Graphics g, final String str, final int x, final int y, + final HorizontalAlignment horizontalAlignment, + final VerticalAlignment verticalAlignment) { + final int textWidth = g.getFontMetrics().stringWidth(str); + final int textHeight = g.getFontMetrics().getAscent(); + int resultX = x; + int resultY = y; + + // if horizontalAligment is left, do nothing + if (horizontalAlignment == HorizontalAlignment.CENTER) { + resultX -= textWidth / 2; + } else if (horizontalAlignment == HorizontalAlignment.RIGHT) { + resultX -= textWidth; + } + + // if verticalAligment is bottom, do nothing + if (verticalAlignment == VerticalAlignment.TOP) { + resultY += textHeight; + } else if (verticalAlignment == VerticalAlignment.CENTER) { + resultY += textHeight / 2 - 1; + } + + + final Color previousColor = g.getColor(); + g.setColor(new Color(1f, 1f, 1f, 0.7f)); +// g.setColor(new Color(0.7f, 0.7f, 1f, 0.7f)); //debug with this + g.fillRect(resultX, resultY - textHeight + 1, textWidth, g.getFontMetrics().getHeight() - 1); + g.setColor(previousColor); + g.drawString(str, resultX, resultY); + } + + //Jan Tancibok Inhibitor arc, Taken from http://stackoverflow.com/questions/21465570/two-points-and-then-finds-the-smallest-circle-and-the-smallest-rectangle-contain?rq=1 + public static void drawCircle(final Graphics g, final int xCenter, final int yCenter, final int x2, final int y2) { + final Graphics2D g2d = (Graphics2D) g; + g2d.setStroke(new BasicStroke(1f)); + + final double aDir = Math.atan2(xCenter - x2, yCenter - y2); + final int i2 = 9; //diameter + + final int x1 = x2 + xCor(i2, aDir); + final int y1 = y2 + yCor(i2, aDir); + + final double diameter = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); + final int cx = ((x2 + x1) / 2); + final int cy = (y2 + y1) / 2; + final int tlCornerx = (int) (cx - diameter / 2); + final int tlCornery = (int) (cy - diameter / 2); + + g2d.drawOval(tlCornerx, tlCornery, (int) diameter, (int) diameter); + g2d.fillOval(tlCornerx, tlCornery, (int) diameter, (int) diameter); + } + + //Taken from http://forum.java.sun.com/thread.jspa?threadID=378460&tstart=135 + public static void drawArrow(final Graphics g, final int xCenter, final int yCenter, final int x, final int y) { + final Graphics2D g2d = (Graphics2D) g; + final double aDir = Math.atan2(xCenter - x, yCenter - y); + //g2d.drawLine(x, y, xCenter, yCenter); + g2d.setStroke(new BasicStroke(1f)); // make the arrow head solid even if dash pattern has been specified + final Polygon tmpPoly = new Polygon(); + final int i1 = 12; + final int i2 = 6; // make the arrow head the same size regardless of the length + tmpPoly.addPoint(x, y); // arrow tip + tmpPoly.addPoint(x + xCor(i1, aDir + 0.5), y + yCor(i1, aDir + 0.5)); + tmpPoly.addPoint(x + xCor(i2, aDir), y + yCor(i2, aDir)); + tmpPoly.addPoint(x + xCor(i1, aDir - 0.5), y + yCor(i1, aDir - 0.5)); + tmpPoly.addPoint(x, y); // arrow tip + g2d.drawPolygon(tmpPoly); + g2d.fillPolygon(tmpPoly); // remove this line to leave arrow head unpainted + } + + //Jan Tancibok Reset arc + public static void drawArrowDouble(final Graphics g, final int xCenter, final int yCenter, final int x, final int y) { + final Graphics2D g2d = (Graphics2D) g; + final double aDir = Math.atan2(xCenter - x, yCenter - y); + //g2d.drawLine(x, y, xCenter, yCenter); + g2d.setStroke(new BasicStroke(1f)); // make the arrow head solid even if dash pattern has been specified + final Polygon tmpPoly = new Polygon(); + int i1 = 12; + final int i2 = 6; // make the arrow head the same size regardless of the length length + tmpPoly.addPoint(x, y); // arrow tip + tmpPoly.addPoint(x + xCor(i1, aDir + 0.5), y + yCor(i1, aDir + 0.5)); + tmpPoly.addPoint(x + xCor(i2, aDir), y + yCor(i2, aDir)); + tmpPoly.addPoint(x + xCor(i1, aDir - 0.5), y + yCor(i1, aDir - 0.5)); + tmpPoly.addPoint(x, y); // arrow tip + g2d.drawPolygon(tmpPoly); + g2d.fillPolygon(tmpPoly); + + i1 = 24; + final int move = 6; + final int dmove = 12; + tmpPoly.addPoint(x + xCor(i2 + move, aDir), y + yCor(i2 + move, aDir)); // arrow tip + tmpPoly.addPoint(x + xCor(i1, aDir - 0.25), y + yCor(i1, aDir - 0.25)); + tmpPoly.addPoint(x + xCor(i2 + dmove, aDir), y + yCor(i2 + dmove, aDir)); + tmpPoly.addPoint(x + xCor(i1, aDir + 0.25), y + yCor(i1, aDir + 0.25)); + tmpPoly.addPoint(x + xCor(i2 + move, aDir), y + yCor(i2 + move, aDir)); // arrow tip + g2d.drawPolygon(tmpPoly); + g2d.fillPolygon(tmpPoly);// remove this line to leave arrow head unpainted + } + + private static int yCor(final int len, final double dir) { + return (int) (len * Math.cos(dir)); + } + + private static int xCor(final int len, final double dir) { + return (int) (len * Math.sin(dir)); + } + + public static boolean isPointNearSegment(final Point from, final Point to, final Point testPos, final int nearTolerance) { + final Rectangle r = new Rectangle(testPos.x - nearTolerance / 2, testPos.y - nearTolerance / 2, nearTolerance, nearTolerance); + return r.intersectsLine(from.x, from.y, to.x, to.y); + } + + public static boolean isPointNearPoint(final Point from, final Point testPos, final int nearTolerance) { + final Rectangle r1 = new Rectangle(from.x - nearTolerance / 2, from.y - nearTolerance / 2, nearTolerance, nearTolerance); + final Rectangle r2 = new Rectangle(testPos.x, testPos.y, 1, 1); + return r2.intersects(r1); + } +} diff --git a/pne-editor/src/org/pneditor/util/Point.java b/pne-editor/src/org/pneditor/util/Point.java new file mode 100644 index 0000000000000000000000000000000000000000..9905d9b152aa7da5975eba8c5968dc4b49a78d97 --- /dev/null +++ b/pne-editor/src/org/pneditor/util/Point.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class Point { + + private java.awt.Point point; + + public Point(final int x, final int y) { + this.point = new java.awt.Point(x, y); + } + + public Point(final java.awt.Point point) { + this.point = point; + } + + public Point() { + this(0, 0); + } + + public int getX() { + return this.point.x; + } + + public int getY() { + return this.point.y; + } + + public double distance(final Point pointTo) { + return this.point.distance(pointTo.point); + } + + public Point getTranslated(final int dx, final int dy) { + return new Point(getX() + dx, getY() + dy); + } + + public Point getTranslated(final Point pointToTranslate) { + return new Point(getX() + pointToTranslate.getX(), getY() + pointToTranslate.getY()); + } + + public Point getNegative() { + return new Point(-getX(), -getY()); + } + + public java.awt.Point getPoint() { + return new java.awt.Point(this.point); + } + + @Override + public String toString() { + return "[" + this.point.x + ", " + this.point.y + "]"; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final Point other = (Point) obj; + if (this.point != other.point && (this.point == null || !this.point.equals(other.point))) { //TODO: check + return false; + } + return true; + } + + @Override + public int hashCode() { + return 33 + (this.point != null ? this.point.hashCode() : 0); + } + +} diff --git a/pne-editor/src/org/pneditor/util/StringTools.java b/pne-editor/src/org/pneditor/util/StringTools.java new file mode 100644 index 0000000000000000000000000000000000000000..15825dcc7df4d13475caddb33a75db4a7725489a --- /dev/null +++ b/pne-editor/src/org/pneditor/util/StringTools.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.util; + +import java.io.File; +import java.util.Locale; + +/** + * This class contains some simple string management functions. + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class StringTools { + + /** + * Returns extension of a file i.e. from File("example.html.txt") returns + * "txt" + * + * @param file file to get the extension from + * @return extension of the file + */ + public static String getExtension(final File file) { + return getExtension(file.getName()); + } + + private static String getExtension(final String filename) { + String ext = null; + final int i = filename.lastIndexOf('.'); + + if (i > 0 && i < filename.length() - 1) { + ext = filename.substring(i + 1).toLowerCase(Locale.ENGLISH); + } + if (ext != null) { + return ext; + } + return ""; + } + + public static String getExtensionCutOut(final String filename) { + final String extension = getExtension(filename); + return filename.substring(0, filename.length() - 1 - extension.length()); + } +} diff --git a/pne-editor/src/org/pneditor/workflow/WorkflowLogger.java b/pne-editor/src/org/pneditor/workflow/WorkflowLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..157cb4a6a04e8e0d2504c93a73b52e32e0b0bc0b --- /dev/null +++ b/pne-editor/src/org/pneditor/workflow/WorkflowLogger.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz <riesz.martin at gmail.com> + * + * 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 org.pneditor.workflow; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Date; + +import org.pneditor.petrinet.models.initial.Transition; + +/** + * + * @author Martin Riesz <riesz.martin at gmail.com> + */ +public class WorkflowLogger { + + private static String defaultLogDirectory = System.getProperty("user.home") + File.separator+"logs"; + + public static void log(final String dirName, final String workflowFilename, final String caseId, final Transition transition, final String userId) throws IOException { + final File directory = new File(dirName); + if (!directory.exists()) { + directory.mkdirs(); + } + final File file = new File(dirName + File.separator + workflowFilename + ".log"); + final OutputStream fileOutputStream = Files.newOutputStream(Paths.get(file.toURI())); + final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); + final PrintStream out = new PrintStream(bufferedOutputStream); + out.println(caseId + " " + new Date().getTime() + " " + userId + " " + transition.getLabel()); + bufferedOutputStream.close(); + fileOutputStream.close(); + } + + public static void log(final String workflowFilename, final String caseId, final Transition transition, final String userId) throws IOException { + log(defaultLogDirectory, workflowFilename, caseId, transition, userId); + } + +} diff --git a/pne-editor/src/resources/icon16.png b/pne-editor/src/resources/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..d81727230644f550b4681ae5265967058a6022b7 Binary files /dev/null and b/pne-editor/src/resources/icon16.png differ diff --git a/pne-editor/src/resources/icon32.png b/pne-editor/src/resources/icon32.png new file mode 100644 index 0000000000000000000000000000000000000000..ab227c3f4a1620add321edec3a25b4a5228bd32f Binary files /dev/null and b/pne-editor/src/resources/icon32.png differ diff --git a/pne-editor/src/resources/icon48.png b/pne-editor/src/resources/icon48.png new file mode 100644 index 0000000000000000000000000000000000000000..a599ef868f9038b480b32ed5fffc9f1bd87c8f32 Binary files /dev/null and b/pne-editor/src/resources/icon48.png differ diff --git a/pne-editor/src/resources/pneditor/About16.gif b/pne-editor/src/resources/pneditor/About16.gif new file mode 100644 index 0000000000000000000000000000000000000000..04da95eb831806d5586b246423126eb2b477eb7b Binary files /dev/null and b/pne-editor/src/resources/pneditor/About16.gif differ diff --git a/pne-editor/src/resources/pneditor/Add16.gif b/pne-editor/src/resources/pneditor/Add16.gif new file mode 100644 index 0000000000000000000000000000000000000000..0fc47e193cf88cea7e6718e602e71f560cfad5cd Binary files /dev/null and b/pne-editor/src/resources/pneditor/Add16.gif differ diff --git a/pne-editor/src/resources/pneditor/Copy16.gif b/pne-editor/src/resources/pneditor/Copy16.gif new file mode 100644 index 0000000000000000000000000000000000000000..fa986813a821559ca5120bf8dfaa3c38cd474190 Binary files /dev/null and b/pne-editor/src/resources/pneditor/Copy16.gif differ diff --git a/pne-editor/src/resources/pneditor/Cut16.gif b/pne-editor/src/resources/pneditor/Cut16.gif new file mode 100644 index 0000000000000000000000000000000000000000..14b73a8577fa6d300ddf6ea8b1f999ee214f822f Binary files /dev/null and b/pne-editor/src/resources/pneditor/Cut16.gif differ diff --git a/pne-editor/src/resources/pneditor/Delete16.gif b/pne-editor/src/resources/pneditor/Delete16.gif new file mode 100644 index 0000000000000000000000000000000000000000..d9d1a338f4dea468baac6c6ad2a763b4af4d5b5e Binary files /dev/null and b/pne-editor/src/resources/pneditor/Delete16.gif differ diff --git a/pne-editor/src/resources/pneditor/New16.gif b/pne-editor/src/resources/pneditor/New16.gif new file mode 100644 index 0000000000000000000000000000000000000000..3513dfddbb9402244b189c1886e738051f83b256 Binary files /dev/null and b/pne-editor/src/resources/pneditor/New16.gif differ diff --git a/pne-editor/src/resources/pneditor/Open16.gif b/pne-editor/src/resources/pneditor/Open16.gif new file mode 100644 index 0000000000000000000000000000000000000000..fabd5676f96cf46b62fe3c91fce204c2339b64ea Binary files /dev/null and b/pne-editor/src/resources/pneditor/Open16.gif differ diff --git a/pne-editor/src/resources/pneditor/Paste16.gif b/pne-editor/src/resources/pneditor/Paste16.gif new file mode 100644 index 0000000000000000000000000000000000000000..f118c7eab8c450001b762d80446f6b7b9f5222c3 Binary files /dev/null and b/pne-editor/src/resources/pneditor/Paste16.gif differ diff --git a/pne-editor/src/resources/pneditor/Preferences16.gif b/pne-editor/src/resources/pneditor/Preferences16.gif new file mode 100644 index 0000000000000000000000000000000000000000..32b77eee23246aea9b62b83c954d325b0fcc14b2 Binary files /dev/null and b/pne-editor/src/resources/pneditor/Preferences16.gif differ diff --git a/pne-editor/src/resources/pneditor/Redo16.gif b/pne-editor/src/resources/pneditor/Redo16.gif new file mode 100644 index 0000000000000000000000000000000000000000..8fdd814c2f412a1d3de25534f056137fc26f8f1e Binary files /dev/null and b/pne-editor/src/resources/pneditor/Redo16.gif differ diff --git a/pne-editor/src/resources/pneditor/Remove16.gif b/pne-editor/src/resources/pneditor/Remove16.gif new file mode 100644 index 0000000000000000000000000000000000000000..c1b4ca11db482031fb59ece38e8f5b5798cd3663 Binary files /dev/null and b/pne-editor/src/resources/pneditor/Remove16.gif differ diff --git a/pne-editor/src/resources/pneditor/Save16.gif b/pne-editor/src/resources/pneditor/Save16.gif new file mode 100644 index 0000000000000000000000000000000000000000..954f1accde64db9e98e9a6e528b459f3027b018c Binary files /dev/null and b/pne-editor/src/resources/pneditor/Save16.gif differ diff --git a/pne-editor/src/resources/pneditor/SaveAs16.gif b/pne-editor/src/resources/pneditor/SaveAs16.gif new file mode 100644 index 0000000000000000000000000000000000000000..8d3929c8aa7d56483d4d3b218e840ca56506561a Binary files /dev/null and b/pne-editor/src/resources/pneditor/SaveAs16.gif differ diff --git a/pne-editor/src/resources/pneditor/Undo16.gif b/pne-editor/src/resources/pneditor/Undo16.gif new file mode 100644 index 0000000000000000000000000000000000000000..25cbc64796c7eddd97af39b2fbddf6a36f0c6234 Binary files /dev/null and b/pne-editor/src/resources/pneditor/Undo16.gif differ diff --git a/pne-editor/src/resources/pneditor/addrole.gif b/pne-editor/src/resources/pneditor/addrole.gif new file mode 100644 index 0000000000000000000000000000000000000000..a55d2a36e8282021094e9b799c60a9695440d3ff Binary files /dev/null and b/pne-editor/src/resources/pneditor/addrole.gif differ diff --git a/pne-editor/src/resources/pneditor/addtorole16.gif b/pne-editor/src/resources/pneditor/addtorole16.gif new file mode 100644 index 0000000000000000000000000000000000000000..b35b2752131848d62c17c14d570a14dd9c7b4204 Binary files /dev/null and b/pne-editor/src/resources/pneditor/addtorole16.gif differ diff --git a/pne-editor/src/resources/pneditor/arc16.gif b/pne-editor/src/resources/pneditor/arc16.gif new file mode 100644 index 0000000000000000000000000000000000000000..77e6c48b22fb6bb16f0a0b1dc0bae63a84e1c0c5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/arc16.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/arc.gif b/pne-editor/src/resources/pneditor/canvas/arc.gif new file mode 100644 index 0000000000000000000000000000000000000000..d6128c07470b1a2da41968d2c4c05e498c323b86 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/arc.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/fire.gif b/pne-editor/src/resources/pneditor/canvas/fire.gif new file mode 100644 index 0000000000000000000000000000000000000000..35553866b63d13dc5117a38100c74e32ba7a374d Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/fire.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/fullrole.gif b/pne-editor/src/resources/pneditor/canvas/fullrole.gif new file mode 100644 index 0000000000000000000000000000000000000000..113b95af4daad79110a3e7aab6e6c9688778fa52 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/fullrole.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/mixedrole.gif b/pne-editor/src/resources/pneditor/canvas/mixedrole.gif new file mode 100644 index 0000000000000000000000000000000000000000..792b1cbcd027674342cc96d4902bd245603b11c5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/mixedrole.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/partialrole.gif b/pne-editor/src/resources/pneditor/canvas/partialrole.gif new file mode 100644 index 0000000000000000000000000000000000000000..579b2bdc03b010a5bfba2348b7c8f8fe13d46371 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/partialrole.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/partialrole2.gif b/pne-editor/src/resources/pneditor/canvas/partialrole2.gif new file mode 100644 index 0000000000000000000000000000000000000000..792b1cbcd027674342cc96d4902bd245603b11c5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/partialrole2.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/place.gif b/pne-editor/src/resources/pneditor/canvas/place.gif new file mode 100644 index 0000000000000000000000000000000000000000..0bc14cb5751b51e6b04ef28c0d35a8030fdc88bc Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/place.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/token.gif b/pne-editor/src/resources/pneditor/canvas/token.gif new file mode 100644 index 0000000000000000000000000000000000000000..68dff14d7c6be853f2b012f65382eb47f0fa2981 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/token.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/token_or_fire.gif b/pne-editor/src/resources/pneditor/canvas/token_or_fire.gif new file mode 100644 index 0000000000000000000000000000000000000000..116d562298a425dd66f3c259565dbbc30885a6e6 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/token_or_fire.gif differ diff --git a/pne-editor/src/resources/pneditor/canvas/transition.gif b/pne-editor/src/resources/pneditor/canvas/transition.gif new file mode 100644 index 0000000000000000000000000000000000000000..bce10117d110f6864f634e79e4010e8dc436d0c9 Binary files /dev/null and b/pne-editor/src/resources/pneditor/canvas/transition.gif differ diff --git a/pne-editor/src/resources/pneditor/closesubnet.gif b/pne-editor/src/resources/pneditor/closesubnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..f5b2b7a3170ddc0ad2c20cbea588223d50b39317 Binary files /dev/null and b/pne-editor/src/resources/pneditor/closesubnet.gif differ diff --git a/pne-editor/src/resources/pneditor/converttransitiontosubnet.gif b/pne-editor/src/resources/pneditor/converttransitiontosubnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..56111b9632510b94f8861bc0b2ee46f2ef8ba940 Binary files /dev/null and b/pne-editor/src/resources/pneditor/converttransitiontosubnet.gif differ diff --git a/pne-editor/src/resources/pneditor/deleterole.gif b/pne-editor/src/resources/pneditor/deleterole.gif new file mode 100644 index 0000000000000000000000000000000000000000..112d3cd88d7409ab50c33a4deb3b1e114d40f55c Binary files /dev/null and b/pne-editor/src/resources/pneditor/deleterole.gif differ diff --git a/pne-editor/src/resources/pneditor/export.gif b/pne-editor/src/resources/pneditor/export.gif new file mode 100644 index 0000000000000000000000000000000000000000..6450b2e65c68b4a2c8afad8a67111e9104ef885b Binary files /dev/null and b/pne-editor/src/resources/pneditor/export.gif differ diff --git a/pne-editor/src/resources/pneditor/filechooser/eps.gif b/pne-editor/src/resources/pneditor/filechooser/eps.gif new file mode 100644 index 0000000000000000000000000000000000000000..42e46be7df27a12c84d9b9825bd81858ed6338df Binary files /dev/null and b/pne-editor/src/resources/pneditor/filechooser/eps.gif differ diff --git a/pne-editor/src/resources/pneditor/filechooser/file.gif b/pne-editor/src/resources/pneditor/filechooser/file.gif new file mode 100644 index 0000000000000000000000000000000000000000..c401de63c94ec51299bed7e2017dfd02743c6f3b Binary files /dev/null and b/pne-editor/src/resources/pneditor/filechooser/file.gif differ diff --git a/pne-editor/src/resources/pneditor/filechooser/pflow.gif b/pne-editor/src/resources/pneditor/filechooser/pflow.gif new file mode 100644 index 0000000000000000000000000000000000000000..2e131c71846f5de678029acb53a852f0c444b7a4 Binary files /dev/null and b/pne-editor/src/resources/pneditor/filechooser/pflow.gif differ diff --git a/pne-editor/src/resources/pneditor/filechooser/png.gif b/pne-editor/src/resources/pneditor/filechooser/png.gif new file mode 100644 index 0000000000000000000000000000000000000000..6b48693f3770868968c53d60752efe067c900057 Binary files /dev/null and b/pne-editor/src/resources/pneditor/filechooser/png.gif differ diff --git a/pne-editor/src/resources/pneditor/filechooser/pnml.gif b/pne-editor/src/resources/pneditor/filechooser/pnml.gif new file mode 100644 index 0000000000000000000000000000000000000000..b6470e7362b1bb0eac40974e894260b5475ea563 Binary files /dev/null and b/pne-editor/src/resources/pneditor/filechooser/pnml.gif differ diff --git a/pne-editor/src/resources/pneditor/import.gif b/pne-editor/src/resources/pneditor/import.gif new file mode 100644 index 0000000000000000000000000000000000000000..bceb6878e33b972519aaad07b9c3289dc2970015 Binary files /dev/null and b/pne-editor/src/resources/pneditor/import.gif differ diff --git a/pne-editor/src/resources/pneditor/label.gif b/pne-editor/src/resources/pneditor/label.gif new file mode 100644 index 0000000000000000000000000000000000000000..60d4e6eff1c2f39162607588aba9f4490a814313 Binary files /dev/null and b/pne-editor/src/resources/pneditor/label.gif differ diff --git a/pne-editor/src/resources/pneditor/layout.gif b/pne-editor/src/resources/pneditor/layout.gif new file mode 100644 index 0000000000000000000000000000000000000000..3fee08c888f8f67002e033a822006ee341d956d1 Binary files /dev/null and b/pne-editor/src/resources/pneditor/layout.gif differ diff --git a/pne-editor/src/resources/pneditor/layout.xcf b/pne-editor/src/resources/pneditor/layout.xcf new file mode 100644 index 0000000000000000000000000000000000000000..276aee00f24ed124a7a1fd436ad33985264ae8bc Binary files /dev/null and b/pne-editor/src/resources/pneditor/layout.xcf differ diff --git a/pne-editor/src/resources/pneditor/log.gif b/pne-editor/src/resources/pneditor/log.gif new file mode 100644 index 0000000000000000000000000000000000000000..bc278f9ae9b15c27ba6bc9b0541b7836bae74fd5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/log.gif differ diff --git a/pne-editor/src/resources/pneditor/multiplicity.gif b/pne-editor/src/resources/pneditor/multiplicity.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0d55fd08b992ab5d3f62fa0dc205c42af72f928 Binary files /dev/null and b/pne-editor/src/resources/pneditor/multiplicity.gif differ diff --git a/pne-editor/src/resources/pneditor/opensubnet.gif b/pne-editor/src/resources/pneditor/opensubnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..2a077358fad80dc5224f6257333e387cf7194d8e Binary files /dev/null and b/pne-editor/src/resources/pneditor/opensubnet.gif differ diff --git a/pne-editor/src/resources/pneditor/place16.gif b/pne-editor/src/resources/pneditor/place16.gif new file mode 100644 index 0000000000000000000000000000000000000000..0667de9a324f5a104ec853a301aea1f1101091f5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/place16.gif differ diff --git a/pne-editor/src/resources/pneditor/removefromrole16.gif b/pne-editor/src/resources/pneditor/removefromrole16.gif new file mode 100644 index 0000000000000000000000000000000000000000..39c35eee59616b3c19327ec8a4ed67c3d4f4a9a3 Binary files /dev/null and b/pne-editor/src/resources/pneditor/removefromrole16.gif differ diff --git a/pne-editor/src/resources/pneditor/replacesubnet.gif b/pne-editor/src/resources/pneditor/replacesubnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..140f67c3098bf038f9980a2b2eecd3feae011f24 Binary files /dev/null and b/pne-editor/src/resources/pneditor/replacesubnet.gif differ diff --git a/pne-editor/src/resources/pneditor/replacetransitionbysubnet.gif b/pne-editor/src/resources/pneditor/replacetransitionbysubnet.gif new file mode 100644 index 0000000000000000000000000000000000000000..140f67c3098bf038f9980a2b2eecd3feae011f24 Binary files /dev/null and b/pne-editor/src/resources/pneditor/replacetransitionbysubnet.gif differ diff --git a/pne-editor/src/resources/pneditor/savesubnetas.gif b/pne-editor/src/resources/pneditor/savesubnetas.gif new file mode 100644 index 0000000000000000000000000000000000000000..296fd5ad98e77db1c9d4d77fbc45122984d5e3fb Binary files /dev/null and b/pne-editor/src/resources/pneditor/savesubnetas.gif differ diff --git a/pne-editor/src/resources/pneditor/select.gif b/pne-editor/src/resources/pneditor/select.gif new file mode 100644 index 0000000000000000000000000000000000000000..8e8b1153b48da7eef94866fa40abe5c275424cdc Binary files /dev/null and b/pne-editor/src/resources/pneditor/select.gif differ diff --git a/pne-editor/src/resources/pneditor/setarcresetaction.gif b/pne-editor/src/resources/pneditor/setarcresetaction.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c37e3ab870332670d18d7662900af64b624c4bb Binary files /dev/null and b/pne-editor/src/resources/pneditor/setarcresetaction.gif differ diff --git a/pne-editor/src/resources/pneditor/staticplace.gif b/pne-editor/src/resources/pneditor/staticplace.gif new file mode 100644 index 0000000000000000000000000000000000000000..550a831b142ed220e1ecbdbd678ffdb6001457cb Binary files /dev/null and b/pne-editor/src/resources/pneditor/staticplace.gif differ diff --git a/pne-editor/src/resources/pneditor/synthesize.gif b/pne-editor/src/resources/pneditor/synthesize.gif new file mode 100644 index 0000000000000000000000000000000000000000..ccb97868ac00454f3955be7705bae5bcf432c655 Binary files /dev/null and b/pne-editor/src/resources/pneditor/synthesize.gif differ diff --git a/pne-editor/src/resources/pneditor/synthesize.xcf b/pne-editor/src/resources/pneditor/synthesize.xcf new file mode 100644 index 0000000000000000000000000000000000000000..14d4e2f150c9aafb507e5d5fc598e1656e42664e Binary files /dev/null and b/pne-editor/src/resources/pneditor/synthesize.xcf differ diff --git a/pne-editor/src/resources/pneditor/token_and_fire16.gif b/pne-editor/src/resources/pneditor/token_and_fire16.gif new file mode 100644 index 0000000000000000000000000000000000000000..79c94f14256e18c868eb86e76c5b75878b30a93d Binary files /dev/null and b/pne-editor/src/resources/pneditor/token_and_fire16.gif differ diff --git a/pne-editor/src/resources/pneditor/tokens.gif b/pne-editor/src/resources/pneditor/tokens.gif new file mode 100644 index 0000000000000000000000000000000000000000..5c45fce0221936e03c42711d759b72a340c8cbc0 Binary files /dev/null and b/pne-editor/src/resources/pneditor/tokens.gif differ diff --git a/pne-editor/src/resources/pneditor/transition16.gif b/pne-editor/src/resources/pneditor/transition16.gif new file mode 100644 index 0000000000000000000000000000000000000000..b98da190ba2efcad71cfc32bbfbe641c5731c1c5 Binary files /dev/null and b/pne-editor/src/resources/pneditor/transition16.gif differ diff --git a/src/main/java/org/petriNet/Main.java b/src/main/java/org/petriNet/Main.java index 40a4ca45d95a05ed1720a7eb9b8e157e70287b4f..798714eefc1414d40fc5f7a08b455a388d8d8a2e 100644 --- a/src/main/java/org/petriNet/Main.java +++ b/src/main/java/org/petriNet/Main.java @@ -35,7 +35,7 @@ public class Main { // CP4 Place P4 = new Place(0, Mutex.generateId(1)); - Mutex.addPlace(P4); + Mutex.addPlace(P4); // CT4 Transition T4 = new Transition("T4", Mutex.generateId(2));