Released GUI version.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package pl.umk.mat.martinp.reactics;
|
||||
|
||||
import edu.uci.ics.jung.algorithms.layout.FRLayout;
|
||||
import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
|
||||
import edu.uci.ics.jung.algorithms.layout.Layout;
|
||||
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
|
||||
@@ -29,11 +30,13 @@ import java.io.PrintWriter;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class ContextAutomatonEditor extends JPanel {
|
||||
public class ContextAutomatonEditor extends JPanel implements RSObserver {
|
||||
private enum EditorState {STATE, EDGE, DELETE, CLEAR, NONE}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ReactionSystem rs;
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Visual configuration settings
|
||||
//---------------------------------------------------------------
|
||||
@@ -79,6 +82,8 @@ public class ContextAutomatonEditor extends JPanel {
|
||||
createGraphEditor();
|
||||
createModeButtonsPanel();
|
||||
createContextMenus();
|
||||
|
||||
rs = ReactionSystem.getInstance();
|
||||
}
|
||||
|
||||
public boolean isModified() { return graph.isModified(); }
|
||||
@@ -99,6 +104,18 @@ public class ContextAutomatonEditor extends JPanel {
|
||||
graph.loadFromXML(input);
|
||||
}
|
||||
|
||||
|
||||
public void recalculateCoordinates() {
|
||||
Layout<CAState, CAEdge> autoLayout = new FRLayout<CAState, CAEdge>(graph, graphViewer.getSize());
|
||||
autoLayout.initialize();
|
||||
|
||||
for (CAState state : graph.getVertices()) {
|
||||
Point2D pos = autoLayout.transform(state);
|
||||
state.updateLocation(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void clear() {
|
||||
graph.clear();
|
||||
|
||||
@@ -349,7 +366,6 @@ public class ContextAutomatonEditor extends JPanel {
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else {
|
||||
//TODO: State description should be unique
|
||||
idOk = true;
|
||||
state.setLabel(newLabel);
|
||||
}
|
||||
@@ -393,6 +409,10 @@ public class ContextAutomatonEditor extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public void onRSUpdate() {
|
||||
repaint();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -525,10 +545,16 @@ public class ContextAutomatonEditor extends JPanel {
|
||||
edge = pickSupport.getEdge(layout, clickPt.getX(), clickPt.getY());
|
||||
|
||||
if (node != null) {
|
||||
Collection<CAEdge> edges = graph.getIncidentEdges(node);
|
||||
|
||||
for (CAEdge e : edges)
|
||||
rs.removeCAEdge(e);
|
||||
|
||||
graph.removeState(node);
|
||||
}
|
||||
else if (edge != null) {
|
||||
graph.removeEdge(edge);
|
||||
rs.removeCAEdge(edge);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -254,8 +254,11 @@ class ContextAutomatonGraph extends DirectedSparseGraph<CAState, CAEdge> {
|
||||
public void addEdge(CAState from, CAState to, Collection<Transition> transitionList) {
|
||||
CAEdge edge = this.findEdge(from, to);
|
||||
|
||||
if (edge == null)
|
||||
this.addEdge(new CAEdge(transitionList), from, to);
|
||||
if (edge == null) {
|
||||
CAEdge caEdge = ReactionSystem.getInstance().createCAEdge();
|
||||
caEdge.addTransitions(transitionList);
|
||||
this.addEdge(caEdge, from, to);
|
||||
}
|
||||
else
|
||||
edge.addTransitions(transitionList);
|
||||
|
||||
@@ -378,9 +381,9 @@ class CAEdge {
|
||||
this.id = nextId++;
|
||||
}
|
||||
|
||||
public CAEdge(Collection<Transition> transitionList) {
|
||||
this.transitions.addAll(transitionList);
|
||||
}
|
||||
// public CAEdge(Collection<Transition> transitionList) {
|
||||
// this.transitions.addAll(transitionList);
|
||||
// }
|
||||
|
||||
Vector<Transition> getTransitions() {
|
||||
return transitions;
|
||||
|
||||
@@ -17,9 +17,10 @@ import java.util.Collection;
|
||||
import java.util.Vector;
|
||||
|
||||
|
||||
public class FormulaEditor extends JPanel {
|
||||
public class FormulaEditor extends JPanel implements RSObserver {
|
||||
private FormulaTableModel ftModel;
|
||||
private JTable formTable;
|
||||
private ReactionSystem rs;
|
||||
private Vector<Formula> formulaList;
|
||||
|
||||
boolean modified = false;
|
||||
@@ -34,8 +35,9 @@ public class FormulaEditor extends JPanel {
|
||||
static final Border selectedBorder = BorderFactory.createLineBorder(Color.RED, 2);
|
||||
|
||||
|
||||
public FormulaEditor() {
|
||||
formulaList = new Vector<Formula>();
|
||||
public FormulaEditor(ReactionSystem rs) {
|
||||
this.rs = rs;
|
||||
formulaList = rs.formulas;
|
||||
|
||||
// Create the table for displaying formulas. Prevent default selection modes.
|
||||
ftModel = new FormulaTableModel();
|
||||
@@ -106,7 +108,7 @@ public class FormulaEditor extends JPanel {
|
||||
ftModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
private boolean showFormulaEditDialog(Formula ff) {
|
||||
private boolean showFormulaEditDialog(JFrame parent, Formula ff) {
|
||||
final int Select = 0;
|
||||
final int Approve = 1;
|
||||
|
||||
@@ -149,7 +151,7 @@ public class FormulaEditor extends JPanel {
|
||||
labelInput.setText(labelStr);
|
||||
formulaInput.setText(formulaStr);
|
||||
|
||||
int result = JOptionPane.showConfirmDialog(null, myPanel,
|
||||
int result = JOptionPane.showConfirmDialog(parent, myPanel,
|
||||
"Formula details", JOptionPane.OK_CANCEL_OPTION);
|
||||
|
||||
if (result != JOptionPane.OK_OPTION) {
|
||||
@@ -159,8 +161,6 @@ public class FormulaEditor extends JPanel {
|
||||
labelStr = labelInput.getText();
|
||||
formulaStr = formulaInput.getText();
|
||||
|
||||
//TODO: Validate the data entered to the text fields
|
||||
|
||||
ff.label = labelStr;
|
||||
ff.formula = formulaStr;
|
||||
|
||||
@@ -171,10 +171,10 @@ public class FormulaEditor extends JPanel {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addFormula() {
|
||||
public void addFormula(JFrame parent) {
|
||||
Formula ff = new Formula();
|
||||
|
||||
if (showFormulaEditDialog(ff)) {
|
||||
if (showFormulaEditDialog(parent, ff)) {
|
||||
formulaList.add(ff);
|
||||
modified = true;
|
||||
ftModel.fireTableDataChanged();
|
||||
@@ -182,11 +182,11 @@ public class FormulaEditor extends JPanel {
|
||||
}
|
||||
|
||||
// If more than one formula is selected throw an exception only the first can be edited
|
||||
public void editFormula() {
|
||||
public void editFormula(JFrame parent) {
|
||||
int[] selected = formTable.getSelectedRows();
|
||||
|
||||
if (selected.length != 1) {
|
||||
JOptionPane.showMessageDialog(this, "Select a single formula to edit.", "Select formula", JOptionPane.WARNING_MESSAGE);
|
||||
JOptionPane.showMessageDialog(parent, "Select a single formula to edit.", "Select formula", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ public class FormulaEditor extends JPanel {
|
||||
if (fEdt == null)
|
||||
return;
|
||||
|
||||
showFormulaEditDialog(fEdt);
|
||||
showFormulaEditDialog(parent, fEdt);
|
||||
fEdt.status = Formula.FormulaStatus.None;
|
||||
modified = true;
|
||||
ftModel.fireTableDataChanged();
|
||||
@@ -240,6 +240,10 @@ public class FormulaEditor extends JPanel {
|
||||
ftModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
public void onRSUpdate() {
|
||||
resetFormulasStatus();
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
static class FormulaColumnModel extends DefaultTableColumnModel {
|
||||
int colno = 0;
|
||||
|
||||
@@ -17,10 +17,8 @@ import java.util.*;
|
||||
class ProcessEditor extends JPanel {
|
||||
private JTable reactionList;
|
||||
private RSTableModel reactionsModel;
|
||||
private Vector<Reaction> reactions;
|
||||
|
||||
private final int id;
|
||||
private String label;
|
||||
private RSProcess rsProcess;
|
||||
private boolean modified = false;
|
||||
|
||||
private JCheckBox selectBox;
|
||||
@@ -30,32 +28,12 @@ class ProcessEditor extends JPanel {
|
||||
private final Color selectedBorderColor = new Color(150, 10, 10);
|
||||
private static final int borderThickness = 4;
|
||||
|
||||
private static int nextId = 1;
|
||||
|
||||
|
||||
public ProcessEditor() {
|
||||
id = nextId;
|
||||
++nextId;
|
||||
label = new String("Process_" + id);
|
||||
public ProcessEditor(RSProcess rsProc) {
|
||||
rsProcess = rsProc;
|
||||
init();
|
||||
}
|
||||
|
||||
ProcessEditor(String name) {
|
||||
id = nextId;
|
||||
++nextId;
|
||||
label = name;
|
||||
init();
|
||||
}
|
||||
|
||||
ProcessEditor(ProcessEditor procEdt) {
|
||||
id = nextId;
|
||||
++nextId;
|
||||
label = "Copy_of_" + procEdt.label;
|
||||
init();
|
||||
reactions.addAll(procEdt.reactions);
|
||||
reactionsModel.fireTableDataChanged();
|
||||
modified = procEdt.modified;
|
||||
}
|
||||
public RSProcess getProcess() { return rsProcess; }
|
||||
|
||||
public boolean isSelected() {
|
||||
return selectBox.isSelected();
|
||||
@@ -66,17 +44,12 @@ class ProcessEditor extends JPanel {
|
||||
public void clearModificationStatus() { modified = false; }
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void addReaction(Reaction rr) {
|
||||
reactions.add(rr);
|
||||
reactionsModel.fireTableDataChanged();
|
||||
return rsProcess.label;
|
||||
}
|
||||
|
||||
private void init() {
|
||||
// Create border for the component
|
||||
outBorder = BorderFactory.createTitledBorder(label);
|
||||
outBorder = BorderFactory.createTitledBorder(rsProcess.label);
|
||||
Font font = outBorder.getTitleFont();
|
||||
Font newFont = new Font (font.getFamily(), Font.BOLD, font.getSize() + 2);
|
||||
outBorder.setTitleFont(new Font (font.getFamily(), Font.BOLD, font.getSize() + 2));
|
||||
@@ -85,7 +58,6 @@ class ProcessEditor extends JPanel {
|
||||
setBorder(outBorder);
|
||||
|
||||
// Create reactions list component
|
||||
reactions = new Vector<Reaction>();
|
||||
reactionsModel = new RSTableModel();
|
||||
reactionList = new JTable(reactionsModel);
|
||||
|
||||
@@ -122,14 +94,6 @@ class ProcessEditor extends JPanel {
|
||||
});
|
||||
buttonPanel.add(rmButton);
|
||||
|
||||
JButton optButton = new JButton("Options");
|
||||
optButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
editOptions();
|
||||
}
|
||||
});
|
||||
buttonPanel.add(optButton);
|
||||
|
||||
selectBox = new JCheckBox("Select");
|
||||
selectBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
@@ -145,7 +109,7 @@ class ProcessEditor extends JPanel {
|
||||
setPreferredSize(new Dimension(-1, 200));
|
||||
}
|
||||
|
||||
private boolean showReactionEditDialog(Reaction rr) {
|
||||
private boolean showReactionEditDialog(JComponent parent, Reaction rr) {
|
||||
final int Select = 0;
|
||||
final int Approve = 1;
|
||||
|
||||
@@ -221,7 +185,7 @@ class ProcessEditor extends JPanel {
|
||||
inhibitorsInput.setText(inhibitorsStr);
|
||||
productsInput.setText(productsStr);
|
||||
|
||||
int result = JOptionPane.showConfirmDialog(null, myPanel,
|
||||
int result = JOptionPane.showConfirmDialog(parent, myPanel,
|
||||
"Reaction details", JOptionPane.OK_CANCEL_OPTION);
|
||||
|
||||
if (result != JOptionPane.OK_OPTION) {
|
||||
@@ -251,8 +215,6 @@ class ProcessEditor extends JPanel {
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: Validate entities names against a regular expression
|
||||
|
||||
rr.reactants.clear();
|
||||
rr.reactants.addAll(reactantsSet);
|
||||
rr.inhibitors.clear();
|
||||
@@ -260,8 +222,6 @@ class ProcessEditor extends JPanel {
|
||||
rr.products.clear();
|
||||
rr.products.addAll(productsSet);
|
||||
|
||||
|
||||
|
||||
opStatus = Approve;
|
||||
}
|
||||
while(opStatus == Select);
|
||||
@@ -272,25 +232,25 @@ class ProcessEditor extends JPanel {
|
||||
public Set<String> getReactantsSet() {
|
||||
HashSet<String> rset = new HashSet<String>();
|
||||
|
||||
for (Reaction rr : reactions)
|
||||
for (Reaction rr : rsProcess.reactions)
|
||||
rset.addAll(rr.getReactantsSet());
|
||||
|
||||
return rset;
|
||||
}
|
||||
|
||||
public void exportToXML(PrintWriter output) {
|
||||
output.println(" <process name=\"" + this.label + "\">");
|
||||
output.println(" <process name=\"" + rsProcess.label + "\">");
|
||||
|
||||
for (Reaction rr : reactions)
|
||||
for (Reaction rr : rsProcess.reactions)
|
||||
rr.exportToXML(output);
|
||||
|
||||
output.println(" </process>");
|
||||
}
|
||||
|
||||
public String toRSSLString() {
|
||||
StringBuilder rsslString = new StringBuilder(" " + this.label + " {\n");
|
||||
StringBuilder rsslString = new StringBuilder(" " + rsProcess.label + " {\n");
|
||||
|
||||
for (Reaction rr : reactions) {
|
||||
for (Reaction rr : rsProcess.reactions) {
|
||||
rsslString.append(rr.toRSSLString());
|
||||
}
|
||||
|
||||
@@ -299,42 +259,25 @@ class ProcessEditor extends JPanel {
|
||||
return rsslString.toString();
|
||||
}
|
||||
|
||||
private void editOptions() {
|
||||
String idRegex = "[a-zA-Z][a-zA-Z_0-9:-]*";
|
||||
boolean idOk = false;
|
||||
void rename(String newLabel) {
|
||||
rsProcess.label = newLabel;
|
||||
outBorder.setTitle(rsProcess.label);
|
||||
|
||||
do {
|
||||
String newLabel = JOptionPane.showInputDialog(this, "Process name", label);
|
||||
if (newLabel == null)
|
||||
return;
|
||||
|
||||
newLabel = newLabel.trim();
|
||||
|
||||
if (!newLabel.matches(idRegex)) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"<html>Process name should start with a letter and may contain only:<br/>" +
|
||||
"letters, numbers, colons (:), underscores (_) and hyphens (-)</html>",
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else {
|
||||
idOk = true;
|
||||
label = newLabel;
|
||||
outBorder.setTitle(label);
|
||||
}
|
||||
}
|
||||
while (!idOk);
|
||||
|
||||
modified = true;
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
// Add new reaction
|
||||
public void addReaction(Reaction rr) {
|
||||
rsProcess.reactions.add(rr);
|
||||
reactionsModel.fireTableDataChanged();
|
||||
}
|
||||
|
||||
private void addReaction() {
|
||||
Reaction rr = new Reaction();
|
||||
if (!showReactionEditDialog(rr))
|
||||
if (!showReactionEditDialog(this, rr))
|
||||
return;
|
||||
|
||||
reactions.add(rr);
|
||||
rsProcess.reactions.add(rr);
|
||||
modified = true;
|
||||
reactionsModel.fireTableDataChanged();
|
||||
}
|
||||
@@ -348,13 +291,13 @@ class ProcessEditor extends JPanel {
|
||||
return;
|
||||
}
|
||||
|
||||
Reaction rr = new Reaction(reactions.get(rIdx));
|
||||
Reaction rr = new Reaction(rsProcess.reactions.get(rIdx));
|
||||
reactionList.clearSelection();
|
||||
if (!showReactionEditDialog(rr)) {
|
||||
if (!showReactionEditDialog(this, rr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reactions.setElementAt(rr, rIdx);
|
||||
rsProcess.reactions.setElementAt(rr, rIdx);
|
||||
modified = true;
|
||||
reactionsModel.fireTableDataChanged();
|
||||
}
|
||||
@@ -368,7 +311,7 @@ class ProcessEditor extends JPanel {
|
||||
return;
|
||||
}
|
||||
|
||||
reactions.remove(rIdx);
|
||||
rsProcess.reactions.remove(rIdx);
|
||||
reactionList.clearSelection();
|
||||
reactionsModel.fireTableDataChanged();
|
||||
modified = true;
|
||||
@@ -398,7 +341,7 @@ class ProcessEditor extends JPanel {
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return reactions.size();
|
||||
return rsProcess.reactions.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
@@ -406,7 +349,7 @@ class ProcessEditor extends JPanel {
|
||||
}
|
||||
|
||||
public Object getValueAt(int row, int column) {
|
||||
Reaction rr = reactions.get(row);
|
||||
Reaction rr = rsProcess.reactions.get(row);
|
||||
|
||||
return switch (column) {
|
||||
case 0 -> rr.reactants;
|
||||
|
||||
@@ -13,8 +13,10 @@ import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Collection;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@@ -26,21 +28,26 @@ public class ReacticsGUI extends JFrame {
|
||||
|
||||
private static final String defaultConfigFileName = "reactics.conf";
|
||||
|
||||
private JFrame window;
|
||||
private JTabbedPane modulePane;
|
||||
private ReactantSetPanel reactantSetPanel;
|
||||
private ReactionSystemEditor reactionSystem;
|
||||
private ContextAutomatonEditor contextAutomaton;
|
||||
private TransitionSystemViewer transitionSystem;
|
||||
private TransitionSystemViewer compressedTransitionSystem;
|
||||
private ReactionSystemEditor reactionSystemEditor;
|
||||
private ContextAutomatonEditor contextAutomatonEditor;
|
||||
private TransitionSystemViewer transitionSystemViewer;
|
||||
private TransitionSystemViewer compressedTransitionSystemViewer;
|
||||
private FormulaEditor formulaEditor;
|
||||
|
||||
private FileSelector fileSelector;
|
||||
|
||||
private ReactionSystem reactionSystem;
|
||||
private ReacticsRuntime reactics;
|
||||
|
||||
|
||||
public ReacticsGUI() {
|
||||
super(ApplicationName);
|
||||
|
||||
reactionSystem = ReactionSystem.getInstance();
|
||||
|
||||
try {
|
||||
reactics = ReacticsRuntime.getInstance();
|
||||
}
|
||||
@@ -74,6 +81,8 @@ public class ReacticsGUI extends JFrame {
|
||||
"however not model checking will be possible.",
|
||||
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
window = this;
|
||||
}
|
||||
|
||||
private void createMenuBar() {
|
||||
@@ -104,7 +113,6 @@ public class ReacticsGUI extends JFrame {
|
||||
importFromRSSL();
|
||||
}
|
||||
});
|
||||
rsslImportItem.setEnabled(false);
|
||||
fileMenu.add(rsslImportItem);
|
||||
|
||||
JMenuItem rsslExportItem = new JMenuItem("Save to RSSL file");
|
||||
@@ -156,23 +164,28 @@ public class ReacticsGUI extends JFrame {
|
||||
// Reaction System Editor
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
reactionSystem = new ReactionSystemEditor();
|
||||
modulePane.addTab("Reaction System", reactionSystem);
|
||||
reactionSystemEditor = new ReactionSystemEditor();
|
||||
modulePane.addTab("Reaction System", reactionSystemEditor);
|
||||
reactionSystem.addObserver(reactionSystemEditor);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
// Context Automaton Editor
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
contextAutomaton = new ContextAutomatonEditor(getSize());
|
||||
modulePane.addTab("Context Automaton", contextAutomaton);
|
||||
contextAutomatonEditor = new ContextAutomatonEditor(getSize());
|
||||
modulePane.addTab("Context Automaton", contextAutomatonEditor);
|
||||
reactionSystem.addObserver(contextAutomatonEditor);
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------
|
||||
// Transition System Viewer
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
JPanel transitionSystemPanel = new JPanel(new BorderLayout());
|
||||
transitionSystem = new TransitionSystemViewer(getSize(), false);
|
||||
transitionSystemPanel.add(transitionSystem, BorderLayout.CENTER);
|
||||
transitionSystemViewer = new TransitionSystemViewer(getSize(), false);
|
||||
transitionSystemPanel.add(transitionSystemViewer, BorderLayout.CENTER);
|
||||
reactionSystem.addObserver(transitionSystemViewer);
|
||||
|
||||
JPanel tsCtrlPanel = new JPanel();
|
||||
JButton tsUpdateBtn = new JButton("Update transition system");
|
||||
@@ -184,7 +197,7 @@ public class ReacticsGUI extends JFrame {
|
||||
JCheckBox tsLockCBox = new JCheckBox("Lock relative nodes positions");
|
||||
tsLockCBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
transitionSystem.lockNodesPositions(tsLockCBox.isSelected());
|
||||
transitionSystemViewer.lockNodesPositions(tsLockCBox.isSelected());
|
||||
}
|
||||
});
|
||||
tsCtrlPanel.add(tsLockCBox);
|
||||
@@ -197,8 +210,9 @@ public class ReacticsGUI extends JFrame {
|
||||
//-----------------------------------------------------------------------------------------
|
||||
|
||||
JPanel compressedTransitionSystemPanel = new JPanel(new BorderLayout());
|
||||
compressedTransitionSystem = new TransitionSystemViewer(getSize(), true);
|
||||
compressedTransitionSystemPanel.add(compressedTransitionSystem, BorderLayout.CENTER);
|
||||
compressedTransitionSystemViewer = new TransitionSystemViewer(getSize(), true);
|
||||
compressedTransitionSystemPanel.add(compressedTransitionSystemViewer, BorderLayout.CENTER);
|
||||
reactionSystem.addObserver(compressedTransitionSystemViewer);
|
||||
|
||||
JPanel ctsCtrlPanel = new JPanel();
|
||||
JButton ctsUpdateBtn = new JButton("Update transition system");
|
||||
@@ -210,7 +224,7 @@ public class ReacticsGUI extends JFrame {
|
||||
JCheckBox ctsLockCBox = new JCheckBox("Lock relative nodes positions");
|
||||
ctsLockCBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
compressedTransitionSystem.lockNodesPositions(ctsLockCBox.isSelected());
|
||||
compressedTransitionSystemViewer.lockNodesPositions(ctsLockCBox.isSelected());
|
||||
}
|
||||
});
|
||||
ctsCtrlPanel.add(ctsLockCBox);
|
||||
@@ -224,20 +238,21 @@ public class ReacticsGUI extends JFrame {
|
||||
|
||||
JPanel formulaEditorPanel = new JPanel();
|
||||
formulaEditorPanel.setLayout(new BorderLayout());
|
||||
formulaEditor = new FormulaEditor();
|
||||
formulaEditor = new FormulaEditor(reactionSystem);
|
||||
reactionSystem.addObserver(formulaEditor);
|
||||
formulaEditorPanel.add(formulaEditor, BorderLayout.CENTER);
|
||||
|
||||
JPanel formulaCtrlPanel = new JPanel();
|
||||
JButton addButton = new JButton("Add formula");
|
||||
addButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) { formulaEditor.addFormula(); }
|
||||
public void actionPerformed(ActionEvent actionEvent) { formulaEditor.addFormula(window); }
|
||||
});
|
||||
formulaCtrlPanel.add(addButton);
|
||||
|
||||
JButton edtButton = new JButton("Edit formula");
|
||||
edtButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
formulaEditor.editFormula();
|
||||
formulaEditor.editFormula(window);
|
||||
}
|
||||
});
|
||||
formulaCtrlPanel.add(edtButton);
|
||||
@@ -304,15 +319,14 @@ public class ReacticsGUI extends JFrame {
|
||||
}
|
||||
|
||||
private boolean isModified() {
|
||||
return reactionSystem.isModified() || contextAutomaton.isModified() || formulaEditor.isModified();
|
||||
return reactionSystemEditor.isModified() || contextAutomatonEditor.isModified();
|
||||
}
|
||||
|
||||
private void clearModificationStatus() {
|
||||
reactionSystem.clearModificationStatus();
|
||||
contextAutomaton.clearModificationStatus();
|
||||
formulaEditor.clearModificationStatus();
|
||||
transitionSystem.clearModificationStatus();
|
||||
compressedTransitionSystem.clearModificationStatus();
|
||||
reactionSystemEditor.clearModificationStatus();
|
||||
contextAutomatonEditor.clearModificationStatus();
|
||||
transitionSystemViewer.clearModificationStatus();
|
||||
compressedTransitionSystemViewer.clearModificationStatus();
|
||||
}
|
||||
|
||||
private void updateReactionSystem() {
|
||||
@@ -335,18 +349,16 @@ public class ReacticsGUI extends JFrame {
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
reactionSystem.notifyObservers();
|
||||
updateReactantSet();
|
||||
transitionSystem.clear();
|
||||
compressedTransitionSystem.clear();
|
||||
formulaEditor.resetFormulasStatus();
|
||||
clearModificationStatus();
|
||||
}
|
||||
|
||||
private void updateReactantSet() {
|
||||
TreeSet<String> rset = new TreeSet<String>();
|
||||
|
||||
rset.addAll(reactionSystem.getReactantsSet());
|
||||
rset.addAll(contextAutomaton.getReactantsSet());
|
||||
rset.addAll(reactionSystemEditor.getReactantsSet());
|
||||
rset.addAll(contextAutomatonEditor.getReactantsSet());
|
||||
rset.remove("");
|
||||
reactantSetPanel.updateReactants(rset);
|
||||
}
|
||||
@@ -355,23 +367,24 @@ public class ReacticsGUI extends JFrame {
|
||||
if (isModified()) {
|
||||
updateReactionSystem();
|
||||
}
|
||||
else if (transitionSystem.isComputed()) {
|
||||
else if (transitionSystemViewer.isComputed()) {
|
||||
// Skip re-computing transition system structure
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String tsStructure = reactics.getTransitionSystemStructure();
|
||||
transitionSystem.updateTransitionSystemStructure(tsStructure);
|
||||
compressedTransitionSystem.updateTransitionSystemStructure(tsStructure);
|
||||
transitionSystemViewer.updateTransitionSystemStructure(tsStructure);
|
||||
compressedTransitionSystemViewer.updateTransitionSystemStructure(tsStructure);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.out.println("IOException: " + ioe.getMessage());
|
||||
System.out.println("[ReactICS] I/O Error: " + ioe.getMessage());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Could not write reaction system structure to a temporary file\n" + ioe.getMessage(),
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
catch (ReacticsRuntimeException rre) {
|
||||
System.out.println("[ReactICS] Runtime Error: " + rre.getMessage());
|
||||
JOptionPane.showMessageDialog(this,
|
||||
rre.getMessage(),
|
||||
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||
@@ -379,15 +392,29 @@ public class ReacticsGUI extends JFrame {
|
||||
}
|
||||
|
||||
private void evaluateFormulas() {
|
||||
Collection<Formula> formulas = formulaEditor.getSelectedFormulas();
|
||||
|
||||
if (isModified())
|
||||
updateReactionSystem();
|
||||
|
||||
Collection<Formula> formulas = formulaEditor.getSelectedFormulas();
|
||||
Path rsslFile = reactics.getRSSLFile();
|
||||
long originalSize = -1;
|
||||
|
||||
try {
|
||||
originalSize = Files.size(rsslFile);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
for (Formula ff : formulas) {
|
||||
try {
|
||||
System.out.println("[ReactICS] Evaluate formula: " + ff.label);
|
||||
|
||||
Files.writeString(rsslFile, ff.toRSSLString() + "\n", StandardCharsets.UTF_8, StandardOpenOption.APPEND);
|
||||
|
||||
ReacticsRuntime.EvalResult result = reactics.evaluateFormula(ff.label);
|
||||
ff.status = result.result();
|
||||
ff.mcTime = result.mcTime() + " s";
|
||||
@@ -405,6 +432,19 @@ public class ReacticsGUI extends JFrame {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
rre.getMessage(),
|
||||
"Reactics Runtime Error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
ff.status = Formula.FormulaStatus.Invalid;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
RandomAccessFile raf = new RandomAccessFile(rsslFile.toFile(), "rw");
|
||||
raf.setLength(originalSize);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||
JOptionPane.showMessageDialog(this, ioe.getMessage(),
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -421,8 +461,8 @@ public class ReacticsGUI extends JFrame {
|
||||
try {
|
||||
PrintWriter xmlOut = new PrintWriter(new FileWriter(outFile));
|
||||
xmlOut.println("<xml version=\"1.0\">");
|
||||
reactionSystem.exportToXML(xmlOut);
|
||||
contextAutomaton.exportToXML(xmlOut);
|
||||
reactionSystemEditor.exportToXML(xmlOut);
|
||||
contextAutomatonEditor.exportToXML(xmlOut);
|
||||
formulaEditor.exportToXML(xmlOut);
|
||||
xmlOut.println("</xml>");
|
||||
xmlOut.flush();
|
||||
@@ -435,86 +475,16 @@ public class ReacticsGUI extends JFrame {
|
||||
}
|
||||
|
||||
private void loadFromXML() {
|
||||
FileNameExtensionFilter rpnFilter = new FileNameExtensionFilter("Reaction System (XML)", "xml");
|
||||
FileNameExtensionFilter fileTypeFilter = new FileNameExtensionFilter("Reaction System (XML)", "xml");
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.addChoosableFileFilter(rpnFilter);
|
||||
fc.addChoosableFileFilter(fileTypeFilter);
|
||||
fc.setAcceptAllFileFilterUsed(true);
|
||||
fc.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||
|
||||
|
||||
if(fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||
File xmlFile = fc.getSelectedFile();
|
||||
|
||||
System.out.println("[ReactICS] Load from XML file: " + xmlFile.getName());
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
transitionSystem.clear();
|
||||
compressedTransitionSystem.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(xmlFile);
|
||||
doc.getDocumentElement().normalize();
|
||||
reactionSystem.loadFromXML(doc);
|
||||
contextAutomaton.loadFromXML(doc);
|
||||
formulaEditor.loadFromXML(doc);
|
||||
updateReactionSystem();
|
||||
}
|
||||
catch(IOException ioe) {
|
||||
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Error reading file: " + xmlFile.getName() + "\n" + ioe.getMessage(),
|
||||
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(ParserConfigurationException pce) {
|
||||
System.err.println("[ReactICS] Parse Configuration Error: " + pce.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, pce.getMessage(),
|
||||
"Parse Configuration Error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(SAXException se) {
|
||||
System.err.println("[ReactICS] SAXException: " + se.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, se.getMessage(),
|
||||
"Parse error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(FileStructureError err) {
|
||||
System.err.println("[ReactICS]: File Structure Error: " + err.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, err.getMessage(),
|
||||
"XML file structure error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(Exception e) {
|
||||
System.out.println("[ReactICS] Error: " + e.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Unexpected error reading file: " + xmlFile.getName() +
|
||||
" " + e.getMessage(),
|
||||
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystem.clear();
|
||||
contextAutomaton.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
|
||||
loadFromXMLFile(xmlFile);
|
||||
setTitle("ReactICS GUI : " + xmlFile.getName());
|
||||
}
|
||||
|
||||
@@ -522,6 +492,109 @@ public class ReacticsGUI extends JFrame {
|
||||
clearModificationStatus();
|
||||
}
|
||||
|
||||
|
||||
private void loadFromXMLFile(File xmlFile) {
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
transitionSystemViewer.clear();
|
||||
compressedTransitionSystemViewer.clear();
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(xmlFile);
|
||||
doc.getDocumentElement().normalize();
|
||||
reactionSystemEditor.loadFromXML(doc);
|
||||
contextAutomatonEditor.loadFromXML(doc);
|
||||
formulaEditor.loadFromXML(doc);
|
||||
updateReactionSystem();
|
||||
}
|
||||
catch(IOException ioe) {
|
||||
System.err.println("[ReactICS] Error: " + ioe.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Error reading file: " + xmlFile.getName() + "\n" + ioe.getMessage(),
|
||||
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(ParserConfigurationException pce) {
|
||||
System.err.println("[ReactICS] Parse Configuration Error: " + pce.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, pce.getMessage(),
|
||||
"Parse Configuration Error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(SAXException se) {
|
||||
System.err.println("[ReactICS] SAXException: " + se.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, se.getMessage(),
|
||||
"Parse error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(FileStructureError err) {
|
||||
System.err.println("[ReactICS]: File Structure Error: " + err.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, err.getMessage(),
|
||||
"XML file structure error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
catch(Exception e) {
|
||||
System.out.println("[ReactICS] Error: " + e.getMessage());
|
||||
|
||||
JOptionPane.showMessageDialog(this, "Unexpected error reading file: " + xmlFile.getName() +
|
||||
" " + e.getMessage(),
|
||||
"Input error", JOptionPane.ERROR_MESSAGE);
|
||||
|
||||
reactionSystemEditor.clear();
|
||||
contextAutomatonEditor.clear();
|
||||
reactantSetPanel.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void importFromRSSL() {
|
||||
FileNameExtensionFilter fileTypeFilter = new FileNameExtensionFilter("Reaction System Specification Language (rs)", "rs");
|
||||
JFileChooser fc = new JFileChooser();
|
||||
fc.addChoosableFileFilter(fileTypeFilter);
|
||||
fc.setAcceptAllFileFilterUsed(true);
|
||||
fc.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||
|
||||
|
||||
if(fc.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
|
||||
File rsslFile = fc.getSelectedFile();
|
||||
|
||||
try {
|
||||
File xmlFile = reactics.convertToXMLFile(rsslFile);
|
||||
loadFromXMLFile(xmlFile);
|
||||
} catch (IOException e) {
|
||||
System.err.println("IOException: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
} catch (ReacticsRuntimeException e) {
|
||||
System.err.println("ReacticsRuntimeException: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
setTitle("ReactICS GUI : " + rsslFile.getName());
|
||||
contextAutomatonEditor.recalculateCoordinates();
|
||||
}
|
||||
|
||||
modulePane.setSelectedIndex(0);
|
||||
clearModificationStatus();
|
||||
}
|
||||
|
||||
|
||||
private void exportToRSSLFile() {
|
||||
File outFile = fileSelector.selectOutputFile(this, new File(System.getProperty("user.dir")),
|
||||
new FileNameExtensionFilter("Reaction System Specification Language (RSSL)", "rs"));
|
||||
@@ -543,13 +616,18 @@ public class ReacticsGUI extends JFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private void importFromRSSL() {
|
||||
//TODO: Import reaction system structure from RSSL file
|
||||
}
|
||||
|
||||
private void exportToISPLFile() {
|
||||
updateReactionSystem();
|
||||
|
||||
if (!reactionSystem.isplTranslationAllowed()) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"Context automaton contains guards for some transitions.\n" +
|
||||
"Current version of ReactICS does not support translation to ISPL format in this case.\n",
|
||||
"Translation is not possible", JOptionPane.INFORMATION_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
File outFile = fileSelector.selectOutputFile(this, new File(System.getProperty("user.dir")),
|
||||
new FileNameExtensionFilter("Interpreted System Programming Language (ISPL)", "ispl"));
|
||||
|
||||
@@ -592,9 +670,9 @@ public class ReacticsGUI extends JFrame {
|
||||
|
||||
private void printRSStructure(PrintWriter outStream) {
|
||||
outStream.println("options { use-context-automaton; make-progressive; };\n");
|
||||
outStream.println(reactionSystem.toRSSLString());
|
||||
outStream.println(contextAutomaton.toRSSLString());
|
||||
outStream.println(formulaEditor.toRSSLString());
|
||||
outStream.println(reactionSystemEditor.toRSSLString());
|
||||
outStream.println(contextAutomatonEditor.toRSSLString());
|
||||
// outStream.println(formulaEditor.toRSSLString());
|
||||
}
|
||||
|
||||
private void showAboutWindow() {
|
||||
|
||||
@@ -153,6 +153,29 @@ public class ReacticsRuntime {
|
||||
throw new ReacticsRuntimeException(errMsg.toString());
|
||||
}
|
||||
|
||||
|
||||
public File convertToXMLFile(File rsslInputFile) throws IOException, ReacticsRuntimeException {
|
||||
File xmlFile = Files.createTempFile("_" + rsslInputFile.getName(), ".xml").toFile();
|
||||
xmlFile.deleteOnExit();
|
||||
|
||||
ProcessBuilder procBuilder = new ProcessBuilder(rctPath + rctRuntime, "-y", rsslInputFile.getAbsolutePath());
|
||||
procBuilder.redirectOutput(new File(xmlFile.getAbsolutePath()));
|
||||
Process proc = procBuilder.start();
|
||||
|
||||
String line;
|
||||
StringBuilder errMsg = new StringBuilder();
|
||||
BufferedReader procErrStr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
|
||||
while ((line = procErrStr.readLine()) != null) {
|
||||
errMsg.append(line).append("\n");
|
||||
}
|
||||
|
||||
if (!errMsg.isEmpty())
|
||||
throw new ReacticsRuntimeException(errMsg.toString());
|
||||
|
||||
return xmlFile;
|
||||
}
|
||||
|
||||
|
||||
record EvalResult(Formula.FormulaStatus result, String mcTime, String totalTime, String memory) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,13 +22,15 @@ import java.util.Vector;
|
||||
* A distributed reaction system contains a number of processes.
|
||||
* Each process contains a list of reactions.
|
||||
*/
|
||||
public class ReactionSystemEditor extends JPanel {
|
||||
private Vector<ProcessEditor> processes = new Vector<ProcessEditor>();
|
||||
public class ReactionSystemEditor extends JPanel implements RSObserver {
|
||||
ReactionSystem rs;
|
||||
private Vector<ProcessEditor> procEditors = new Vector<ProcessEditor>();
|
||||
private JPanel processPanel = new JPanel();
|
||||
private boolean modified = false;
|
||||
|
||||
|
||||
public ReactionSystemEditor() {
|
||||
rs = ReactionSystem.getInstance();
|
||||
|
||||
processPanel.setLayout(new BoxLayout(processPanel, BoxLayout.Y_AXIS));
|
||||
|
||||
final Dimension buttonSize = new Dimension(150, 25);
|
||||
@@ -63,6 +65,16 @@ public class ReactionSystemEditor extends JPanel {
|
||||
}
|
||||
});
|
||||
|
||||
JButton renameButton = new JButton("Rename");
|
||||
renameButton.setMaximumSize(buttonSize);
|
||||
renameButton.setPreferredSize(buttonSize);
|
||||
renameButton.setMaximumSize(buttonSize);
|
||||
renameButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent actionEvent) {
|
||||
renameProcess();
|
||||
}
|
||||
});
|
||||
|
||||
JButton upButton = new JButton("Move up");
|
||||
upButton.setMaximumSize(buttonSize);
|
||||
upButton.setPreferredSize(buttonSize);
|
||||
@@ -89,6 +101,7 @@ public class ReactionSystemEditor extends JPanel {
|
||||
buttonPanel.add(addButton);
|
||||
buttonPanel.add(rmButton);
|
||||
buttonPanel.add(copyButton);
|
||||
buttonPanel.add(renameButton);
|
||||
buttonPanel.add(upButton);
|
||||
buttonPanel.add(downButton);
|
||||
|
||||
@@ -102,23 +115,23 @@ public class ReactionSystemEditor extends JPanel {
|
||||
public boolean isModified() {
|
||||
boolean procModified = false;
|
||||
|
||||
for (ProcessEditor pe : processes)
|
||||
for (ProcessEditor pe : procEditors)
|
||||
procModified |= pe.isModified();
|
||||
|
||||
return modified | procModified;
|
||||
return rs.modified | procModified;
|
||||
}
|
||||
|
||||
public void clearModificationStatus() {
|
||||
for (ProcessEditor pe : processes)
|
||||
for (ProcessEditor pe : procEditors)
|
||||
pe.clearModificationStatus();
|
||||
|
||||
modified = false;
|
||||
rs.modified = false;
|
||||
}
|
||||
|
||||
public Set<String> getReactantsSet() {
|
||||
HashSet<String> rset = new HashSet<String>();
|
||||
|
||||
for (ProcessEditor pe : processes)
|
||||
for (ProcessEditor pe : procEditors)
|
||||
rset.addAll(pe.getReactantsSet());
|
||||
|
||||
return rset;
|
||||
@@ -127,20 +140,20 @@ public class ReactionSystemEditor extends JPanel {
|
||||
public void exportToXML(PrintWriter output) {
|
||||
output.println(" <reaction-system>");
|
||||
|
||||
for (ProcessEditor process : processes)
|
||||
for (ProcessEditor process : procEditors)
|
||||
process.exportToXML(output);
|
||||
|
||||
output.println(" </reaction-system>");
|
||||
}
|
||||
|
||||
public void loadFromXML(Document input) throws ReactionSystemStructureError {
|
||||
NodeList rsSextions = input.getElementsByTagName("reaction-system");
|
||||
NodeList rsSections = input.getElementsByTagName("reaction-system");
|
||||
|
||||
if (rsSextions.getLength() == 0 || rsSextions.getLength() > 1) {
|
||||
if (rsSections.getLength() == 0 || rsSections.getLength() > 1) {
|
||||
throw new ReactionSystemStructureError("An XML file should contain a single reaction system description.");
|
||||
}
|
||||
|
||||
NodeList processList = rsSextions.item(0).getChildNodes();
|
||||
NodeList processList = rsSections.item(0).getChildNodes();
|
||||
|
||||
for (int idx=0; idx<processList.getLength(); ++idx) {
|
||||
Node processNode = processList.item(idx);
|
||||
@@ -149,10 +162,10 @@ public class ReactionSystemEditor extends JPanel {
|
||||
continue;
|
||||
|
||||
String procName = processNode.getAttributes().getNamedItem("name").getNodeValue();
|
||||
ProcessEditor processEditor = new ProcessEditor(procName);
|
||||
ProcessEditor processEditor = new ProcessEditor(rs.createProcess(procName));
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------
|
||||
// Reactins details
|
||||
// Reactions details
|
||||
//----------------------------------------------------------------------------------------------------------
|
||||
|
||||
NodeList reactionList = processNode.getChildNodes();
|
||||
@@ -194,7 +207,7 @@ public class ReactionSystemEditor extends JPanel {
|
||||
processEditor.addReaction(reaction);
|
||||
}
|
||||
|
||||
processes.add(processEditor);
|
||||
procEditors.add(processEditor);
|
||||
processPanel.add(processEditor);
|
||||
}
|
||||
|
||||
@@ -204,7 +217,7 @@ public class ReactionSystemEditor extends JPanel {
|
||||
public String toRSSLString() {
|
||||
StringBuilder rsString = new StringBuilder("reactions {\n");
|
||||
|
||||
for (ProcessEditor pe : processes) {
|
||||
for (ProcessEditor pe : procEditors) {
|
||||
rsString.append(pe.toRSSLString());
|
||||
}
|
||||
|
||||
@@ -215,116 +228,177 @@ public class ReactionSystemEditor extends JPanel {
|
||||
|
||||
public void clear() {
|
||||
processPanel.removeAll();
|
||||
processes.clear();
|
||||
procEditors.clear();
|
||||
rs.clearProcesses();
|
||||
}
|
||||
|
||||
private void createProcess() {
|
||||
ProcessEditor newProcess = new ProcessEditor();
|
||||
processes.add(newProcess);
|
||||
processPanel.add(newProcess);
|
||||
modified = true;
|
||||
ProcessEditor newProcEdt = new ProcessEditor(rs.createProcess());
|
||||
procEditors.add(newProcEdt);
|
||||
processPanel.add(newProcEdt);
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void createProcess(String label) {
|
||||
ProcessEditor newProcess = new ProcessEditor(label);
|
||||
processes.add(newProcess);
|
||||
processPanel.add(newProcess);
|
||||
modified = true;
|
||||
ProcessEditor newProcEdt = new ProcessEditor(rs.createProcess(label));
|
||||
procEditors.add(newProcEdt);
|
||||
processPanel.add(newProcEdt);
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void removeProcesses() {
|
||||
Vector<ProcessEditor> toRemove = new Vector<ProcessEditor>();
|
||||
for (ProcessEditor edt : processes) {
|
||||
for (ProcessEditor edt : procEditors) {
|
||||
if (edt.isSelected()) {
|
||||
toRemove.add(edt);
|
||||
}
|
||||
}
|
||||
|
||||
if (toRemove.size() == processes.size()) {
|
||||
if (toRemove.size() == procEditors.size()) {
|
||||
JOptionPane.showMessageDialog(this, "There should be at least a single process in the system.",
|
||||
"Warning", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
for (ProcessEditor edt : toRemove) {
|
||||
processPanel.remove(edt);
|
||||
processes.remove(edt);
|
||||
if (rs.removeProcess(edt.getProcess())) {
|
||||
processPanel.remove(edt);
|
||||
procEditors.remove(edt);
|
||||
}
|
||||
else {
|
||||
JOptionPane.showMessageDialog(this, "Process " + edt.getLabel() +
|
||||
" appears in a formula or a context automaton guard.\n" +
|
||||
"Update them before removing the process.",
|
||||
"Warning", JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
modified = true;
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void copyProcesses() {
|
||||
Vector<ProcessEditor> toBeCopied = new Vector<ProcessEditor>();
|
||||
|
||||
for (ProcessEditor edt : processes) {
|
||||
for (ProcessEditor edt : procEditors) {
|
||||
if (edt.isSelected()) {
|
||||
toBeCopied.add(edt);
|
||||
}
|
||||
}
|
||||
|
||||
for (ProcessEditor edt : toBeCopied) {
|
||||
ProcessEditor newEdt = new ProcessEditor(edt);
|
||||
ProcessEditor newEdt = new ProcessEditor(rs.copyProcess(edt.getProcess()));
|
||||
processPanel.add(newEdt);
|
||||
processes.add(newEdt);
|
||||
procEditors.add(newEdt);
|
||||
}
|
||||
|
||||
modified = true;
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void renameProcess() {
|
||||
ProcessEditor toRename = null;
|
||||
boolean fail = false;
|
||||
|
||||
for (ProcessEditor edt : procEditors) {
|
||||
if (edt.isSelected()) {
|
||||
if (toRename == null) {
|
||||
toRename = edt;
|
||||
}
|
||||
else {
|
||||
fail = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fail || toRename == null) {
|
||||
JOptionPane.showMessageDialog(this, "Select a single process to rename.", "Select process", JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
String idRegex = "[a-zA-Z][a-zA-Z_0-9:-]*";
|
||||
boolean idOk = false;
|
||||
|
||||
do {
|
||||
String newLabel = JOptionPane.showInputDialog(this, "Process name", toRename.getProcess().label);
|
||||
if (newLabel == null)
|
||||
return;
|
||||
|
||||
newLabel = newLabel.trim();
|
||||
|
||||
if (!newLabel.matches(idRegex)) {
|
||||
JOptionPane.showMessageDialog(this,
|
||||
"<html>Process name should start with a letter and may contain only:<br/>" +
|
||||
"letters, numbers, colons (:), underscores (_) and hyphens (-)</html>",
|
||||
"Error", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
else {
|
||||
idOk = true;
|
||||
rs.renameProcess(toRename.getProcess(), newLabel);
|
||||
toRename.rename(newLabel);
|
||||
rs.notifyObservers();
|
||||
}
|
||||
}
|
||||
while (!idOk);
|
||||
|
||||
}
|
||||
|
||||
private void moveSelectedUp() {
|
||||
Vector<Integer> toBeMovedIds = new Vector<Integer>();
|
||||
for (int i=0; i<processes.size(); ++i) {
|
||||
if (processes.elementAt(i).isSelected())
|
||||
for (int i = 0; i< procEditors.size(); ++i) {
|
||||
if (procEditors.elementAt(i).isSelected())
|
||||
toBeMovedIds.add(i);
|
||||
}
|
||||
|
||||
for (int pos : toBeMovedIds) {
|
||||
if (pos == 0 || processes.elementAt(pos-1).isSelected())
|
||||
if (pos == 0 || procEditors.elementAt(pos-1).isSelected())
|
||||
continue;
|
||||
|
||||
Collections.swap(processes, pos, pos-1);
|
||||
Collections.swap(procEditors, pos, pos-1);
|
||||
}
|
||||
|
||||
processPanel.removeAll();
|
||||
|
||||
for (ProcessEditor edt : processes) {
|
||||
for (ProcessEditor edt : procEditors) {
|
||||
processPanel.add(edt);
|
||||
}
|
||||
|
||||
modified = true;
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
private void moveSelectedDown() {
|
||||
Vector<Integer> toBeMovedIds = new Vector<Integer>();
|
||||
|
||||
for (int i=processes.size()-1; i>=0; --i) {
|
||||
if (processes.elementAt(i).isSelected())
|
||||
for (int i = procEditors.size()-1; i>=0; --i) {
|
||||
if (procEditors.elementAt(i).isSelected())
|
||||
toBeMovedIds.add(i);
|
||||
}
|
||||
|
||||
for (int pos : toBeMovedIds) {
|
||||
if (pos == processes.size()-1 || processes.elementAt(pos+1).isSelected())
|
||||
if (pos == procEditors.size()-1 || procEditors.elementAt(pos+1).isSelected())
|
||||
continue;
|
||||
|
||||
Collections.swap(processes, pos, pos+1);
|
||||
Collections.swap(procEditors, pos, pos+1);
|
||||
}
|
||||
|
||||
processPanel.removeAll();
|
||||
|
||||
for (ProcessEditor edt : processes) {
|
||||
for (ProcessEditor edt : procEditors) {
|
||||
processPanel.add(edt);
|
||||
}
|
||||
|
||||
modified = true;
|
||||
rs.modified = true;
|
||||
revalidate();
|
||||
}
|
||||
|
||||
public void onRSUpdate() {
|
||||
repaint();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
||||
public class TransitionSystemViewer extends JPanel {
|
||||
public class TransitionSystemViewer extends JPanel implements RSObserver {
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Visual configuration settings
|
||||
@@ -266,6 +266,10 @@ public class TransitionSystemViewer extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
public void onRSUpdate() {
|
||||
clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -353,7 +357,6 @@ class TSState {
|
||||
String.join("<br/>", blocks) +
|
||||
"</html>";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user