示例#1
0
/**
 * @author Danilo Pianini
 * @param <T>
 */
public class Perspective<T> extends JPanel implements ChangeListener, ActionListener {

  private static final long serialVersionUID = -6074331788924400019L;
  private static final FileFilter XML_FILTER =
      new FileNameExtensionFilter(r(Res.ALCHEMIST_XML), "xml");

  private final UpperBar bar;

  private File currentDirectory = new File(System.getProperty("user.home"));
  private SwingOutputMonitor<T> main;
  private RandomEngine rand;
  private final SimControlPanel scp = SimControlPanel.createControlPanel(null);
  private final JEffectsTab<T> effectsTab;
  private transient ISimulation<T> sim;
  private final StatusBar status;
  private File xml;

  @SuppressWarnings("rawtypes")
  private static final Class<? extends GraphicalOutputMonitor> DEFAULT_MONITOR_CLASS =
      Generic2DDisplay.class;

  private static final String DEFAULT_MONITOR_PACKAGE = "it.unibo.alchemist.boundary.monitors.";

  private static String r(final Res res) {
    return Res.get(res);
  }

  /** Builds a new SAPERE perspective. */
  public Perspective() {
    super();
    setLayout(new BorderLayout());

    bar = new UpperBar(scp);
    add(bar, BorderLayout.NORTH);
    bar.addActionListener(this);
    bar.addChangeListener(this);

    status = new StatusBar();
    status.setText(r(Res.SAPERE_PERSPECTIVE));
    add(status, BorderLayout.SOUTH);

    effectsTab = new JEffectsTab<>();
    effectsTab.addLinksToggleActionListener(this);
    effectsTab.setEnabled(false);

    bar.registerTab(effectsTab);

    setMainDisplay(new Generic2DDisplay<T>());
  }

  private void dispose() {
    if (main != null) {
      main.dispose();
      if (sim != null) {
        sim.removeOutputMonitor(main);
      }
      remove((Component) main);
    }
    main = null;
    sim = null;
    effectsTab.setMonitor(null);
  }

  @Override
  public void actionPerformed(final ActionEvent e) {
    if (Commands.OPEN.equalsToString(e.getActionCommand())) {
      openXML();
    } else if (Commands.PARALLEL.equalsToString(e.getActionCommand())) {
      process(true);
    } else if (Commands.PROCESS.equalsToString(e.getActionCommand())) {
      process(false);
    } else if (Commands.DICE.equalsToString(e.getActionCommand())) {
      setRandom();
    } else if (SimControlCommand.PLAY.equalsToString(e.getActionCommand())) {
      sim.play();
      bar.setPlay(true);
    } else if (SimControlCommand.PAUSE.equalsToString(e.getActionCommand())) {
      sim.pause();
      bar.setPlay(false);
    } else if (SimControlCommand.STEP.equalsToString(e.getActionCommand())) {
      sim.play();
      sim.pause();
    } else if (SimControlCommand.STOP.equalsToString(e.getActionCommand())) {
      sim.stop();
      bar.setFileOK(true);
    } else if (Commands.PAINT_LINKS.equalsToString(e.getActionCommand())) {
      main.setDrawLinks(effectsTab.isDrawingLinks()); // side.isDrawingLinks());
    } else if (Commands.REACTIVITY.equalsToString(e.getActionCommand())) {
      switch (bar.getReactivityStatus()) {
        case MAX_REACTIVITY:
          main.setStep(1);
          main.setRealTime(false);
          break;
        case REAL_TIME:
          main.setRealTime(true);
          main.setStep(1);
          break;
        case USER_SELECTED:
          main.setStep(bar.getReactivity());
          main.setRealTime(false);
          break;
        default:
          break;
      }
    } else {
      dispose();
    }
  }

  @SuppressWarnings("unchecked")
  private void createMonitor() {
    String monitorClassName = sim.getEnvironment().getPreferredMonitor();
    Class<? extends SwingOutputMonitor<T>> monitorClass;
    if (monitorClassName == null) {
      monitorClass = (Class<? extends SwingOutputMonitor<T>>) DEFAULT_MONITOR_CLASS;
    } else {
      if (!monitorClassName.contains(".")) {
        monitorClassName = DEFAULT_MONITOR_PACKAGE + monitorClassName;
      }
      try {
        monitorClass = (Class<SwingOutputMonitor<T>>) Class.forName(monitorClassName);
      } catch (final ClassNotFoundException e) {
        L.warn(e);
        monitorClass = (Class<? extends SwingOutputMonitor<T>>) DEFAULT_MONITOR_CLASS;
      }
    }
    try {
      final SwingOutputMonitor<T> display = monitorClass.getConstructor().newInstance();
      setMainDisplay(display);
    } catch (InstantiationException
        | IllegalAccessException
        | IllegalArgumentException
        | InvocationTargetException
        | NoSuchMethodException
        | SecurityException e) {
      L.error(e);
    }
  }

  private void openXML() {
    final JFileChooser fc = new JFileChooser();
    fc.setMultiSelectionEnabled(false);
    fc.setFileFilter(XML_FILTER);
    fc.setCurrentDirectory(currentDirectory);
    final int returnVal = fc.showOpenDialog(null);
    if (returnVal == JFileChooser.APPROVE_OPTION) {
      xml = fc.getSelectedFile();
      currentDirectory = fc.getSelectedFile().getParentFile();
      if (xml.exists() && xml.getName().endsWith("xml")) {
        status.setText(r(Res.READY_TO_PROCESS) + " " + xml.getAbsolutePath());
        status.setOK();
        if (sim != null) {
          sim.stop();
        }
        bar.setFileOK(true);
      } else {
        status.setText(r(Res.FILE_NOT_VALID) + " " + xml.getAbsolutePath());
        status.setNo();
        bar.setFileOK(false);
      }
    }
  }

  private void process(final boolean parallel) {
    if (sim != null) {
      sim.stopAndWait();
    }
    try {
      sim = null;
      final Future<Result<T>> fenv = EnvironmentBuilder.build(new FileInputStream(xml));
      final IEnvironment<T> env = fenv.get().getEnvironment();
      rand = fenv.get().getRandomEngine();
      sim = new Simulation<>(env, new DoubleTime(Double.POSITIVE_INFINITY), parallel);
      bar.setSimulation(sim);
      scp.setSimulation(sim);
      final Thread simThread = new Thread(sim);
      createMonitor();
      simThread.start();
      final TimeStepMonitor<T> tm = bar.getTimeMonitor();
      sim.addOutputMonitor(tm);
      bar.setRandom(rand.getSeed());
      bar.setFileOK(true);
      bar.setProcessOK(true);
      effectsTab.setEnabled(true);
      status.setOK();
      status.setText(r(Res.FILE_PROCESSED) + ": " + xml.getAbsolutePath());
    } catch (Exception e) {
      processError(e);
    }
  }

  private void processError(final Throwable e) {
    SwingUtilities.invokeLater(
        () -> {
          bar.setFileOK(false);
          bar.setProcessOK(false);
          status.setText(r(Res.FILE_NOT_VALID) + " " + xml.getAbsolutePath());
          status.setNo();
          L.error(e);
        });
  }

  private void setMainDisplay(final SwingOutputMonitor<T> gom) {
    if (main != null) {
      sim.removeOutputMonitor(main);
      gom.setStep(main.getStep());
      gom.setRealTime(main.isRealTime());
      remove((Component) main);
      main.dispose();
    }
    main = gom;
    if (sim != null) {
      new Thread(() -> sim.addOutputMonitor(main)).start();
    }
    add((Component) main, BorderLayout.CENTER);
    revalidate();
    effectsTab.setMonitor(gom);
    gom.setDrawLinks(effectsTab.isDrawingLinks());
  }

  private void setRandom() {
    if (rand != null) {
      try {
        rand.setSeed(bar.getRandomText());
        status.setOK();
        status.setText(r(Res.RANDOM_REINIT_SUCCESS) + ": " + rand.getSeed());
      } catch (final NumberFormatException e) {
        status.setNo();
        status.setText(r(Res.RANDOM_REINIT_FAIL) + ": " + r(Res.IS_NOT_AN_INTEGER));
      }
    } else {
      status.setNo();
      status.setText(r(Res.RANDOM_REINIT_FAIL) + ": RandomEngine " + r(Res.IS_NOT_INITIALIZED_YET));
    }
  }

  @Override
  public void stateChanged(final ChangeEvent e) {
    if (bar.getReactivityStatus().equals(Status.USER_SELECTED)) {
      main.setStep(bar.getReactivity());
    }
  }
}