package nl.fontys.sofa.limo.view.action; import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFormattedTextField; import nl.fontys.sofa.limo.domain.component.SupplyChain; import nl.fontys.sofa.limo.simulation.Simulator; import nl.fontys.sofa.limo.simulation.SimulatorTask; import nl.fontys.sofa.limo.simulation.SimulatorTaskListener; import nl.fontys.sofa.limo.view.chain.ChainBuilder; import nl.fontys.sofa.limo.view.chain.ChainGraphScene; import nl.fontys.sofa.limo.view.topcomponent.ResultTopComponent; import nl.fontys.sofa.limo.view.util.LIMOResourceBundle; import nl.fontys.sofa.limo.view.widget.BasicWidget; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; import org.openide.util.ContextAwareAction; import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.Utilities; import org.openide.util.WeakListeners; import org.openide.util.actions.Presenter; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; /** * Action which is responsible for running the simulation. * <p> * It looks in the global lookup which {@link org.openide.windows.TopComponent} * currently is active and retrieves the * {@link nl.fontys.sofa.limo.view.chain.ChainGraphScene} from it. * <p> * The validation of the chain is done by the * {@link nl.fontys.sofa.limo.view.chain.ChainBuilder} and if this succeeds the * simulation is run and the corresponding * {@link org.openide.windows.TopComponent} is disabled. * * @author Sebastiaan Heijmann */ @ActionID(category = "File", id = "nl.fontys.sofa.limo.view.action.SimulateAction") @ActionRegistration(lazy = false, displayName = "NOT-USED") @ActionReferences({ @ActionReference(path = "Shortcuts", name = "D-F5")}) public final class SimulateAction extends AbstractAction implements Presenter.Toolbar, ContextAwareAction, LookupListener, SimulatorTaskListener { public static final int DEFAULT_NUM_RUNS = 10000; private final JFormattedTextField inputRunsTF; private final Lookup lkp; private final Lookup.Result<ChainGraphScene> result; private final Lookup.Result<BasicWidget> widgets; private final JButton button = new JButton(this); /** * Constructor sets the input text field from where to get the number of * simulation runs from. * * @param inputRunsTF the formatted text field. */ public SimulateAction(JFormattedTextField inputRunsTF) { this.inputRunsTF = inputRunsTF; this.lkp = Utilities.actionsGlobalContext(); this.result = lkp.lookupResult(ChainGraphScene.class); this.result.addLookupListener(WeakListeners.create(LookupListener.class, this, result)); this.widgets = lkp.lookupResult(BasicWidget.class); this.widgets.addLookupListener(WeakListeners.create(LookupListener.class, this, widgets)); } public SimulateAction() { this.inputRunsTF = null; this.lkp = Utilities.actionsGlobalContext(); this.result = lkp.lookupResult(ChainGraphScene.class); this.result.addLookupListener(WeakListeners.create(LookupListener.class, this, result)); this.widgets = lkp.lookupResult(BasicWidget.class); this.widgets.addLookupListener(WeakListeners.create(LookupListener.class, this, widgets)); } public SimulateAction(Lookup lkp) { this.inputRunsTF = null; this.lkp = lkp; this.result = lkp.lookupResult(ChainGraphScene.class); this.result.addLookupListener(WeakListeners.create(LookupListener.class, this, result)); this.widgets = lkp.lookupResult(BasicWidget.class); this.widgets.addLookupListener(WeakListeners.create(LookupListener.class, this, widgets)); } /** * {@inheritDoc} * <p> * Invokes the simulate action. */ @Override public void actionPerformed(ActionEvent e) { int numberOfRuns = DEFAULT_NUM_RUNS; Object input = null; if (inputRunsTF != null && inputRunsTF.isEditValid()) { input = inputRunsTF.getValue(); } if (input != null) { numberOfRuns = (int) input; } performSimulation(result.allInstances(), numberOfRuns); } @Override public void taskFinished(final SimulatorTask task) { result.allInstances().stream().map((scene) -> { TopComponent tc = (TopComponent) scene.getParent(); tc.makeBusy(false); scene.setEnabled(true); return scene; }).forEach((scene) -> { scene.setBackground(Color.WHITE); }); if (task.getCancelled().get()) { return; } //for (final SimulationResult simResult : task.getResults()) { WindowManager.getDefault().invokeWhenUIReady(() -> { try { ResultTopComponent rtc = new ResultTopComponent(task.getResults()); rtc.open(); rtc.requestActive(); } catch (InstantiationException ex) { Exceptions.printStackTrace(ex); } }); //} } /** * {@inheritDoc} * <p> * Creates a new simulation button to invoke this action from. * * @return the component as a {@link javax.swing.JButton}. */ @Override public Component getToolbarPresenter() { button.setIcon(new ImageIcon(getClass().getClassLoader().getResource("icons/gui/Process.png"))); button.setText(LIMOResourceBundle.getString("SIMULATE")); button.setOpaque(false); button.setBorder(null); return button; } private void performSimulation(Collection<? extends ChainGraphScene> scenes, int numberOfRuns) { List<SupplyChain> chain = new ArrayList<>(); for (ChainGraphScene scene : scenes) { ChainBuilder chainBuilder = scene.getChainBuilder(); if (chainBuilder != null && chainBuilder.validate()) { TopComponent tc = (TopComponent) scene.getParent(); SupplyChain supplyChain = chainBuilder.getSupplyChain(); chain.add(supplyChain); tc.makeBusy(true); scene.setEnabled(false); scene.setBackground(Color.LIGHT_GRAY); } else { DialogDisplayer.getDefault().notify(new NotifyDescriptor.Message( LIMOResourceBundle.getString("CHAIN_VALIDATION_FAILED"), NotifyDescriptor.WARNING_MESSAGE)); return; } } SupplyChain[] c = chain.toArray(new SupplyChain[chain.size()]); SimulatorTask task = Simulator.simulate(numberOfRuns, c); task.addTaskListener(this); } @Override public Action createContextAwareInstance(Lookup lkp) { return new SimulateAction(lkp); } @Override public void resultChanged(LookupEvent le) { for (ChainGraphScene scene : result.allInstances()) { if (scene.getChainBuilder().validate()) { button.setEnabled(true); return; } } if (result.allInstances().size() > 0) { button.setEnabled(false); } } }