Java tutorial
/** * * vsim * * This program is distributed under the terms of the GNU General Public License * The license is included in license.txt * * @author: Alejandro Vera * */ package cl.almejo.vsim.gui; import cl.almejo.vsim.Messages; import cl.almejo.vsim.circuit.Circuit; import cl.almejo.vsim.circuit.CircuitCanvas; import cl.almejo.vsim.circuit.CircuitEvent; import cl.almejo.vsim.circuit.CircuitStateListener; import cl.almejo.vsim.gates.Gate; import cl.almejo.vsim.gui.actions.*; import cl.almejo.vsim.gui.actions.state.ActionToolHelper; import cl.almejo.vsim.gui.actions.state.GateToolHelper; import cl.almejo.vsim.gui.components.ZoomChanger; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.swing.*; import javax.swing.border.BevelBorder; import javax.swing.filechooser.FileNameExtensionFilter; import java.awt.*; import java.awt.event.*; import java.io.File; import java.io.IOException; public class SimWindow extends JFrame implements ComponentListener, WindowListener, MouseListener, MouseMotionListener, CircuitStateListener { private static final Logger LOGGER = LoggerFactory.getLogger(SimWindow.class); private static final long serialVersionUID = 1L; private final CircuitCanvas _canvas; private final JTabbedPane _displaysPane; private Circuit _circuit; private ActionToolHelper _toolHelper = ActionToolHelper.CURSOR; static final KeyStroke ACCELERATOR_NEW = KeyStroke.getKeyStroke(KeyEvent.VK_N, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_OPEN = KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_SAVE = KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_SAVE_AS = KeyStroke.getKeyStroke("control shift S"); static final KeyStroke ACCELERATOR_QUIT = KeyStroke.getKeyStroke(KeyEvent.VK_Q, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_CUT = KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_COPY = KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_PASTE = KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_UNDO = KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_REDO = KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK); static final KeyStroke ACCELERATOR_SHOW_GRID = KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); static final KeyStroke ACCELERATOR_PREFERENCES = KeyStroke.getKeyStroke(KeyEvent.VK_P, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK); private final WindowAction NEW_ACTION = new NewAction(Messages.t("action.new"), Messages.t("action.new.description"), "new.png", ACCELERATOR_NEW, this); private final WindowAction OPEN_ACTION = new OpenAction(Messages.t("action.open"), Messages.t("action.open.description"), "open.png", ACCELERATOR_OPEN, this); private final WindowAction SAVE_ACTION = new SaveAction(Messages.t("action.save"), Messages.t("action.save.description"), "save.png", ACCELERATOR_SAVE, this); private final WindowAction SAVE_AS_ACTION = new SaveAsAction(Messages.t("action.saveas"), Messages.t("action.saveas.description"), null, ACCELERATOR_SAVE_AS, this); private final WindowAction QUIT_ACTION = new QuitAction(Messages.t("action.quit"), Messages.t("action.quit.description"), null, ACCELERATOR_QUIT, this); private final WindowAction CUT_ACTION = new CutAction(Messages.t("action.cut"), Messages.t("action.cut.description"), "cut.png", ACCELERATOR_CUT, this); private final WindowAction COPY_ACTION = new CopyAction(Messages.t("action.copy"), Messages.t("action.copy.description"), "copy.png", ACCELERATOR_COPY, this); private final WindowAction PASTE_ACTION = new PasteAction(Messages.t("action.paste"), Messages.t("action.paste.description"), "paste.png", ACCELERATOR_PASTE, this); private final WindowAction UNDO_ACTION = new UndoAction(Messages.t("action.undo"), Messages.t("action.undo.description"), "undo.png", ACCELERATOR_UNDO, this); private final WindowAction REDO_ACTION = new RedoAction(Messages.t("action.redo"), Messages.t("action.redo.description"), "redo.png", ACCELERATOR_REDO, this); private final WindowAction PREFERENCES_ACTION = new PreferencesAction(Messages.t("action.preferences"), Messages.t("action.preferences.description"), null, ACCELERATOR_PREFERENCES, this); private final WindowAction SHOW_GRID_ACTION = new ShowGridAction(Messages.t("action.grid.show"), Messages.t("action.grid.show.description"), null, ACCELERATOR_SHOW_GRID, this); private final WindowAction START_ACTION = new StartStopSimulationAction(Messages.t("action.start"), Messages.t("action.start.description"), "play.png", null, this); private final WindowAction PAUSE_ACTION = new StartStopSimulationAction(Messages.t("action.pause"), Messages.t("action.pause.description"), "pause.png", null, this); private final WindowAction CLONE_WINDOW_ACTION = new CloneWindowAction(Messages.t("action.window.clone"), Messages.t("action.window.clone.description"), null, null, this); private final WindowAction CLOSE_ACTION = new CloseWindowAction(Messages.t("action.window.close"), Messages.t("action.window.close.description"), null, null, this); private final WindowAction ONLINE_HELP_ACTION = new OnlineHelpAction(Messages.t("action.help.online"), Messages.t("action.help.online.description"), null, null, this); private final WindowAction ABOUT_ACTION = new AboutAction(Messages.t("action.help.about"), Messages.t("action.help.about.description"), null, null, this); private final WindowAction CURSOR_TOOL_ACTION = new ToolAction(Messages.t("action.tool.cursor"), Messages.t("action.tool.cursor.description"), "cursor.png", null, this, ActionToolHelper.CURSOR); private final WindowAction MOVE_VIEWPORT_TOOL_ACTION = new ToolAction(Messages.t("action.tool.move.viewport"), Messages.t("action.tool.move.viewport.description"), "move-viewport.png", null, this, ActionToolHelper.MOVE_VIEWPORT); private final WindowAction WIRES_TOOL_ACTION = new ToolAction(Messages.t("action.tool.wires"), Messages.t("action.tool.wires.description"), "wires.png", null, this, ActionToolHelper.WIRES); private final WindowAction AND2_TOOL_ACTION = new ToolAction(Messages.t("action.tool.and2"), Messages.t("action.tool.and2.description"), "and2.png", null, this, new GateToolHelper(Gate.AND2)); private final WindowAction AND3_TOOL_ACTION = new ToolAction(Messages.t("action.tool.and3"), Messages.t("action.tool.and3.description"), "and3.png", null, this, new GateToolHelper(Gate.AND3)); private final WindowAction AND4_TOOL_ACTION = new ToolAction(Messages.t("action.tool.and4"), Messages.t("action.tool.and4.description"), "and4.png", null, this, new GateToolHelper(Gate.AND4)); private final WindowAction XOR2_TOOL_ACTION = new ToolAction(Messages.t("action.tool.xor2"), Messages.t("action.tool.xor2.description"), "xor2.png", null, this, new GateToolHelper(Gate.XOR2)); private final WindowAction XOR3_TOOL_ACTION = new ToolAction(Messages.t("action.tool.xor3"), Messages.t("action.tool.xor3.description"), "xor3.png", null, this, new GateToolHelper(Gate.XOR3)); private final WindowAction XOR4_TOOL_ACTION = new ToolAction(Messages.t("action.tool.xor4"), Messages.t("action.tool.xor4.description"), "xor4.png", null, this, new GateToolHelper(Gate.XOR4)); private final WindowAction OR2_TOOL_ACTION = new ToolAction(Messages.t("action.tool.or2"), Messages.t("action.tool.or2.description"), "or2.png", null, this, new GateToolHelper(Gate.OR2)); private final WindowAction OR3_TOOL_ACTION = new ToolAction(Messages.t("action.tool.or3"), Messages.t("action.tool.or3.description"), "or3.png", null, this, new GateToolHelper(Gate.OR3)); private final WindowAction OR4_TOOL_ACTION = new ToolAction(Messages.t("action.tool.or4"), Messages.t("action.tool.or4.description"), "or4.png", null, this, new GateToolHelper(Gate.OR4)); private final WindowAction NOT_TOOL_ACTION = new ToolAction(Messages.t("action.tool.not"), Messages.t("action.tool.not.description"), "not.png", null, this, new GateToolHelper(Gate.NOT)); private final WindowAction CLOCK_TOOL_ACTION = new ToolAction(Messages.t("action.tool.clock"), Messages.t("action.tool.clock.description"), "clock.png", null, this, new GateToolHelper(Gate.CLOCK)); private final WindowAction FLIP_FLOP_DATA_TOOL_ACTION = new ToolAction(Messages.t("action.tool.flip.flop.data"), Messages.t("action.tool.flip.flop.data.description"), "flipflopdata.png", null, this, new GateToolHelper(Gate.FLIP_FLOP_DATA)); private final WindowAction TRISTATE_TOOL_ACTION = new ToolAction(Messages.t("action.tool.tristate"), Messages.t("action.tool.tristate.description"), "tristate.png", null, this, new GateToolHelper(Gate.TRISTATE)); private final WindowAction SEVEN_SEGMENTS_DISPLAY_TOOL_ACTION = new ToolAction( Messages.t("action.tool.seven.segments.display"), Messages.t("action.tool.seven.segments.display.description"), "seven-segments-display.png", null, this, new GateToolHelper(Gate.SEVEN_SEGMENTS_DISPLAY)); private final WindowAction SEVEN_SEGMENTS_DISPLAY_DOUBLE_TOOL_ACTION = new ToolAction( Messages.t("action.tool.seven.segments.display.double"), Messages.t("action.tool.seven.segments.display.double.description"), "seven-segments-display-double.png", null, this, new GateToolHelper(Gate.SEVEN_SEGMENTS_DISPLAY_DOUBLE)); private final WindowAction LED_TOOL_ACTION = new ToolAction(Messages.t("action.tool.led"), Messages.t("action.tool.led.description"), "led.png", null, this, new GateToolHelper(Gate.LED)); private final WindowAction TIME_DIAGRAM_TOOL_ACTION = new ToolAction(Messages.t("action.tool.time.diagram"), Messages.t("action.tool.time.diagram.description"), "time-diagram.png", null, this, new GateToolHelper(Gate.TIME_DIAGRAM)); private final WindowAction SWITCH_TOOL_ACTION = new ToolAction(Messages.t("action.tool.switch"), Messages.t("action.tool.switch.description"), "switch.png", null, this, new GateToolHelper(Gate.SWITCH)); private static JFileChooser OPEN_FILE_CHOOSER; private static JFileChooser SAVE_AS_FILE_CHOOSER; static { OPEN_FILE_CHOOSER = new JFileChooser(); OPEN_FILE_CHOOSER.setDialogTitle(Messages.t("file.open")); FileNameExtensionFilter vsimFilter = new FileNameExtensionFilter(Messages.t("file.open.filter.description"), "json"); OPEN_FILE_CHOOSER.addChoosableFileFilter(vsimFilter); OPEN_FILE_CHOOSER.setFileFilter(vsimFilter); SAVE_AS_FILE_CHOOSER = new JFileChooser(); SAVE_AS_FILE_CHOOSER.setDialogTitle(Messages.t("file.save")); SAVE_AS_FILE_CHOOSER.addChoosableFileFilter(vsimFilter); SAVE_AS_FILE_CHOOSER.setFileFilter(vsimFilter); } private static class CenterCanvasButton extends JPanel { @Override protected void paintComponent(Graphics graphics) { Graphics2D graphics2D = (Graphics2D) graphics; Dimension size = getSize(); graphics2D.setColor(Color.BLACK); graphics2D.drawOval(2, 2, (int) size.getWidth() - 3, (int) size.getHeight() - 3); graphics2D.drawLine((int) size.getWidth() / 2 + 1, 0, (int) size.getWidth() / 2 + 1, (int) size.getHeight()); graphics2D.drawLine(0, (int) size.getHeight() / 2 + 1, (int) size.getWidth(), (int) size.getHeight() / 2 + 1); } } public SimWindow(Circuit circuit) { _circuit = circuit; _circuit.addCircuitEventListener(this); _canvas = new CircuitCanvas(_circuit); setBounds(100, 100, 800, 800); _displaysPane = new JTabbedPane(); CanvasScrollPane scrollPane = new CanvasScrollPane(_canvas); CenterCanvasButton panel = new CenterCanvasButton(); panel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { SimWindow.this.getCanvas().center(); } }); scrollPane.addCorner(panel); JSplitPane rightSplitpane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, scrollPane, _displaysPane); rightSplitpane.setOneTouchExpandable(true); rightSplitpane.setDividerLocation(600); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JSplitPane(JSplitPane.VERTICAL_SPLIT, getToolsPane(), new JPanel()), rightSplitpane); getContentPane().add(splitPane, BorderLayout.CENTER); JPanel statusBar = getStatusBar(); statusBar.add(new ZoomChanger(_canvas)); getContentPane().add(statusBar, BorderLayout.SOUTH); setVisible(true); setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); addComponentListener(this); addWindowListener(this); _canvas.addMouseListener(this); _canvas.setZoom(1.0); _canvas.addMouseMotionListener(this); _canvas.resizeViewport(); addMenu(); addMainToolbar(); updateActionStates(); updateTitle(); } private JPanel getStatusBar() { JPanel statusBar = new JPanel(); statusBar.setBorder(new BevelBorder(BevelBorder.LOWERED)); return statusBar; } private void addMenu() { JMenuBar menuBar = new JMenuBar(); JMenu menu = newMenu(Messages.t("menu.file"), KeyEvent.VK_F, menuBar); menu.add(newMenuItem(NEW_ACTION, Messages.c("menu.file.new.mnemonic"))); menu.add(newMenuItem(OPEN_ACTION, Messages.c("menu.file.open.mnemonic"))); menu.add(newMenuItem(SAVE_ACTION, Messages.c("menu.file.save.mnemonic"))); menu.add(newMenuItem(SAVE_AS_ACTION, Messages.c("menu.file.saveas.mnemonic"))); menu.addSeparator(); menu.add(newMenuItem(QUIT_ACTION, Messages.c("menu.file.quit.mnemonic"))); menu = newMenu(Messages.t("menu.edit"), KeyEvent.VK_F, menuBar); menu.add(newMenuItem(CUT_ACTION, Messages.c("menu.edit.cut.mnemonic"))); menu.add(newMenuItem(COPY_ACTION, Messages.c("menu.edit.copy.mnemonic"))); menu.add(newMenuItem(PASTE_ACTION, Messages.c("menu.edit.paste.mnemonic"))); menu.add(newMenuItem(UNDO_ACTION, Messages.c("menu.edit.undo.mnemonic"))); menu.add(newMenuItem(REDO_ACTION, Messages.c("menu.edit.redo.mnemonic"))); menu.add(newMenuItem(PREFERENCES_ACTION, Messages.c("menu.edit.preferences.mnemonic"))); menu = newMenu(Messages.t("menu.view"), KeyEvent.VK_V, menuBar); menu.add(newCheckboxMenuItem(SHOW_GRID_ACTION, Messages.c("menu.view.grid.mnemonic"), true)); menu = newMenu(Messages.t("menu.tools"), KeyEvent.VK_H, menuBar); menu.add(newMenuItem(CURSOR_TOOL_ACTION, Messages.c("menu.tool.cursor.mnemonic"))); menu.add(newMenuItem(MOVE_VIEWPORT_TOOL_ACTION, Messages.c("menu.tool.move.viewport.mnemonic"))); menu.add(newMenuItem(WIRES_TOOL_ACTION, Messages.c("menu.tool.wires.mnemonic"))); menu.add(newMenuItem(AND2_TOOL_ACTION, Messages.c("menu.tool.and2.mnemonic"))); menu.add(newMenuItem(AND3_TOOL_ACTION, Messages.c("menu.tool.and3.mnemonic"))); menu.add(newMenuItem(AND4_TOOL_ACTION, Messages.c("menu.tool.and4.mnemonic"))); menu.add(newMenuItem(OR2_TOOL_ACTION, Messages.c("menu.tool.or2.mnemonic"))); menu.add(newMenuItem(OR3_TOOL_ACTION, Messages.c("menu.tool.or3.mnemonic"))); menu.add(newMenuItem(OR4_TOOL_ACTION, Messages.c("menu.tool.or4.mnemonic"))); menu.add(newMenuItem(XOR2_TOOL_ACTION, Messages.c("menu.tool.or2.mnemonic"))); menu.add(newMenuItem(XOR3_TOOL_ACTION, Messages.c("menu.tool.or3.mnemonic"))); menu.add(newMenuItem(XOR4_TOOL_ACTION, Messages.c("menu.tool.or4.mnemonic"))); menu.add(newMenuItem(CLOCK_TOOL_ACTION, Messages.c("menu.tool.clock.mnemonic"))); menu.add(newMenuItem(NOT_TOOL_ACTION, Messages.c("menu.tool.not.mnemonic"))); menu.add(newMenuItem(FLIP_FLOP_DATA_TOOL_ACTION, Messages.c("menu.tool.flip.flop.data.mnemonic"))); menu.add(newMenuItem(TRISTATE_TOOL_ACTION, Messages.c("menu.tool.tristate.mnemonic"))); menu.add(newMenuItem(SEVEN_SEGMENTS_DISPLAY_TOOL_ACTION, Messages.c("menu.tool.seven.segments.display.mnemonic"))); menu.add(newMenuItem(SEVEN_SEGMENTS_DISPLAY_DOUBLE_TOOL_ACTION, Messages.c("menu.tool.seven.segments.display.double.mnemonic"))); menu.add(newMenuItem(LED_TOOL_ACTION, Messages.c("menu.tool.led.mnemonic"))); menu.add(newMenuItem(TIME_DIAGRAM_TOOL_ACTION, Messages.c("menu.tool.time.diagram.mnemonic"))); menu.add(newMenuItem(SWITCH_TOOL_ACTION, Messages.c("menu.tool.switch.mnemonic"))); menu = newMenu(Messages.t("menu.simulation"), KeyEvent.VK_F, menuBar); menu.add(newMenuItem(START_ACTION, Messages.c("menu.simulation.start.mnemonic"))); menu.add(newMenuItem(PAUSE_ACTION, Messages.c("menu.simulation.pause.mnemonic"))); menu = newMenu(Messages.t("menu.window"), KeyEvent.VK_F, menuBar); menu.add(newMenuItem(CLONE_WINDOW_ACTION, Messages.c("menu.window.clone.mnemonic"))); menu.add(newMenuItem(CLOSE_ACTION, Messages.c("menu.window.close.mnemonic"))); menu = newMenu(Messages.t("menu.help"), KeyEvent.VK_F, menuBar); menu.add(newMenuItem(ONLINE_HELP_ACTION, Messages.c("menu.help.online.mnemonic"))); menu.add(newMenuItem(ABOUT_ACTION, Messages.c("menu.help.about.mnemonic"))); setJMenuBar(menuBar); } private JMenuItem newMenuItem(WindowAction action, char mnemonic) { JMenuItem menuItem = new JMenuItem(action); menuItem.setMnemonic(mnemonic); return menuItem; } private JMenuItem newCheckboxMenuItem(WindowAction action, char mnemonic, boolean selected) { JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(action); menuItem.setMnemonic(mnemonic); menuItem.setSelected(selected); return menuItem; } private JMenu newMenu(String title, int mnemonic, JMenuBar menuBar) { JMenu menu = new JMenu(title); menu.setMnemonic(mnemonic); menuBar.add(menu); return menu; } private void addMainToolbar() { JToolBar toolBar = new JToolBar(); toolBar.add(newToolbarButton(NEW_ACTION)); toolBar.add(newToolbarButton(OPEN_ACTION)); toolBar.add(newToolbarButton(SAVE_ACTION)); toolBar.addSeparator(); toolBar.add(newToolbarButton(UNDO_ACTION)); toolBar.add(newToolbarButton(REDO_ACTION)); toolBar.add(newToolbarButton(CUT_ACTION)); toolBar.add(newToolbarButton(COPY_ACTION)); toolBar.add(newToolbarButton(PASTE_ACTION)); toolBar.addSeparator(); ButtonGroup group = new ButtonGroup(); toolBar.add(newGrouppedButton(START_ACTION, group)); toolBar.add(newGrouppedButton(PAUSE_ACTION, group)); getContentPane().add(toolBar, BorderLayout.NORTH); } private JPanel getToolsPane() { JPanel panel = new JPanel(); panel.setLayout(new GridLayout(0, 2)); ButtonGroup group = new ButtonGroup(); JToggleButton button = newGrouppedButton(CURSOR_TOOL_ACTION, group); button.setSelected(true); panel.add(button); panel.add(newGrouppedButton(MOVE_VIEWPORT_TOOL_ACTION, group)); panel.add(newGrouppedButton(WIRES_TOOL_ACTION, group)); panel.add(newGrouppedButton(AND2_TOOL_ACTION, group)); panel.add(newGrouppedButton(AND3_TOOL_ACTION, group)); panel.add(newGrouppedButton(AND4_TOOL_ACTION, group)); panel.add(newGrouppedButton(OR2_TOOL_ACTION, group)); panel.add(newGrouppedButton(OR3_TOOL_ACTION, group)); panel.add(newGrouppedButton(OR4_TOOL_ACTION, group)); panel.add(newGrouppedButton(XOR2_TOOL_ACTION, group)); panel.add(newGrouppedButton(XOR3_TOOL_ACTION, group)); panel.add(newGrouppedButton(XOR4_TOOL_ACTION, group)); panel.add(newGrouppedButton(NOT_TOOL_ACTION, group)); panel.add(newGrouppedButton(CLOCK_TOOL_ACTION, group)); panel.add(newGrouppedButton(FLIP_FLOP_DATA_TOOL_ACTION, group)); panel.add(newGrouppedButton(SEVEN_SEGMENTS_DISPLAY_TOOL_ACTION, group)); panel.add(newGrouppedButton(SEVEN_SEGMENTS_DISPLAY_DOUBLE_TOOL_ACTION, group)); panel.add(newGrouppedButton(TRISTATE_TOOL_ACTION, group)); panel.add(newGrouppedButton(LED_TOOL_ACTION, group)); panel.add(newGrouppedButton(TIME_DIAGRAM_TOOL_ACTION, group)); panel.add(newGrouppedButton(SWITCH_TOOL_ACTION, group)); return panel; } private JButton newToolbarButton(Action action) { JButton button = new JButton(); button.setAction(action); button.setText(""); return button; } private JToggleButton newGrouppedButton(Action action, ButtonGroup group) { JToggleButton button = new JToggleButton(); button.setAction(action); button.setText(""); group.add(button); return button; } public void undo() { _circuit.undo(); } public void redo() { _circuit.redo(); } @Override public void componentResized(ComponentEvent e) { _canvas.resizeViewport(); } @Override public void componentMoved(ComponentEvent e) { } @Override public void componentShown(ComponentEvent e) { } @Override public void componentHidden(ComponentEvent e) { } @Override public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { quit(); } @Override public void windowClosed(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { } @Override public void windowDeiconified(WindowEvent e) { } @Override public void windowActivated(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } @Override public void mouseClicked(MouseEvent event) { if (SwingUtilities.isRightMouseButton(event)) { _toolHelper.rightClicked(this, event); return; } if (event.getClickCount() >= 2) { _toolHelper.mouseDoubleClicked(this, event); return; } _toolHelper.mouseClicked(this, event); } @Override public void mousePressed(MouseEvent event) { _toolHelper.mouseDown(this, event); } @Override public void mouseReleased(MouseEvent event) { _toolHelper.mouseUp(this, event); } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } @Override public void mouseDragged(MouseEvent event) { _toolHelper.mouseDragged(this, event); } @Override public void mouseMoved(MouseEvent event) { _toolHelper.mouseMoved(this, event); } public void setToolHelper(ActionToolHelper toolHelper) { _toolHelper = toolHelper; } public void undoableConnect(int xi, int yi, int xf, int yf) { _circuit.undoableConnect(xi, yi, xf, yf); } public Circuit getCircuit() { return _circuit; } public void undoableDisconnect(int x, int y) { _circuit.undoableDisconnect(x, y); } private void updateActionStates() { updateStartPause(_circuit); updateUndoRedo(_circuit); updateFileOperationActions(); updateCutCopyPaste(); } private void updateCutCopyPaste() { CUT_ACTION.setEnabled(false); COPY_ACTION.setEnabled(false); PASTE_ACTION.setEnabled(false); } private void updateFileOperationActions() { SAVE_ACTION.setEnabled(_circuit.isModified()); } @Override public void onPause(CircuitEvent event) { updateStartPause(event.getCircuit()); } @Override public void onResume(CircuitEvent event) { updateStartPause(event.getCircuit()); } @Override public void onChanged(CircuitEvent event) { SAVE_ACTION.setEnabled(_circuit.isModified()); updateUndoRedo(event.getCircuit()); updateTitle(); } public void updateTitle() { setTitle(_circuit.getName() + " " + (_circuit.isModified() ? "* " : "") + "| " + Messages.t("main.title")); } @Override public void onUndo(CircuitEvent event) { updateUndoRedo(event.getCircuit()); } @Override public void onRedo(CircuitEvent event) { updateUndoRedo(event.getCircuit()); } @Override public void onSaved(CircuitEvent event) { updateTitle(); SAVE_ACTION.setEnabled(_circuit.isModified()); } private void updateUndoRedo(Circuit circuit) { UNDO_ACTION.setEnabled(circuit.canUndo()); REDO_ACTION.setEnabled(circuit.canRedo()); } private void updateStartPause(Circuit circuit) { PAUSE_ACTION.setEnabled(circuit.isSimulationRunning()); START_ACTION.setEnabled(!circuit.isSimulationRunning()); } public void load() { if (_circuit != null && _circuit.isModified()) { int replace = askSaveNow(); if (replace == JOptionPane.CANCEL_OPTION) { return; } if (replace == JOptionPane.YES_OPTION) { if (saveAs() == JOptionPane.CANCEL_OPTION) { LOGGER.info("save cancelled by user."); } } } try { if (OPEN_FILE_CHOOSER.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File file = OPEN_FILE_CHOOSER.getSelectedFile(); setCircuit(Circuit.fromJSon(FileUtils.readFileToString(file), file.getPath())); LOGGER.info("Loaded: " + file.getName() + "."); return; } LOGGER.info("load cancelled by user."); } catch (IOException exception) { exception.printStackTrace(); } } public int saveAs() { SAVE_AS_FILE_CHOOSER.setSelectedFile(new File(_circuit.getName())); if (SAVE_AS_FILE_CHOOSER.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) { LOGGER.info("save cancelled by user."); return 0; } File file = SAVE_AS_FILE_CHOOSER.getSelectedFile(); if (file.exists()) { if (askOverwrite() != JOptionPane.YES_OPTION) { return JOptionPane.CANCEL_OPTION; } } _circuit.setName(file.getPath()); updateTitle(); save(file.getPath()); LOGGER.info("saved: " + file.getPath()); return JOptionPane.OK_OPTION; } public void save(String path) { try { FileUtils.writeStringToFile(new File(path), _circuit.toJSon()); _circuit.setSaved(); } catch (IOException e) { e.printStackTrace(); } } private int askOverwrite() { return JOptionPane.showConfirmDialog(this, Messages.t("file.replace.message"), Messages.t("file.replace.title"), JOptionPane.YES_NO_OPTION); } private int askSaveNow() { return JOptionPane.showConfirmDialog(this, Messages.t("file.save.now.message"), Messages.t("file.save.now.title"), JOptionPane.YES_NO_CANCEL_OPTION); } public void setCircuit(Circuit circuit) { if (circuit == null) { return; } _circuit.remove(_canvas); _circuit.removeCircuitEventListener(this); _circuit = circuit; _circuit.addCircuitEventListener(this); _canvas.setCircuit(_circuit); _circuit.setSaved(); updateTitle(); } public void addDisplayPanel(String name, JPanel displayPanel) { _displaysPane.add(name, displayPanel); } public CircuitCanvas getCanvas() { return _canvas; } public void quit() { if (askSureToQuit() == JOptionPane.YES_OPTION) { if (_circuit != null && _circuit.isModified()) { int saveBeforeQuit = askSaveBeforeQuit(); if (saveBeforeQuit == JOptionPane.CANCEL_OPTION) { return; } if (saveBeforeQuit == JOptionPane.YES_OPTION) { if (saveAs() == JOptionPane.CANCEL_OPTION) { LOGGER.info("save cancelled by user."); return; } } } if (_circuit != null) { _circuit.remove(_canvas); } System.exit(0); } } private int askSaveBeforeQuit() { return JOptionPane.showConfirmDialog(this, Messages.t("action.save.before.quit.message"), Messages.t("action.save.before.quit.title"), JOptionPane.YES_NO_CANCEL_OPTION); } private int askSureToQuit() { return JOptionPane.showConfirmDialog(this, Messages.t("action.quit.message"), Messages.t("action.quit.title"), JOptionPane.YES_NO_OPTION); } }