diff --git a/.gitignore b/.gitignore index d6648aa..6df6619 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ nbproject/private/ out/ .idea/workspace.xml .idea/tasks.xml +/bin/ diff --git a/README.md b/README.md index 95d6ad8..d0bffdf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,16 @@ PNEditor (Petri Net editor) ======== +Status of the different branches : + +- Invariant : adds a token limit on places +- MacroRecorder : abandonned branche (a version of macro that had modifications from invariant) +- MacroRecorderClean : adds a macro manager +- MacroLimit : integrates the token limit and the macro manager +- macroAndTokenLimit : integrates the token limit, the macro manager and the fire N modification +from https://github.com/e17goudi/pneditor. due to some modifications on the marking class there, +this version compile but has some bugs (try to find them !) + + You can download PNEditor from [www.pneditor.org](http://www.pneditor.org/) diff --git a/src/org/pneditor/editor/MacroManager.java b/src/org/pneditor/editor/MacroManager.java new file mode 100644 index 0000000..82e21d8 --- /dev/null +++ b/src/org/pneditor/editor/MacroManager.java @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz + * + * 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 . + */ +package org.pneditor.editor; + +import java.util.ArrayList; +import java.util.List; +import org.pneditor.editor.actions.RecordMacroAction; +import org.pneditor.editor.actions.PlayMacroAction; +import org.pneditor.util.Command; +import org.pneditor.util.GraphicsTools; +import javax.swing.AbstractAction; + +import org.pneditor.util.RecordableCommand; + + +/** + * MacroManager manages macro recording and playing + * + * @author Ladislas Ducerf + */ +public class MacroManager { + + + //the list of commands, once recording is done + private List recordedCommands = new ArrayList(); + // list of commands being recorded + private List buffer = new ArrayList(); + /* + * The separation of the two list allows for the saved macro to be played during + * recording, so the new one can be composed of the old one + */ + + + private Root root; + private PlayMacroAction playMacroAction; + private boolean recording; + + /** + * Constructs a new MacroManager + * + * @param root Root object + * @param playMacroAction action for play macro button + */ + public MacroManager(Root root, PlayMacroAction playMacroAction) { + this.root = root; + this.playMacroAction = playMacroAction; + this.recording = false; + } + + /** + * Records a command in the buffer if it implements the RecordableCommand + * interface + * + * @param command the command to be recorded + */ + public void recordCommand(Command command) { + //Do we want macro to be sensitive to undo/redo during recording ? + // Currently they are not + if(isRecordableCommand(command) ) { + buffer.add((RecordableCommand) command); + //currentCommandIndex = buffer.size() - 1; + } + } + + /** + * Returns true if a commands implements the RecordableCommand interface + * + * @param command the command to be tested + * @return + */ + public boolean isRecordableCommand(Command command) { + return (command instanceof RecordableCommand); + } + + /** + * Puts the macroManager in recording mode and prepares everything + */ + public void beginRecording() { + this.recording = true; + eraseBuffer(); + refresh(); + } + + /** + * Puts the macroManager out of recording mode and saves the buffer + */ + public void endRecording() { + this.recording = false; + copyBufferToRecordedCommands(); + refresh(); + } + + + /** + * Identifies if all elements of the macro (places/nodes) are still existing + * + * @return false if at least one element is missing, true otherwise + */ + public boolean macroUnaffected() { + boolean unaffected = true; + for (RecordableCommand command : recordedCommands) { + if(! root.getDocument().petriNet.getCurrentSubnet().getElements().contains(command.getRecordedElement())) { + unaffected = false; + break; + } + } + return unaffected; + } + + /** + * Undo a played macro. Called by the undo method of the PlayMacro command + */ + public void undoMacro() { + for (int i = recordedCommands.size() - 1 ; i >= 0 ; i --) { + Command command = recordedCommands.get(i); + command.undo(); + refresh(); + } + } + + + /** + * Execute a macro. Called by the execute method of the PlayMacro command + */ + public void playMacro() { + for (Command command : recordedCommands) { + command.execute(); + refresh(); + } + + } + + /** + * Erases all commands from the buffer. + */ + public void eraseBuffer() { + buffer = new ArrayList(); + } + + /** + * Copy the buffer to the recorded commands + */ + public void copyBufferToRecordedCommands() { + recordedCommands = new ArrayList(buffer); + } + + /** + * Return the number of commands saved + * + * @return the size of recordedCommands + */ + public int getRecordedCommandsNumber() { + return recordedCommands.size(); + } + + + public boolean getRecording() { + return recording; + } + + + private void refresh() { + root.refreshAll(); + } + + public void refreshPlayIcon() { + if (macroUnaffected()) { + playMacroAction.putValue(AbstractAction.SMALL_ICON, GraphicsTools.getIcon("pneditor/macroPlay.gif")); + } else { + playMacroAction.putValue(AbstractAction.SMALL_ICON, GraphicsTools.getIcon("pneditor/macroPlayUncertain.gif")); + } + } + +} diff --git a/src/org/pneditor/editor/Root.java b/src/org/pneditor/editor/Root.java index 7fbdd07..449fb39 100644 --- a/src/org/pneditor/editor/Root.java +++ b/src/org/pneditor/editor/Root.java @@ -119,6 +119,15 @@ public UndoManager getUndoManager() { return undoManager; } + // Macro manager - per tab + protected RecordMacroAction recordMacro = new RecordMacroAction(this); + protected PlayMacroAction playMacro = new PlayMacroAction(this); + private MacroManager macroManager = new MacroManager(this, playMacro); + + public MacroManager getMacroManager() { + return macroManager; + } + // Current directory - per application private File currentDirectory; @@ -310,6 +319,7 @@ public void refreshAll() { canvas.repaint(); enableOnlyPossibleActions(); getRoleEditor().refreshSelected(); + getMacroManager().refreshPlayIcon(); } public void repaintCanvas() { @@ -317,6 +327,9 @@ public void repaintCanvas() { } private void enableOnlyPossibleActions() { + + + boolean isDeletable = clickedElement != null && !(clickedElement instanceof ReferencePlace) || !selection.isEmpty() @@ -335,13 +348,15 @@ private void enableOnlyPossibleActions() { boolean roleSelected = !roleEditor.getSelectedElements().isEmpty(); boolean isParent = !document.petriNet.isCurrentSubnetRoot(); boolean isPtoT = false; - + boolean macroCurrentlyRecording = getMacroManager().getRecording(); + boolean macroExists = (getMacroManager().getRecordedCommandsNumber()!=0 ); + + if (isArc) { Arc test; test = (Arc) clickedElement; isPtoT = test.isPlaceToTransition(); } - cutAction.setEnabled(isCutable); copyAction.setEnabled(isCopyable); pasteAction.setEnabled(isPastable); @@ -362,6 +377,8 @@ private void enableOnlyPossibleActions() { undo.setEnabled(getUndoManager().isUndoable()); redo.setEnabled(getUndoManager().isRedoable()); setPlaceStatic.setEnabled(isPlaceNode); + + playMacro.setEnabled(macroExists&(!macroCurrentlyRecording)); } @Override @@ -521,7 +538,11 @@ private void setupMainFrame() { toolBar.addSeparator(); toolBar.add(addSelectedTransitionsToSelectedRoles); toolBar.add(removeSelectedTransitionsFromSelectedRoles); - + toolBar.addSeparator(); + + toolBar.add(recordMacro); + toolBar.add(playMacro); + JMenuBar menuBar = new JMenuBar(); mainFrame.setJMenuBar(menuBar); diff --git a/src/org/pneditor/editor/UndoManager.java b/src/org/pneditor/editor/UndoManager.java index 118d6cf..0d1ce06 100644 --- a/src/org/pneditor/editor/UndoManager.java +++ b/src/org/pneditor/editor/UndoManager.java @@ -60,6 +60,9 @@ public void executeCommand(Command command) { executedCommands.add(command); currentCommandIndex = executedCommands.size() - 1; command.execute(); + if (root.getMacroManager().getRecording()) { + root.getMacroManager().recordCommand(command); + } refresh(); root.setModified(true); } diff --git a/src/org/pneditor/editor/actions/PlayMacroAction.java b/src/org/pneditor/editor/actions/PlayMacroAction.java new file mode 100644 index 0000000..d8ce22b --- /dev/null +++ b/src/org/pneditor/editor/actions/PlayMacroAction.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz + * + * 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 . + */ +package org.pneditor.editor.actions; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.HashSet; +import java.util.Set; +import javax.swing.AbstractAction; +import javax.swing.KeyStroke; +import org.pneditor.editor.Root; +import org.pneditor.editor.commands.PlayMacroCommand; +import org.pneditor.petrinet.Element; +import org.pneditor.util.GraphicsTools; + +/** + * + * @author Ladislas Ducerf + */ +public class PlayMacroAction extends AbstractAction { + + private Root root; + + public PlayMacroAction(Root root) { + this.root = root; + String name = "Play macro"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon("pneditor/macroPlay.gif")); + putValue(SHORT_DESCRIPTION, name); + setEnabled(false); + } + + public void actionPerformed(ActionEvent e) { + root.getUndoManager().executeCommand(new PlayMacroCommand(root.getMacroManager())); + } +} diff --git a/src/org/pneditor/editor/actions/RecordMacroAction.java b/src/org/pneditor/editor/actions/RecordMacroAction.java new file mode 100644 index 0000000..aa6e0d0 --- /dev/null +++ b/src/org/pneditor/editor/actions/RecordMacroAction.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz + * + * 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 . + */ +package org.pneditor.editor.actions; + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.util.HashSet; +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.petrinet.Element; +import org.pneditor.util.GraphicsTools; + +/** + * + * @author Ladislas Ducerf + */ +public class RecordMacroAction extends AbstractAction { + + private Root root; + + public RecordMacroAction(Root root) { + this.root = root; + String name = "Record macro of token operations"; + putValue(NAME, name); + putValue(SMALL_ICON, GraphicsTools.getIcon("pneditor/macroRecord.gif")); + putValue(SHORT_DESCRIPTION, name); + setEnabled(true); + } + + public void actionPerformed(ActionEvent e) { + if(root.getMacroManager().getRecording()) { //currently recording + root.getMacroManager().endRecording(); + putValue(SMALL_ICON, GraphicsTools.getIcon("pneditor/macroRecord.gif")); + String name = "Record macro of the 'Edit tokens / Fire transitions' tool"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + + }else { //currently not recording + root.getMacroManager().beginRecording(); + putValue(SMALL_ICON, GraphicsTools.getIcon("pneditor/macroStop.gif")); + String name = "Stop macro recording"; + putValue(NAME, name); + putValue(SHORT_DESCRIPTION, name); + + } + } +} diff --git a/src/org/pneditor/editor/commands/AddTokenCommand.java b/src/org/pneditor/editor/commands/AddTokenCommand.java index 9b725c9..5c6403d 100644 --- a/src/org/pneditor/editor/commands/AddTokenCommand.java +++ b/src/org/pneditor/editor/commands/AddTokenCommand.java @@ -16,15 +16,16 @@ */ package org.pneditor.editor.commands; +import org.pneditor.petrinet.Element; import org.pneditor.petrinet.Marking; import org.pneditor.petrinet.PlaceNode; -import org.pneditor.util.Command; +import org.pneditor.util.RecordableCommand; /** * * @author Martin Riesz */ -public class AddTokenCommand implements Command { +public class AddTokenCommand implements RecordableCommand { private PlaceNode placeNode; private Marking marking; @@ -51,4 +52,8 @@ public String toString() { return "Add token"; } + public Element getRecordedElement() { + return placeNode; + } + } diff --git a/src/org/pneditor/editor/commands/FireTransitionCommand.java b/src/org/pneditor/editor/commands/FireTransitionCommand.java index 0375173..4d61cdd 100644 --- a/src/org/pneditor/editor/commands/FireTransitionCommand.java +++ b/src/org/pneditor/editor/commands/FireTransitionCommand.java @@ -16,15 +16,17 @@ */ package org.pneditor.editor.commands; +import org.pneditor.petrinet.Element; import org.pneditor.petrinet.Marking; import org.pneditor.petrinet.Transition; -import org.pneditor.util.Command; +import org.pneditor.util.RecordableCommand; + /** * * @author Martin Riesz */ -public class FireTransitionCommand implements Command { +public class FireTransitionCommand implements RecordableCommand { private Transition transition; private Marking marking; @@ -50,9 +52,14 @@ public void redo() { execute(); } + public Element getRecordedElement() { + return transition; + } + @Override public String toString() { return "Fire transition"; } + } diff --git a/src/org/pneditor/editor/commands/PlayMacroCommand.java b/src/org/pneditor/editor/commands/PlayMacroCommand.java new file mode 100644 index 0000000..00f8d95 --- /dev/null +++ b/src/org/pneditor/editor/commands/PlayMacroCommand.java @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz + * + * 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 . + */ +package org.pneditor.editor.commands; + +import org.pneditor.util.Command; +import org.pneditor.editor.MacroManager; + +/** + * + * @author Ladislas Ducerf + */ +public class PlayMacroCommand implements Command { + + private MacroManager macroManager; + + public PlayMacroCommand(MacroManager macroManager) { + this.macroManager = macroManager; + } + + public void execute() { + macroManager.playMacro(); + } + + public void undo() { + macroManager.undoMacro(); + } + + public void redo() { + execute(); + } + + @Override + public String toString() { + return "Play Macro"; + } + +} diff --git a/src/org/pneditor/editor/commands/RemoveTokenCommand.java b/src/org/pneditor/editor/commands/RemoveTokenCommand.java index d72933a..2785543 100644 --- a/src/org/pneditor/editor/commands/RemoveTokenCommand.java +++ b/src/org/pneditor/editor/commands/RemoveTokenCommand.java @@ -16,15 +16,16 @@ */ package org.pneditor.editor.commands; +import org.pneditor.petrinet.Element; import org.pneditor.petrinet.Marking; import org.pneditor.petrinet.PlaceNode; -import org.pneditor.util.Command; +import org.pneditor.util.RecordableCommand; /** * * @author Martin Riesz */ -public class RemoveTokenCommand implements Command { +public class RemoveTokenCommand implements RecordableCommand { private PlaceNode placeNode; private Marking marking; @@ -53,4 +54,8 @@ public String toString() { return "Remove token"; } + public Element getRecordedElement() { + return placeNode; + } + } diff --git a/src/org/pneditor/util/RecordableCommand.java b/src/org/pneditor/util/RecordableCommand.java new file mode 100644 index 0000000..001b7c4 --- /dev/null +++ b/src/org/pneditor/util/RecordableCommand.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008-2010 Martin Riesz + * + * 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 . + */ +package org.pneditor.util; + +import org.pneditor.petrinet.Element; +/** + * + * @author Ladislas Ducerf + */ +public interface RecordableCommand extends Command{ + + public Element getRecordedElement(); + +} diff --git a/src/resources/pneditor/macroPlay.gif b/src/resources/pneditor/macroPlay.gif new file mode 100644 index 0000000..5a5e42c Binary files /dev/null and b/src/resources/pneditor/macroPlay.gif differ diff --git a/src/resources/pneditor/macroPlayUncertain.gif b/src/resources/pneditor/macroPlayUncertain.gif new file mode 100644 index 0000000..7949ffe Binary files /dev/null and b/src/resources/pneditor/macroPlayUncertain.gif differ diff --git a/src/resources/pneditor/macroRecord.gif b/src/resources/pneditor/macroRecord.gif new file mode 100644 index 0000000..32bc76a Binary files /dev/null and b/src/resources/pneditor/macroRecord.gif differ diff --git a/src/resources/pneditor/macroStop.gif b/src/resources/pneditor/macroStop.gif new file mode 100644 index 0000000..3a5ae0d Binary files /dev/null and b/src/resources/pneditor/macroStop.gif differ