package pipe.actions.gui; import pipe.controllers.PetriNetController; import pipe.controllers.RateParameterController; import pipe.controllers.application.PipeApplicationController; import pipe.gui.AbstractDatum; import pipe.gui.RateEditorPanel; import pipe.historyActions.MultipleEdit; import pipe.historyActions.component.AddPetriNetObject; import pipe.historyActions.component.DeletePetriNetObject; import pipe.utilities.gui.GuiUtils; import uk.ac.imperial.pipe.exceptions.InvalidRateException; import uk.ac.imperial.pipe.exceptions.PetriNetComponentException; import uk.ac.imperial.pipe.exceptions.PetriNetComponentNotFoundException; import uk.ac.imperial.pipe.models.petrinet.FunctionalRateParameter; import uk.ac.imperial.pipe.models.petrinet.PetriNet; import uk.ac.imperial.pipe.models.petrinet.RateParameter; import javax.swing.*; import javax.swing.undo.UndoableEdit; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @SuppressWarnings("serial") public class SpecifyRateParameterAction extends GuiAction { private static final Logger LOGGER = Logger.getLogger(SpecifyRateParameterAction.class.getName()); private final PipeApplicationController pipeApplicationController; private RateEditorPanel rateEditorPanel; private JDialog guiDialog; public SpecifyRateParameterAction(PipeApplicationController pipeApplicationController) { super("Rate Parameter", "Specify Rate Parameters (alt-R)", KeyEvent.VK_R, InputEvent.ALT_DOWN_MASK); this.pipeApplicationController = pipeApplicationController; } /** * Pops up with an editor for the token rates if there is an active petri net * * @param e event */ @Override public void actionPerformed(ActionEvent e) { if (pipeApplicationController.getActivePetriNetController() != null) { buildGuiClasses(); showGui(); } } private void buildGuiClasses() { rateEditorPanel = new RateEditorPanel(pipeApplicationController.getActivePetriNetController()); guiDialog = new RateDialog(); } private void showGui() { guiDialog.setSize(600, 200); guiDialog.setLocationRelativeTo(null); rateEditorPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); rateEditorPanel.setOpaque(true); JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(Box.createHorizontalGlue()); JButton ok = new JButton("OK"); ok.addActionListener((ActionListener) guiDialog); buttonPane.add(ok); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); JButton cancel = new JButton("Cancel"); cancel.addActionListener((ActionListener) guiDialog); buttonPane.add(cancel); guiDialog.add(rateEditorPanel, BorderLayout.CENTER); guiDialog.add(buttonPane, BorderLayout.PAGE_END); rateEditorPanel.setVisible(true); guiDialog.setVisible(true); } private class RateDialog extends JDialog implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("OK")) { if (rateEditorPanel.isDataValid()) { updateFromTable(rateEditorPanel.getTableData()); removeDeletedData(rateEditorPanel.getDeletedData()); setVisible(false); } } else if (e.getActionCommand().equals("Cancel")) { setVisible(false); } } /** * Removes any data deleted from the table if it was in the Petri net * when table loaded */ private void removeDeletedData(Iterable<RateEditorPanel.RateModel.Datum> deletedData) { PetriNetController petriNetController = pipeApplicationController.getActivePetriNetController(); PetriNet petriNet = petriNetController.getPetriNet(); List<UndoableEdit> undoableEdits = new LinkedList<>(); for (RateEditorPanel.RateModel.Datum datum : deletedData) { if (rateEditorPanel.isExistingRateParameter(datum)) { try { RateParameter rateParameter = petriNet.getComponent(datum.id, RateParameter.class); UndoableEdit historyItem = new DeletePetriNetObject(rateParameter, petriNet); undoableEdits.add(historyItem); petriNet.removeRateParameter(rateParameter); } catch (PetriNetComponentNotFoundException e) { LOGGER.log(Level.SEVERE, e.getMessage()); } } } if (undoableEdits.size() > 0) { registerUndoEvent(new MultipleEdit(undoableEdits)); } } /** * Performs an update on the table data items * * @param data list of data in the table */ private void updateFromTable(Iterable<RateEditorPanel.RateModel.Datum> data) { PetriNetController petriNetController = pipeApplicationController.getActivePetriNetController(); List<UndoableEdit> undoableEdits = new LinkedList<>(); for (RateEditorPanel.RateModel.Datum modified : data) { if (rateEditorPanel.isExistingRateParameter(modified)) { AbstractDatum initial = modified.initial; if (!modified.equals(initial) && modified.hasBeenSet()) { try { RateParameterController rateController = petriNetController.getRateParameterController(initial.id); rateController.startMultipleEdits(); rateController.setId(modified.id); rateController.setRate(modified.expression); rateController.finishMultipleEdits(); } catch (PetriNetComponentNotFoundException | InvalidRateException e) { GuiUtils.displayErrorMessage(null, e.getMessage()); } } } else if (modified.hasBeenSet()) { RateParameter rateParameter = new FunctionalRateParameter(modified.expression, modified.id, modified.id); try { petriNetController.getPetriNet().add(rateParameter); undoableEdits.add(new AddPetriNetObject(rateParameter, petriNetController.getPetriNet())); } catch (PetriNetComponentException e) { GuiUtils.displayErrorMessage(null, e.getMessage()); } } } if (undoableEdits.size() > 0) { registerUndoEvent(new MultipleEdit(undoableEdits)); } } } }