/* * 2014 - removed SAVE ALL button and command since it was not working */ package edu.princeton.toy; import java.awt.*; import java.awt.event.*; import java.io.*; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import javax.swing.*; import javax.swing.border.*; import javax.swing.event.*; import edu.princeton.swing.*; import edu.princeton.swing.text.*; import edu.princeton.toy.lang.*; public class TFrame extends JFrame implements ActionListener, ChangeListener, TextListener, ListSelectionListener, TVirtualMachine.ExecutionController { private static final String CLASS_STRING = TFrame.class.toString(); /** * The displacement in the x direction between cascaded windows. */ public static final int CASCADE_X = 24; /** * The displacement in the y direction between cascaded windows. */ public static final int CASCADE_Y = 24; public static final String NEW_COMMAND = CLASS_STRING + "#newCommand"; public static final String OPEN_COMMAND = CLASS_STRING + "#openCommand"; public static final String OPEN_EXAMPLE_COMMAND = CLASS_STRING + "#openExampleCommand"; public static final String CLOSE_COMMAND = CLASS_STRING + "#closeCommand"; public static final String REVERT_COMMAND = CLASS_STRING + "#revertCommand"; public static final String SAVE_COMMAND = CLASS_STRING + "#saveCommand"; // public static final String SAVE_ALL_COMMAND = CLASS_STRING + "#saveAllCommand"; public static final String SAVE_AS_COMMAND = CLASS_STRING + "#saveAsCommand"; public static final String QUIT_COMMAND = CLASS_STRING + "#quitCommand"; public static final String EDIT_MODE_COMMAND = CLASS_STRING + "#editModeCommand"; public static final String DEBUG_MODE_COMMAND = CLASS_STRING + "#debugModeCommand"; public static final String SIM_MODE_COMMAND = CLASS_STRING + "#simModeCommand"; public static final String LOOK_COMMAND = CLASS_STRING + "#lookCommand"; public static final String LOAD_COMMAND = CLASS_STRING + "#loadCommand"; public static final String RESET_COMMAND = CLASS_STRING + "#resetCommand"; public static final String STEP_COMMAND = CLASS_STRING + "#stepCommand"; public static final String RUN_COMMAND = CLASS_STRING + "#runCommand"; public static final String INTERRUPT_COMMAND = CLASS_STRING + "#interruptCommand"; public static final String ENTER_COMMAND = CLASS_STRING + "#enterCommand"; public static final String OPEN_STDIN_COMMAND = CLASS_STRING + "#openStdinCommand"; public static final String SAVE_STDIN_COMMAND = CLASS_STRING + "#saveStdinCommand"; public static final String SAVE_STDOUT_COMMAND = CLASS_STRING + "#saveStdoutCommand"; public static final String SAVE_MEM_DUMP_COMMAND = CLASS_STRING + "#saveMemDumpCommand"; public static final String SAVE_CORE_DUMP_COMMAND = CLASS_STRING + "#saveCoreDumpCommand"; public static final String WORKSPACE_COMMAND = CLASS_STRING + "#workspaceCommand"; public static final String CHECK_SYNTAX_COMMAND = CLASS_STRING + "#checkSyntaxCommand"; public static final String FUNCTION_COMMAND = CLASS_STRING + "#functionCommand"; public static final String CHANGE_EXECUTION_COMMAND = CLASS_STRING + "#changeExecutionCommand"; public static final String CLEAR_ODOMETER_COMMAND = CLASS_STRING + "#clearOdometerCommand"; public static final String CHANGE_CHECKING_COMMAND = CLASS_STRING + "#changeCheckingCommand"; public static final String HIDE_WARNINGS_COMMAND = CLASS_STRING + "#hideWarningsCommand"; private static final List FRAMES = new ArrayList(); private static Object FRAMES_ARRAY[] = new Object[20]; private static final Runner RUNNER = new Runner(); private static final Toolkit TOOLKIT = Toolkit.getDefaultToolkit(); private static final ExtensionFileFilter TOY_FILE_FILTER = new ExtensionFileFilter("toy", "Toy Program File"); private static final ExtensionFileFilter TXT_FILE_FILTER = new ExtensionFileFilter("txt", "Text File"); private static final ListModel BLANK_LIST_MODEL = new DefaultListModel(); private static final Border PADDING_BORDER = new EmptyBorder(2, 2, 2, 2); private TFrameAction newAction, openAction, openExampleAction, closeAction, revertAction, saveAction, saveAsAction, saveAllAction, quitAction; private TFrameAction editModeAction, debugModeAction, simModeAction, lookAction, loadAction, resetAction, stepAction, runAction, interruptAction, enterAction; private TFrameAction openStdinAction, saveStdinAction, saveStdoutAction, saveMemDumpAction, saveCoreDumpAction; private TFrameAction checkSyntaxAction, functionAction; private boolean isNew; private TProgramDocument program; private boolean programChanged; private String oldTitle; private boolean wasSaved; private File file; private String savedText; private ArrayList warningSelectionDots, warningSelectionMarks; private boolean hasFatalError; private TVirtualMachine virtualMachine; private TWordBuffer tempBuffer; private ActionedUndoManager undoManager; private TProgramDocument.WarningInfoStruct previousWarnings; private TProgramDocument.WarningInfoStruct currentWarnings; private String mode; private ButtonModel menuEditModeButtonModel; private ButtonModel menuDebugModeButtonModel; private ButtonModel menuSimModeButtonModel; private ButtonGroup menuModeButtonGroup; private JMenu workspaceMenu; private int workspaceIndex; private JPanel cardPanel; private CardLayout cardLayout; private JSplitPane editPane; private JSplitPane leftEditPane; private JPanel bottomLeftEditPane; private PHighlightedTextArea editTextArea; private TReferencePane editReferencePane; private TStdinPane editStdinPane; private PScrollablePanel warningListPanel; private PWrappedList warningList; private PList warningTallyList; private JSplitPane debugPane; private PHighlightedTextArea debugTextArea; private Object odometerLock; private PTextField stepsTakenTextField; private int stepsTaken; private PTextField elapsedTimeTextField; private int elapsedTime; private JTabbedPane rightDebugPane; private TReferencePane debugReferencePane; private TStdinPane debugStdinPane; private TStdoutPane debugStdoutPane; private TCorePane debugCorePane; private JSplitPane simPane; private JSplitPane leftSimPane; private TSimMachinePane simMachinePane; private TSimDetailPane simDetailPane; private JTabbedPane rightSimPane; private TSimMemPane simMemPane; private TSimStdinPane simStdinPane; private TSimStdoutPane simStdoutPane; private TSimStdin2Pane simStdin2Pane; private TSimStdout2Pane simStdout2Pane; private JPanel simPanel; public TFrame() { this(new TProgramDocument(), null); isNew = true; } public TFrame(TProgramDocument program) { this(program, null); } public TFrame(TProgramDocument program, File file) { super(); if (program == null) throw new NullPointerException(); isNew = false; wasSaved = false; this.file = file; savedText = program.getText(); warningSelectionDots = new ArrayList(); warningSelectionMarks = new ArrayList(); this.program = program; program.addTextListener(this); mode = EDIT_MODE_COMMAND; previousWarnings = new TProgramDocument.WarningInfoStruct(); currentWarnings = new TProgramDocument.WarningInfoStruct(); virtualMachine = new TVirtualMachine(); program.reset(virtualMachine); virtualMachine.addChangeListener(this); tempBuffer = new TWordBuffer(); odometerLock = new Object(); stepsTaken = 0; elapsedTime = 0; setIconImage(TMain.getFrameIcon()); // Prepare the undoManager undoManager = new ActionedUndoManager(); program.addUndoableEditListener(undoManager); // Prepare the actions int menuShortcutKeyMask = TOOLKIT.getMenuShortcutKeyMask(); newAction = new TFrameAction( "New", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_NEW_ICON ), KeyEvent.VK_N, KeyStroke.getKeyStroke(KeyEvent.VK_N, menuShortcutKeyMask), NEW_COMMAND ); openAction = new TFrameAction( "Open...", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_OPEN_ICON ), KeyEvent.VK_O, KeyStroke.getKeyStroke(KeyEvent.VK_O, menuShortcutKeyMask), OPEN_COMMAND ); openExampleAction = new TFrameAction( "Open Example Program...", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_OPEN_EXAMPLE_ICON ), KeyEvent.VK_E, KeyStroke.getKeyStroke(KeyEvent.VK_E, menuShortcutKeyMask), OPEN_EXAMPLE_COMMAND ); closeAction = new TFrameAction( "Close", null, KeyEvent.VK_C, null, CLOSE_COMMAND ); revertAction = new TFrameAction( "Revert", null, KeyEvent.VK_R, null, REVERT_COMMAND ); saveAction = new TFrameAction( "Save", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SAVE_ICON ), KeyEvent.VK_S, KeyStroke.getKeyStroke(KeyEvent.VK_S, menuShortcutKeyMask), SAVE_COMMAND ); saveAsAction = new TFrameAction( "Save As...", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SAVE_AS_ICON ), KeyEvent.VK_S, KeyStroke.getKeyStroke(KeyEvent.VK_S, menuShortcutKeyMask | ActionEvent.SHIFT_MASK), SAVE_AS_COMMAND ); /* saveAllAction = new TFrameAction( "Save All", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SAVE_ALL_ICON ), KeyEvent.VK_S, null, SAVE_ALL_COMMAND ); */ quitAction = new TFrameAction( "Quit", null, KeyEvent.VK_Q, KeyStroke.getKeyStroke(KeyEvent.VK_Q, menuShortcutKeyMask), QUIT_COMMAND ); editModeAction = new TFrameAction( "Edit Mode", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_EDIT_MODE_ICON_ON ), KeyEvent.VK_E, null, EDIT_MODE_COMMAND ); debugModeAction = new TFrameAction( "Debug Mode", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_DEBUG_MODE_ICON_OFF ), KeyEvent.VK_D, null, DEBUG_MODE_COMMAND ); simModeAction = new TFrameAction( "Sim Mode", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SIM_MODE_ICON_OFF ), KeyEvent.VK_S, null, SIM_MODE_COMMAND ); lookAction = new TFrameAction( "Look", null, KeyEvent.VK_L, null, LOOK_COMMAND ); lookAction.setEnabled(false); loadAction = new TFrameAction( "Load", null, KeyEvent.VK_L, null, LOAD_COMMAND ); loadAction.setEnabled(false); resetAction = new TFrameAction( "Reset", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_RESET_ICON ), KeyEvent.VK_R, null, RESET_COMMAND ); resetAction.setEnabled(false); stepAction = new TFrameAction( "Step", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_STEP_ICON ), KeyEvent.VK_S, null, STEP_COMMAND ); stepAction.setEnabled(false); runAction = new TFrameAction( "Run", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_RUN_ICON ), KeyEvent.VK_R, null, RUN_COMMAND ); runAction.setEnabled(false); interruptAction = new TFrameAction( "Interrupt", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_INTERRUPT_ICON ), KeyEvent.VK_I, null, INTERRUPT_COMMAND ); interruptAction.setEnabled(false); enterAction = new TFrameAction( "Enter", null, KeyEvent.VK_E, null, ENTER_COMMAND ); enterAction.setEnabled(false); openStdinAction = new TFrameAction( "Load File to Stdin...", null, KeyEvent.VK_L, null, OPEN_STDIN_COMMAND ); saveStdinAction = new TFrameAction( "Save Stdin to File...", null, KeyEvent.VK_I, null, SAVE_STDIN_COMMAND ); saveStdoutAction = new TFrameAction( "Save Stdout to File...", null, KeyEvent.VK_O, null, SAVE_STDOUT_COMMAND ); saveStdoutAction.setEnabled(false); saveMemDumpAction = new TFrameAction( "Save Memory Dump to File...", null, KeyEvent.VK_M, null, SAVE_MEM_DUMP_COMMAND ); saveMemDumpAction.setEnabled(false); saveCoreDumpAction = new TFrameAction( "Save Core to File...", null, KeyEvent.VK_C, null, SAVE_CORE_DUMP_COMMAND ); saveCoreDumpAction.setEnabled(false); checkSyntaxAction = new TFrameAction( "Check Syntax", TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_CHECK_SYNTAX_ICON ), KeyEvent.VK_C, KeyStroke.getKeyStroke(KeyEvent.VK_C, menuShortcutKeyMask | ActionEvent.SHIFT_MASK), CHECK_SYNTAX_COMMAND, Boolean.TRUE ); functionAction = new TFrameAction( "Insert Function Comment", null, KeyEvent.VK_F, KeyStroke.getKeyStroke(KeyEvent.VK_F, menuShortcutKeyMask), FUNCTION_COMMAND ); // Prepare the menu JMenuBar menuBar; JMenu menu; JMenuItem menuItem; // Create the menu bar. menuBar = new JMenuBar(); setJMenuBar(menuBar); // Build the file menu. { menu = new JMenu("File"); menu.setMnemonic(KeyEvent.VK_F); menuBar.add(menu); menu.add(newAction.createMenuItem()); menu.add(openAction.createMenuItem()); menu.add(openExampleAction.createMenuItem()); menu.add(closeAction.createMenuItem()); menu.add(revertAction.createMenuItem()); menu.addSeparator(); menu.add(saveAction.createMenuItem()); menu.add(saveAsAction.createMenuItem()); //menu.add(saveAllAction.createMenuItem()); menu.addSeparator(); for (int ctr = 0; ctr < TOptionsFrame.FILE_HISTORY_SIZE; ctr++) { menuItem = TOptionsFrame.FILE_HISTORY_ACTIONS[ctr].createMenuItem(); menu.add(menuItem); } menu.addSeparator(); menu.add(quitAction.createMenuItem()); } { // Build the edit menu menu = new JMenu("Edit"); menu.setMnemonic(KeyEvent.VK_E); menuBar.add(menu); menu.add(undoManager.getUndoAction().createMenuItem()); menu.add(undoManager.getRedoAction().createMenuItem()); menu.addSeparator(); menu.add(ClipboardTargetManager.CUT_ACTION.createMenuItem()); menu.add(ClipboardTargetManager.COPY_ACTION.createMenuItem()); menu.add(ClipboardTargetManager.PASTE_ACTION.createMenuItem()); menu.addSeparator(); menu.add(ClipboardTargetManager.SELECT_ALL_ACTION.createMenuItem()); } { // Build the mode menu menu = new JMenu("Mode"); menu.setMnemonic(KeyEvent.VK_M); menuBar.add(menu); menuModeButtonGroup = new ButtonGroup(); JRadioButtonMenuItem rbMenuItem; rbMenuItem = new JRadioButtonMenuItem(editModeAction); rbMenuItem.setAccelerator(editModeAction.getAccelerator()); rbMenuItem.setSelected(true); menuEditModeButtonModel = rbMenuItem.getModel(); menuModeButtonGroup.add(rbMenuItem); menu.add(rbMenuItem); rbMenuItem = new JRadioButtonMenuItem(debugModeAction); rbMenuItem.setAccelerator(debugModeAction.getAccelerator()); menuDebugModeButtonModel = rbMenuItem.getModel(); menuModeButtonGroup.add(rbMenuItem); menu.add(rbMenuItem); rbMenuItem = new JRadioButtonMenuItem(simModeAction); rbMenuItem.setAccelerator(simModeAction.getAccelerator()); menuSimModeButtonModel = rbMenuItem.getModel(); menuModeButtonGroup.add(rbMenuItem); menu.add(rbMenuItem); menu.addSeparator(); menu.add(resetAction.createMenuItem()); menu.add(stepAction.createMenuItem()); menu.add(runAction.createMenuItem()); menu.add(interruptAction.createMenuItem()); menu.addSeparator(); menu.add(openStdinAction.createMenuItem()); menu.add(saveStdinAction.createMenuItem()); menu.add(saveStdoutAction.createMenuItem()); menu.add(saveMemDumpAction.createMenuItem()); menu.add(saveCoreDumpAction.createMenuItem()); } { // Build a tentative workspace menu menu = new JMenu("Workspace"); menu.setMnemonic(KeyEvent.VK_W); menuBar.add(menu); workspaceMenu = menu; } { // Build a tools menu menu = new JMenu("Tools"); menu.setMnemonic(KeyEvent.VK_T); menuBar.add(menu); menu.add(checkSyntaxAction.createMenuItem()); menu.add(functionAction.createMenuItem()); menu.addSeparator(); menu.add(TOptionsFrame.OPTIONS_ACTION.createMenuItem()); } getContentPane().setLayout(new BorderLayout()); { // Prepare the toolbar JToolBar toolbar = new JToolBar(); toolbar.add(newAction).setToolTipText("New"); toolbar.add(openAction).setToolTipText("Open..."); toolbar.add(openExampleAction).setToolTipText("Open Example..."); toolbar.add(saveAction).setToolTipText("Save"); toolbar.add(saveAsAction).setToolTipText("Save As..."); //toolbar.add(saveAllAction).setToolTipText("Save All"); toolbar.addSeparator(); toolbar.add(ClipboardTargetManager.CUT_ACTION).setToolTipText("Cut"); toolbar.add(ClipboardTargetManager.COPY_ACTION).setToolTipText("Copy"); toolbar.add(ClipboardTargetManager.PASTE_ACTION).setToolTipText("Paste"); toolbar.add(ClipboardTargetManager.SELECT_ALL_ACTION).setToolTipText("Select All"); toolbar.addSeparator(); toolbar.add(undoManager.getUndoAction()).setToolTipText("Undo"); toolbar.add(undoManager.getRedoAction()).setToolTipText("Redo"); toolbar.addSeparator(); toolbar.add(editModeAction).setToolTipText("Edit Mode"); toolbar.add(debugModeAction).setToolTipText("Debug Mode"); toolbar.add(simModeAction).setToolTipText("Sim Mode"); toolbar.addSeparator(); toolbar.add(checkSyntaxAction).setToolTipText("Check Syntax"); getContentPane().add(toolbar, BorderLayout.NORTH); } { // Prepare the card panel cardLayout = new CardLayout(); cardPanel = new JPanel(cardLayout); cardPanel.setBorder(new EmptyBorder(2, 2, 2, 2)); { // Prepare the edit pane editPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); { // Prepare the left edit pane leftEditPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); if (leftEditPane.getBorder() == null) { leftEditPane.setBorder(PADDING_BORDER); } else { leftEditPane.setBorder( new CompoundBorder( PADDING_BORDER, leftEditPane.getBorder() ) ); } { // Prepare the text area editTextArea = new PHighlightedTextArea( program, 25, TProgramDocument.OUTSIDE_MARGIN_COLUMN + 2 ); TOptionsFrame.registerComponent( editTextArea, TOptionsFrame.PROGRAM_AREA_INDEX ); TOptionsFrame.registerHighlightedTextArea(editTextArea); int columnMarkers[] = new int[3]; columnMarkers[0] = 8; columnMarkers[1] = TProgramDocument.COMMENT_COLUMN; columnMarkers[2] = TProgramDocument.OUTSIDE_MARGIN_COLUMN; editTextArea.setColumnMarkers(columnMarkers); JPopupMenu popupMenu = editTextArea.getPopupMenu(); popupMenu.removeAll(); popupMenu.add(undoManager.getUndoAction().createMenuItem()); popupMenu.add(undoManager.getRedoAction().createMenuItem()); popupMenu.addSeparator(); popupMenu.add(ClipboardTargetManager.CUT_ACTION.createMenuItem()); popupMenu.add(ClipboardTargetManager.COPY_ACTION.createMenuItem()); popupMenu.add(ClipboardTargetManager.PASTE_ACTION.createMenuItem()); popupMenu.addSeparator(); popupMenu.add(ClipboardTargetManager.SELECT_ALL_ACTION.createMenuItem()); popupMenu.addSeparator(); popupMenu.add(checkSyntaxAction.createMenuItem()); popupMenu.add(functionAction.createMenuItem()); leftEditPane.setTopComponent(editTextArea); } { // Prepare the bottom left pane bottomLeftEditPane = new JPanel(new GridBagLayout()); bottomLeftEditPane.add( new JLabel("Warnings"), new GridBagConstraints( 0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); PHyperlink hyperlink = new PHyperlink( "Change Settings...", null, PHyperlink.METAL_STYLE ); hyperlink.setActionCommand(CHANGE_CHECKING_COMMAND); hyperlink.addActionListener(this); bottomLeftEditPane.add( hyperlink, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); hyperlink = new PHyperlink( "Hide Warnings", null, PHyperlink.METAL_STYLE ); hyperlink.setActionCommand(HIDE_WARNINGS_COMMAND); hyperlink.addActionListener(this); bottomLeftEditPane.add( hyperlink, new GridBagConstraints( 2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); { // Create a concatenation of lists warningListPanel = new PScrollablePanel(new GridBagLayout()); warningListPanel.setFont(null); warningListPanel.setWidthTrackingPolicy( PScrollablePanel.TRACKING_POLICY_ALWAYS ); TOptionsFrame.registerComponent( warningListPanel, TOptionsFrame.WARNING_AREA_INDEX ); { // Prepare the warning list warningList = new PWrappedList(); warningList.setFont(null); warningList.setVisibleRowCount(10); warningList.addListSelectionListener(this); warningListPanel.add( warningList, new GridBagConstraints( 0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0 ) ); } { // Prepare the warning list warningTallyList = new PWrappedList(); warningTallyList.setFont(null); warningTallyList.setEnabled(false); warningListPanel.add( warningTallyList, new GridBagConstraints( 0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0 ) ); } bottomLeftEditPane.add( new JScrollPane( warningListPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER ), new GridBagConstraints( 0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0 ) ); } leftEditPane.setBottomComponent(bottomLeftEditPane); } leftEditPane.setOneTouchExpandable(true); leftEditPane.setResizeWeight(0.8); editPane.setLeftComponent(leftEditPane); } { // Prepare the right edit pane JTabbedPane rightEditPane = new JTabbedPane( JTabbedPane.TOP ); { editReferencePane = new TReferencePane(); TOptionsFrame.registerComponent( editReferencePane, TOptionsFrame.REFERENCE_AREA_INDEX ); rightEditPane.addTab("Reference", editReferencePane); } { editStdinPane = new TStdinPane( virtualMachine, openStdinAction, saveStdinAction, false ); TOptionsFrame.registerComponent( editStdinPane, TOptionsFrame.STDIN_AREA_INDEX ); rightEditPane.addTab("Stdin", editStdinPane); } editPane.setRightComponent(rightEditPane); } editPane.setOneTouchExpandable(true); editPane.setResizeWeight(0.9); cardPanel.add(editPane, EDIT_MODE_COMMAND); } { // Prepare the debug pane debugPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); { // Prepare the left side of the debug pane JPanel debugLeftPane = new JPanel(new GridBagLayout()); { // Prepare the text area debugTextArea = new PHighlightedTextArea( program, 25, TProgramDocument.OUTSIDE_MARGIN_COLUMN + 2 ); TOptionsFrame.registerComponent( debugTextArea, TOptionsFrame.PROGRAM_AREA_INDEX ); TOptionsFrame.registerHighlightedTextArea(debugTextArea); debugTextArea.setEditable(false); int columnMarkers[] = new int[3]; columnMarkers[0] = 8; columnMarkers[1] = TProgramDocument.COMMENT_COLUMN; columnMarkers[2] = TProgramDocument.OUTSIDE_MARGIN_COLUMN; debugTextArea.setColumnMarkers(columnMarkers); debugLeftPane.add( debugTextArea, new GridBagConstraints( 0, 0, 2, 1, 1.0, 1.0, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the stats panel JPanel statsPanel = new JPanel(new GridBagLayout()); JTextField textField; PHyperlink hyperlink; statsPanel.add( new JLabel("Steps Taken"), new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); stepsTakenTextField = new PTextField(12); stepsTakenTextField.setEditable(false); stepsTakenTextField.setBackground(null); stepsTakenTextField.setDisabledTextColor(Color.black); stepsTakenTextField.setText("0"); stepsTakenTextField.setMinimumSize(stepsTakenTextField.getPreferredSize()); statsPanel.add( stepsTakenTextField, new GridBagConstraints( 1, 0, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(2, 2, 2, 2), 00, 0 ) ); hyperlink = new PHyperlink("Clear", null, PHyperlink.METAL_STYLE); hyperlink.setActionCommand(CLEAR_ODOMETER_COMMAND); hyperlink.addActionListener(this); statsPanel.add( hyperlink, new GridBagConstraints( 2, 0, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); statsPanel.add( new JLabel("Elapsed Time"), new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); elapsedTimeTextField = new PTextField(12); elapsedTimeTextField.setEditable(false); elapsedTimeTextField.setBackground(null); elapsedTimeTextField.setDisabledTextColor(Color.black); elapsedTimeTextField.setText("0.000 s"); elapsedTimeTextField.setMinimumSize( elapsedTimeTextField.getPreferredSize() ); statsPanel.add( elapsedTimeTextField, new GridBagConstraints( 1, 1, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); statsPanel.add( new JLabel("Refresh Rate"), new GridBagConstraints( 0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); textField = new JTextField(12); textField.setEnabled(false); textField.setBackground(null); textField.setDisabledTextColor(Color.black); textField.setDocument(TOptionsFrame.getRefreshRateDocument()); textField.setMinimumSize(textField.getPreferredSize()); statsPanel.add( textField, new GridBagConstraints( 1, 2, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); hyperlink = new PHyperlink( "Change Settings...", null, PHyperlink.METAL_STYLE ); hyperlink.setActionCommand(CHANGE_EXECUTION_COMMAND); hyperlink.addActionListener(this); statsPanel.add( hyperlink, new GridBagConstraints( 2, 2, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); statsPanel.add( new JLabel("Target Clock Period"), new GridBagConstraints( 0, 3, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); textField = new JTextField(12); textField.setEnabled(false); textField.setBackground(null); textField.setDisabledTextColor(Color.black); textField.setDocument(TOptionsFrame.getClockPeriodDocument()); textField.setMinimumSize(textField.getPreferredSize()); statsPanel.add( textField, new GridBagConstraints( 1, 3, 1, 1, 0.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); debugLeftPane.add( statsPanel, new GridBagConstraints( 0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), 0, 0 ) ); } { // Prepare the button panel JPanel buttonPanel = new JPanel(new GridLayout(2, 2, 4, 4)); buttonPanel.add(new JButton(stepAction)); buttonPanel.add(new JButton(runAction)); buttonPanel.add(new JButton(resetAction)); buttonPanel.add(new JButton(interruptAction)); debugLeftPane.add( buttonPanel, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST, GridBagConstraints.NONE, new Insets(2, 2, 2, 2), 0, 0 ) ); } debugPane.setLeftComponent(debugLeftPane); } { // Prepare the right debug pane rightDebugPane = new JTabbedPane(JTabbedPane.TOP); { debugReferencePane = new TReferencePane(); TOptionsFrame.registerComponent( debugReferencePane, TOptionsFrame.REFERENCE_AREA_INDEX ); rightDebugPane.addTab("Reference", debugReferencePane); } { debugStdinPane = new TStdinPane( virtualMachine, openStdinAction, saveStdinAction, true ); TOptionsFrame.registerComponent( debugStdinPane, TOptionsFrame.STDIN_AREA_INDEX ); rightDebugPane.addTab("Stdin", debugStdinPane); } { debugStdoutPane = new TStdoutPane( virtualMachine, saveStdoutAction ); TOptionsFrame.registerComponent( debugStdoutPane, TOptionsFrame.STDOUT_AREA_INDEX ); rightDebugPane.addTab("Stdout", debugStdoutPane); } { debugCorePane = new TCorePane( virtualMachine, saveMemDumpAction, saveCoreDumpAction ); TOptionsFrame.registerComponent( debugCorePane, TOptionsFrame.CORE_AREA_INDEX ); rightDebugPane.addTab("Core", debugCorePane); } debugPane.setRightComponent(rightDebugPane); } debugPane.setOneTouchExpandable(true); debugPane.setResizeWeight(0.9); cardPanel.add(debugPane, DEBUG_MODE_COMMAND); } { // Prepare the sim pane simPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); { // Prepare the left sim pane leftSimPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); simMachinePane = new TSimMachinePane( virtualMachine, loadAction, lookAction, stepAction, runAction, enterAction, interruptAction, resetAction ); leftSimPane.setTopComponent(simMachinePane); simDetailPane = new TSimDetailPane(virtualMachine, simMachinePane); leftSimPane.setBottomComponent(simDetailPane); int machinePanePreferredHeight = simMachinePane.getPreferredSize().height; int detailPanePreferredHeight = simDetailPane.getPreferredSize().height; leftSimPane.setOneTouchExpandable(true); leftSimPane.setResizeWeight( (float)machinePanePreferredHeight / (machinePanePreferredHeight + detailPanePreferredHeight) ); simPane.setLeftComponent(leftSimPane); } { // Prepare the right sim pane rightSimPane = new JTabbedPane(JTabbedPane.TOP); simMemPane = new TSimMemPane(virtualMachine); rightSimPane.add( new JScrollPane( simMemPane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ), "Memory" ); simStdinPane = new TSimStdinPane(virtualMachine); rightSimPane.add( new JScrollPane( simStdinPane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ), "Stdin" ); simStdoutPane = new TSimStdoutPane(virtualMachine); rightSimPane.add( new JScrollPane( simStdoutPane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ), "Stdout" ); simStdin2Pane = new TSimStdin2Pane(virtualMachine); rightSimPane.add( new JScrollPane( simStdin2Pane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ), "Stdin'" ); simStdout2Pane = new TSimStdout2Pane(virtualMachine); rightSimPane.add( new JScrollPane( simStdout2Pane, JScrollPane.VERTICAL_SCROLLBAR_NEVER, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS ), "Stdout'" ); simPane.setRightComponent(rightSimPane); } simPane.setOneTouchExpandable(true); simPane.setResizeWeight(0.9); cardPanel.add(simPane, SIM_MODE_COMMAND); } getContentPane().add( cardPanel, BorderLayout.CENTER ); } setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); synchronized (FRAMES) { FRAMES.add(this); updateTitle(); } enableEvents(AWTEvent.WINDOW_EVENT_MASK); doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); pack(); } /** * Override this method to prevent unclean disposals. */ public void dispose() { doCommand(CLOSE_COMMAND, null); } /** * Updates the title of this window as well as the title in all of the workspace menus. */ private void updateTitle() { if (file != null) program.setTitle(file.getName()); String newTitle = program.getTitle(); boolean titleChanged = !newTitle.equals(oldTitle); boolean isSaved = program.getText().equals(savedText); // possible problem if (titleChanged || (isSaved != wasSaved)) { if (isSaved) setTitle(newTitle + " - Visual X-TOY"); else setTitle(newTitle + "* - Visual X-TOY"); } if (titleChanged) updateAllWorkspaceMenus(); oldTitle = new String(newTitle); // make a copy so comparison will work wasSaved = isSaved; } /** * Updates all workspace menus to reflect */ private static void updateAllWorkspaceMenus() { synchronized (FRAMES) { int length = FRAMES.size(); FRAMES_ARRAY = FRAMES.toArray(FRAMES_ARRAY); Object framesArray[] = FRAMES_ARRAY; String titles[] = new String[length]; for (int frameCtr = 0; frameCtr < length; frameCtr++) titles[frameCtr] = ((TFrame)framesArray[frameCtr]).program.getTitle(); for (int frameCtr = 0; frameCtr < length; frameCtr++) { TFrame frame = (TFrame)framesArray[frameCtr]; JMenu menu = frame.workspaceMenu; int menuItemCount = frame.workspaceMenu.getItemCount(); frame.workspaceIndex = frameCtr; // Make sure the workspaceMenu has enough menuItems for (int ctr = menuItemCount; ctr < length; ctr++) { WorkspaceMenuItem menuItem = new WorkspaceMenuItem(ctr); menuItem.setActionCommand(WORKSPACE_COMMAND); menuItem.addActionListener(frame); menu.add(menuItem); } for (int ctr = menuItemCount; ctr > length; ctr--) { menu.remove(ctr - 1); } // Update the titles on the menu items for (int ctr = 0; ctr < length; ctr++) { WorkspaceMenuItem menuItem = (WorkspaceMenuItem)menu.getItem(ctr); menuItem.setText(titles[ctr]); menuItem.getModel().setSelected(ctr == frameCtr); } } } } /** * Starts or stops the auto-syntax-check runner. * * @param autoCheck Wheter or not the auto-syntax-check runner should be running. */ public static void setAutoCheck(boolean autoCheck) { synchronized (RUNNER) { if (autoCheck) { if (RUNNER.runningThread == null) { RUNNER.runningThread = new Thread(RUNNER); RUNNER.runningThread.start(); } } else { RUNNER.runningThread = null; } } } /** * Creates the first frame, initializing locations and bounds from the TOptionFrame's memory * of the last closed TFrame. The frame is also shown and broght to the front. * * @return The frame that was instantiated. */ public static TFrame createInitialFrame() { TFrame frame = new TFrame(); frame.setBounds(TOptionsFrame.getLastFrameBounds()); frame.validate(); frame.simPane.setDividerLocation(TOptionsFrame.getLastVerticalDividerLocation()); frame.leftSimPane.setDividerLocation( TOptionsFrame.getLastSimHorizontalDividerLocation() ); frame.editPane.setDividerLocation(TOptionsFrame.getLastVerticalDividerLocation()); frame.leftEditPane.setDividerLocation( TOptionsFrame.getLastEditHorizontalDividerLocation() ); frame.validate(); frame.doCommand(EDIT_MODE_COMMAND, null); frame.setVisible(true); frame.requestFocus(); frame.toFront(); return frame; } /** * Performs a command based on the argument. * * @param command A string representing the command. Note that pointer equality (not string * equality) is tested here, so it is important to use the string constants defined in this * class. TFrame.WORKSPACE_COMMAND requires an integer to be appended to it in order to * distinguish between the arbitrarily large number of other workspaces. An * IllegalArgumentException will be thrown if the argument is invalid. * @param extraInfo Any extra information necessary. This is specific to the command: * * @return True iff the command was executed sucessfully. */ public boolean doCommand(String command, Object extraInfo) { //////////////////////////////////////////////////////////////////////////////////////////// if (command == NEW_COMMAND) { int x = getX(); int y = getY(); int width = getWidth(); int height = getHeight(); Dimension screenSize = TOOLKIT.getScreenSize(); if (width + CASCADE_X * 3 < screenSize.width && height + CASCADE_Y * 3 < screenSize.height) { x += CASCADE_X; y += CASCADE_Y; if (x + width > screenSize.width || y + height > screenSize.height) { x = 0; y = 0; } } TFrame frame = new TFrame(); frame.setBounds(x, y, width, height); int dividerLocation; if (mode == EDIT_MODE_COMMAND) dividerLocation = editPane.getDividerLocation(); else if (mode == DEBUG_MODE_COMMAND) dividerLocation = debugPane.getDividerLocation(); else dividerLocation = simPane.getDividerLocation(); frame.validate(); frame.simPane.setDividerLocation(dividerLocation); frame.leftSimPane.setDividerLocation(leftSimPane.getDividerLocation()); frame.editPane.setDividerLocation(dividerLocation); frame.leftEditPane.setDividerLocation(leftEditPane.getDividerLocation()); frame.validate(); frame.setVisible(true); frame.requestFocus(); frame.toFront(); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == OPEN_COMMAND) { // Grab the text from the file File files[]; if (extraInfo == null) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TOY_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(true); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); files = chooser.getSelectedFiles(); } else { files = new File[1]; files[0] = (File)extraInfo; } if (files.length == 0) return false; int x = getX(); int y = getY(); int width = getWidth(); int height = getHeight(); Dimension screenSize = TOOLKIT.getScreenSize(); boolean cascade = (width + CASCADE_X * 3 < screenSize.width && height + CASCADE_Y * 3 < screenSize.height); for (int ctr = 0; ctr < files.length; ctr++) { StringBuffer buffer = new StringBuffer(); try { FileReader fileReader = new FileReader(files[ctr]); int readChars; char array[] = new char[100]; do { readChars = fileReader.read(array, 0, array.length); if (readChars != -1) buffer.append(array, 0, readChars); } while (readChars != -1); fileReader.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when reading from the file \"" + files[ctr] + "\".", "File I/O Error", JOptionPane.ERROR_MESSAGE ); return false; } // Decide wheter or not to reuse this window if (files.length == 1 && !virtualMachine.isRunning() && program.getText().equals(savedText) || ctr == 0 && isNew && !virtualMachine.isRunning() && program.getText().equals(savedText)) { String text = buffer.toString(); isNew = false; program.setText(text); savedText = program.getText(); file = files[ctr]; undoManager.discardAllEdits(); updateTitle(); if (mode == EDIT_MODE_COMMAND) doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); else doCommand(RESET_COMMAND, null); } else { TProgramDocument program = new TProgramDocument(buffer.toString()); TFrame frame = new TFrame(program, files[ctr]); if (cascade) { x += CASCADE_X; y += CASCADE_Y; if (x + width > screenSize.width || y + height > screenSize.height) { x = 0; y = 0; } } frame.setBounds(x, y, width, height); int dividerLocation; if (mode == EDIT_MODE_COMMAND) dividerLocation = editPane.getDividerLocation(); else if (mode == DEBUG_MODE_COMMAND) dividerLocation = debugPane.getDividerLocation(); else dividerLocation = simPane.getDividerLocation(); frame.validate(); frame.simPane.setDividerLocation(dividerLocation); frame.leftSimPane.setDividerLocation(leftSimPane.getDividerLocation()); frame.editPane.setDividerLocation(dividerLocation); frame.leftEditPane.setDividerLocation(leftEditPane.getDividerLocation()); frame.validate(); frame.doCommand(mode, null); frame.setVisible(true); frame.requestFocus(); frame.toFront(); } //program.autocomment(); TOptionsFrame.putFileIntoHistory(files[ctr]); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == OPEN_EXAMPLE_COMMAND) { // Grab the text from the Example Dialog String exampleText[] = TExampleDialog.showExampleDialog(this); if (exampleText == null) return false; int x = getX(); int y = getY(); int width = getWidth(); int height = getHeight(); Dimension screenSize = TOOLKIT.getScreenSize(); boolean cascade = (width + CASCADE_X * 3 < screenSize.width && height + CASCADE_Y * 3 < screenSize.height); for (int ctr = 0; ctr < exampleText.length; ctr++) { // Decide wheter or not to reuse this window if (exampleText.length == 1 && !virtualMachine.isRunning() && program.getText().equals(savedText) || ctr == 0 && isNew && !virtualMachine.isRunning() && program.getText().equals(savedText)) { isNew = false; program.setText(exampleText[ctr]); savedText = program.getText(); file = null; undoManager.discardAllEdits(); updateTitle(); if (mode == EDIT_MODE_COMMAND) doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); else doCommand(RESET_COMMAND, null); } else { TProgramDocument program = new TProgramDocument(exampleText[ctr]); TFrame frame = new TFrame(program, null); if (cascade) { x += CASCADE_X; y += CASCADE_Y; if (x + width > screenSize.width || y + height > screenSize.height) { x = 0; y = 0; } } frame.setBounds(x, y, width, height); int dividerLocation; if (mode == EDIT_MODE_COMMAND) dividerLocation = editPane.getDividerLocation(); else if (mode == DEBUG_MODE_COMMAND) dividerLocation = debugPane.getDividerLocation(); else dividerLocation = simPane.getDividerLocation(); frame.validate(); frame.simPane.setDividerLocation(dividerLocation); frame.leftSimPane.setDividerLocation(leftSimPane.getDividerLocation()); frame.editPane.setDividerLocation(dividerLocation); frame.leftEditPane.setDividerLocation(leftEditPane.getDividerLocation()); frame.validate(); frame.doCommand(mode, null); frame.setVisible(true); frame.requestFocus(); frame.toFront(); } } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CLOSE_COMMAND) { virtualMachine.interrupt(); if (!savedText.equals(program.getText())) { boolean done = false; while (!done) { int result = JOptionPane.showConfirmDialog( this, "The program \"" + program.getTitle() + "\" has been modified since it was " + "last saved.\nDo you wish to save before closing the window?", "Confirm Close Command", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE ); if (result == JOptionPane.CANCEL_OPTION) { return false; } else if (result == JOptionPane.YES_OPTION) { done = doCommand(SAVE_COMMAND, null); } else { done = true; } } } setVisible(false); TOptionsFrame.setLastFrameBounds(getBounds()); if (mode == EDIT_MODE_COMMAND) TOptionsFrame.setLastVerticalDividerLocation(editPane.getDividerLocation()); else if (mode == DEBUG_MODE_COMMAND) TOptionsFrame.setLastVerticalDividerLocation(debugPane.getDividerLocation()); else TOptionsFrame.setLastVerticalDividerLocation(simPane.getDividerLocation()); cardLayout.show(cardPanel, EDIT_MODE_COMMAND); TOptionsFrame.setLastEditHorizontalDividerLocation(leftEditPane.getDividerLocation()); cardLayout.show(cardPanel, SIM_MODE_COMMAND); TOptionsFrame.setLastSimHorizontalDividerLocation(leftSimPane.getDividerLocation()); TOptionsFrame.unregisterComponent( editTextArea, TOptionsFrame.PROGRAM_AREA_INDEX ); TOptionsFrame.unregisterHighlightedTextArea(editTextArea); TOptionsFrame.unregisterComponent( warningListPanel, TOptionsFrame.WARNING_AREA_INDEX ); TOptionsFrame.unregisterComponent( editReferencePane, TOptionsFrame.REFERENCE_AREA_INDEX ); TOptionsFrame.unregisterComponent( editStdinPane, TOptionsFrame.STDIN_AREA_INDEX ); TOptionsFrame.unregisterComponent( debugTextArea, TOptionsFrame.PROGRAM_AREA_INDEX ); TOptionsFrame.unregisterHighlightedTextArea(debugTextArea); TOptionsFrame.unregisterComponent( debugReferencePane, TOptionsFrame.REFERENCE_AREA_INDEX ); TOptionsFrame.unregisterComponent( debugStdinPane, TOptionsFrame.STDIN_AREA_INDEX ); TOptionsFrame.unregisterComponent( debugStdoutPane, TOptionsFrame.STDOUT_AREA_INDEX ); TOptionsFrame.unregisterComponent( debugCorePane, TOptionsFrame.CORE_AREA_INDEX ); super.dispose(); synchronized (FRAMES) { FRAMES.remove(this); if (FRAMES.size() == 0) System.exit(0); updateAllWorkspaceMenus(); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == REVERT_COMMAND) { int result = JOptionPane.showConfirmDialog( this, "Reverting to the saved text will cause all of your changes to be lost.\n" + "Are you sure you wish to do this?", "Confirm Revert Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result == JOptionPane.YES_OPTION) { String newText = null; // Attempt to reload the file if possible if (file != null) { try { FileReader fileReader = new FileReader(file); StringBuffer buffer = new StringBuffer(); int readChars; char array[] = new char[100]; do { readChars = fileReader.read(array, 0, array.length); if (readChars != -1) buffer.append(array, 0, readChars); } while (readChars != -1); fileReader.close(); newText = buffer.toString(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when reading from the file \"" + file + "\".\n" + "Visual X-TOY will load the saved text from its own cache.", "File I/O Error", JOptionPane.ERROR_MESSAGE ); } } // If that fails, then use the frame's memory to get the text. if (newText == null) newText = savedText; program.setText(newText); savedText = program.getText(); updateTitle(); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_COMMAND && file != null) { try { FileWriter fileWriter = new FileWriter(file); String text = program.getText(); fileWriter.write(text); fileWriter.close(); savedText = text; updateTitle(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O Error", JOptionPane.ERROR_MESSAGE ); } isNew = false; return true; } //////////////////////////////////////////////////////////////////////////////////////////// /* if (command == SAVE_ALL_COMMAND) { boolean abort = false; synchronized (FRAMES) { Object array[] = FRAMES.toArray(); int ctr = 0; while (!abort && ctr < array.length) { if (!((TFrame)array[ctr]).doCommand(SAVE_COMMAND, null)) abort = true; } } return !abort; } */ //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_AS_COMMAND || command == SAVE_COMMAND && file == null) { if (extraInfo == null) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); if (file != null) { chooser.setSelectedFile(file); } else { char array[] = program.getTitle().toCharArray(); boolean needsWhitespace = false; StringBuffer buffer = new StringBuffer(array.length); for (int ctr = 0; ctr < array.length; ctr++) { char ch = array[ctr]; if (ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9' || ch == '-' || ch == '.') { buffer.append(ch); needsWhitespace = true; } else if (ch >= 'A' && ch <= 'Z') { buffer.append((char)(ch - 'A' + 'a')); needsWhitespace = true; } else if (Character.isWhitespace(ch) || ch == '_') { if (needsWhitespace) { buffer.append('_'); needsWhitespace = false; } } } int bufferLength = buffer.length(); if (!needsWhitespace && bufferLength > 0) buffer.setLength(bufferLength - 1); buffer.append(".toy"); chooser.setSelectedFile( new File( chooser.getCurrentDirectory(), buffer.toString() ) ); } chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TOY_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); file = chooser.getSelectedFile(); if (file.exists()) { int result = JOptionPane.showConfirmDialog( this, "The file \"" + file + "\" already exists.\n" + "Are you sure you want to save over it?", "Confirm Save As Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result != JOptionPane.YES_OPTION) return false; } } else { file = (File)extraInfo; } try { FileWriter fileWriter = new FileWriter(file); String text = program.getText(); fileWriter.write(text); fileWriter.close(); savedText = text; updateTitle(); } catch (Exception e) { file = null; e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O error", JOptionPane.ERROR_MESSAGE ); } isNew = false; TOptionsFrame.putFileIntoHistory(file); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == QUIT_COMMAND) { boolean abort = false; synchronized (FRAMES) { while (!abort) { TFrame frame = (TFrame)FRAMES.get(0); if (!frame.doCommand(CLOSE_COMMAND, null)) abort = true; } } return !abort; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == EDIT_MODE_COMMAND) { if (mode == EDIT_MODE_COMMAND || virtualMachine.isRunning()) { return false; } cardLayout.show(cardPanel, EDIT_MODE_COMMAND); if (mode == DEBUG_MODE_COMMAND) { editPane.setDividerLocation(debugPane.getDividerLocation()); } else if (mode == SIM_MODE_COMMAND) { editPane.setDividerLocation(simPane.getDividerLocation()); } menuModeButtonGroup.setSelected(menuEditModeButtonModel, true); editModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_EDIT_MODE_ICON_ON ) ); debugModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_DEBUG_MODE_ICON_OFF ) ); simModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SIM_MODE_ICON_OFF ) ); mode = EDIT_MODE_COMMAND; checkSyntaxAction.setEnabled(true); functionAction.setEnabled(true); doCommand(RESET_COMMAND, null); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == DEBUG_MODE_COMMAND) { if (mode == DEBUG_MODE_COMMAND || virtualMachine.isRunning()) return false; if (mode == EDIT_MODE_COMMAND) { doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); if (hasFatalError) { JOptionPane.showMessageDialog( this, "Your program contains fatal errors. Please correct these before\n" + "leaving edit mode.", "Action Blocked", JOptionPane.ERROR_MESSAGE ); menuModeButtonGroup.setSelected(menuEditModeButtonModel, true); return false; } program.setInitialStdin(virtualMachine.getUnconsumedStdin()); } cardLayout.show(cardPanel, DEBUG_MODE_COMMAND); if (mode == EDIT_MODE_COMMAND) { debugPane.setDividerLocation(editPane.getDividerLocation()); } else if (mode == SIM_MODE_COMMAND) { debugPane.setDividerLocation(simPane.getDividerLocation()); } menuModeButtonGroup.setSelected(menuDebugModeButtonModel, true); editModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_EDIT_MODE_ICON_OFF ) ); debugModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_DEBUG_MODE_ICON_ON ) ); simModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SIM_MODE_ICON_OFF ) ); mode = DEBUG_MODE_COMMAND; checkSyntaxAction.setEnabled(false); functionAction.setEnabled(false); // We allow the user to select which exceptions can be thrown in Debug mode virtualMachine.setExceptionHandler(TOptionsFrame.getExceptionHandler()); doCommand(RESET_COMMAND, null); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SIM_MODE_COMMAND) { if (mode == SIM_MODE_COMMAND || virtualMachine.isRunning()) return false; if (mode == EDIT_MODE_COMMAND) { doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); if (hasFatalError) { JOptionPane.showMessageDialog( this, "Your program contains fatal errors. Please correct these before\n" + "leaving edit mode.", "Action Blocked", JOptionPane.ERROR_MESSAGE ); menuModeButtonGroup.setSelected(menuEditModeButtonModel, true); return false; } program.setInitialStdin(virtualMachine.getUnconsumedStdin()); } cardLayout.show(cardPanel, SIM_MODE_COMMAND); if (mode == EDIT_MODE_COMMAND) { simPane.setDividerLocation(editPane.getDividerLocation()); } else if (mode == DEBUG_MODE_COMMAND) { simPane.setDividerLocation(debugPane.getDividerLocation()); } menuModeButtonGroup.setSelected(menuSimModeButtonModel, true); editModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_EDIT_MODE_ICON_OFF ) ); debugModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_DEBUG_MODE_ICON_OFF ) ); simModeAction.setSmallIcon( TImageManager.getIcon( TImageManager.REGULAR_UNSCALED_IMAGE_GROUP, TImageManager.REGULAR_UNSCALED_SIM_MODE_ICON_ON ) ); mode = SIM_MODE_COMMAND; checkSyntaxAction.setEnabled(false); functionAction.setEnabled(false); // We don't allow exceptions to be thrown in sim mode virtualMachine.setExceptionHandler(TExceptionHandler.PROMISCUOUS_EXCEPTION_HANDLER); doCommand(RESET_COMMAND, null); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == WORKSPACE_COMMAND) { try { int index = ((Integer)extraInfo).intValue(); if (index != workspaceIndex) { // Uncheck the radio button JRadioButtonMenuItem menuItem = (JRadioButtonMenuItem)workspaceMenu.getItem(index); menuItem.getModel().setSelected(false); // Bring the appropriate frame to the front and give it focus synchronized (FRAMES) { TFrame frame = (TFrame)FRAMES.get(index); frame.requestFocus(); frame.toFront(); } } } catch (Exception e) { e.printStackTrace(); return false; } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CHECK_SYNTAX_COMMAND) { long startTime = System.currentTimeMillis(); programChanged = false; { // Swap the previous warnings and curent warnings TProgramDocument.WarningInfoStruct tempWarningInfo = previousWarnings; previousWarnings = currentWarnings; currentWarnings = tempWarningInfo; } program.getWarnings( currentWarnings, TOptionsFrame.getIgnoreWarnings() ); hasFatalError = currentWarnings.hasFatalError; int length = currentWarnings.warningCount; DefaultListModel model = null; // Ensure that the List model is of the right type if (warningList.getModel() instanceof DefaultListModel) { if (!previousWarnings.warningsEqual(currentWarnings)) { model = (DefaultListModel)warningList.getModel(); warningList.setModel(BLANK_LIST_MODEL); model.clear(); } } else { model = new DefaultListModel(); } // Fill up the list model if (model != null) { model.ensureCapacity(length); for (int ctr = 0; ctr < length; ctr++) model.addElement(currentWarnings.warnings[ctr]); warningList.setModel(model); } // Update as many positions as possible (we'll create more later) if (warningSelectionDots.size() > 0) { int end = Math.min(length, warningSelectionDots.size()); Iterator dotIterator = warningSelectionDots.iterator(); Iterator markIterator = warningSelectionMarks.iterator(); for (int ctr = 0; ctr < end; ctr++) { ((HighlightedDocument.Position)dotIterator.next()).setOffset( currentWarnings.selectionStart[ctr] ); ((HighlightedDocument.Position)markIterator.next()).setOffset( currentWarnings.selectionEnd[ctr] ); } if (dotIterator.hasNext()) { ((HighlightedDocument.Position)dotIterator.next()).setOffset(0); ((HighlightedDocument.Position)markIterator.next()).setOffset(0); } } // Ensure that we have enough positions (also ensure that we don't have way too many, // since positions tend to slow things down) if (warningSelectionDots.size() < length) { warningSelectionDots.ensureCapacity(length); warningSelectionMarks.ensureCapacity(length); for (int ctr = warningSelectionDots.size(); ctr < length; ctr++) { warningSelectionDots.add( program.createPosition( currentWarnings.selectionStart[ctr] ) ); warningSelectionMarks.add( program.createPosition( currentWarnings.selectionEnd[ctr] ) ); } } if (warningTallyList.getModel() instanceof DefaultListModel) { model = (DefaultListModel)warningTallyList.getModel(); if (model.size() > 1) model.clear(); } else { model = new DefaultListModel(); warningTallyList.setModel(model); } int elapsedTime = (int)(System.currentTimeMillis() - startTime); String string = "Syntax check complete: " + (length - (hasFatalError?1:0)) + " warning(s), " + (hasFatalError?1:0) + " error(s), " + (elapsedTime / 1000) + "." + ((elapsedTime % 1000) / 10) + " ms."; if (model.size() == 0) model.addElement(string); else model.set(0, string); if (((Boolean)extraInfo).booleanValue() && leftEditPane.getDividerLocation() >= leftEditPane.getMaximumDividerLocation()) { leftEditPane.setDividerLocation(0.8); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == FUNCTION_COMMAND) { int selectionStart = editTextArea.getSelectionStart(); int selectionEnd = editTextArea.getSelectionEnd(); program.replace( selectionStart, selectionEnd - selectionStart, "function Unnamed\n" + "// Input: \n" + "// Return address: \n" + "// Output: \n" + "// Temporary variables: ", false ); editTextArea.select(selectionStart + 9, selectionStart + 16, selectionStart + 16); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == LOAD_COMMAND) { if (virtualMachine.isRunning()) return false; TWord addr = simMachinePane.getAddr(); virtualMachine.setProgramCtr(addr); virtualMachine.setMem(addr.getValue(), simMachinePane.getData()); simMemPane.scrollToPc(); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == LOOK_COMMAND) { if (virtualMachine.isRunning()) return false; virtualMachine.setProgramCtr(simMachinePane.getAddr()); simMemPane.scrollToPc(); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == STEP_COMMAND) { long startTime = System.currentTimeMillis(); stepsTaken += virtualMachine.step(); if (mode == DEBUG_MODE_COMMAND) { elapsedTime += (int)(System.currentTimeMillis() - startTime); if (virtualMachine.needsInput()) rightDebugPane.setSelectedComponent(debugStdinPane); else if (virtualMachine.hasEncounteredError()) rightDebugPane.setSelectedComponent(debugStdoutPane); stepsTakenTextField.setText(String.valueOf(stepsTaken)); int elapsedTimeSec = elapsedTime / 1000; int elapsedTimeRem = elapsedTime % 1000; if (elapsedTimeRem >= 100) elapsedTimeTextField.setText(elapsedTimeSec + "." + elapsedTimeRem + " s"); else if (elapsedTimeRem >= 100) elapsedTimeTextField.setText(elapsedTimeSec + ".0" + elapsedTimeRem + " s"); else elapsedTimeTextField.setText(elapsedTimeSec + ".00" + elapsedTimeRem + " s"); } else { simMemPane.scrollToPc(); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == RUN_COMMAND) { virtualMachine.run(this); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == ENTER_COMMAND) { if (virtualMachine.isRunning()) return false; TWord data = simMachinePane.getData(); virtualMachine.getUnconsumedStdin(tempBuffer); tempBuffer.add(data); virtualMachine.setStdin(null, tempBuffer); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == INTERRUPT_COMMAND) { virtualMachine.interrupt(); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == RESET_COMMAND) { if (virtualMachine.isRunning()) return false; program.reset(virtualMachine); if (mode == DEBUG_MODE_COMMAND) { synchronized (odometerLock) { stepsTaken = 0; elapsedTime = 0; stepsTakenTextField.setText("0"); elapsedTimeTextField.setText("0.000 s"); } } else if (mode == SIM_MODE_COMMAND) { simStdinPane.scrollToFrontier(true); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == OPEN_STDIN_COMMAND) { // Grab the text from the file JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TXT_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); File file = chooser.getSelectedFile(); StringBuffer buffer = new StringBuffer(); try { FileReader fileReader = new FileReader(file); int readChars; char array[] = new char[100]; do { readChars = fileReader.read(array, 0, array.length); if (readChars != -1) buffer.append(array, 0, readChars); } while (readChars != -1); fileReader.close(); } catch (Exception e) { e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when reading from the file \"" + file + "\".", "File I/O Error", JOptionPane.ERROR_MESSAGE ); return false; } TWordBuffer unconsumedStdin = virtualMachine.getUnconsumedStdin(); int length = buffer.length(); int charCtr = 0; while (charCtr < length) { char ch = buffer.charAt(charCtr); if (TWord.isHexDigit(ch)) { int peekCtr = charCtr + 1; while (peekCtr < length && peekCtr < charCtr + 4 && TWord.isHexDigit(buffer.charAt(peekCtr))) peekCtr++; try { unconsumedStdin.add( TWord.parseWord( buffer.substring(charCtr, peekCtr), 16 ) ); } catch (NumberFormatException e) { e.printStackTrace(); } charCtr = peekCtr; } else { charCtr++; } } virtualMachine.setStdin(null, unconsumedStdin); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_STDIN_COMMAND) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setSelectedFile(new File(chooser.getCurrentDirectory(), "toy_stdin.txt")); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TXT_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); File file = chooser.getSelectedFile(); if (file.exists()) { int result = JOptionPane.showConfirmDialog( this, "The file \"" + file + "\" already exists.\n" + "Are you sure you want to save over it?", "Confirm Save As Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result != JOptionPane.YES_OPTION) return false; } TWordBuffer stdin = virtualMachine.getConsumedStdin(); StringBuffer buffer = new StringBuffer(); int size = stdin.getSize(); for (int ctr = 0; ctr < size; ctr++) { buffer.append(stdin.getWord(ctr).toHexString(false)); buffer.append('\n'); } virtualMachine.getUnconsumedStdin(stdin); size = stdin.getSize(); for (int ctr = 0; ctr < size; ctr++) { buffer.append(stdin.getWord(ctr).toHexString(false)); buffer.append('\n'); } try { FileWriter fileWriter = new FileWriter(file); fileWriter.write(buffer.toString()); fileWriter.close(); } catch (Exception e) { file = null; e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O error", JOptionPane.ERROR_MESSAGE ); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_STDOUT_COMMAND) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setSelectedFile(new File(chooser.getCurrentDirectory(), "toy_stdout.txt")); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TXT_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); File file = chooser.getSelectedFile(); if (file.exists()) { int result = JOptionPane.showConfirmDialog( this, "The file \"" + file + "\" already exists.\n" + "Are you sure you want to save over it?", "Confirm Save As Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result != JOptionPane.YES_OPTION) return false; } TWordBuffer stdout = virtualMachine.getStdout(); StringBuffer buffer = new StringBuffer(); int size = stdout.getSize(); for (int ctr = 0; ctr < size; ctr++) { buffer.append(stdout.getWord(ctr).toHexString(false)); buffer.append('\n'); } try { FileWriter fileWriter = new FileWriter(file); fileWriter.write(buffer.toString()); fileWriter.close(); } catch (Exception e) { file = null; e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O error", JOptionPane.ERROR_MESSAGE ); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_CORE_DUMP_COMMAND) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setSelectedFile(new File(chooser.getCurrentDirectory(), "toy_core.txt")); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TXT_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); File file = chooser.getSelectedFile(); if (file.exists()) { int result = JOptionPane.showConfirmDialog( this, "The file \"" + file + "\" already exists.\n" + "Are you sure you want to save over it?", "Confirm Save As Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result != JOptionPane.YES_OPTION) return false; } try { FileWriter fileWriter = new FileWriter(file); fileWriter.write(virtualMachine.getCoreDump()); fileWriter.close(); } catch (Exception e) { file = null; e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O error", JOptionPane.ERROR_MESSAGE ); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == SAVE_MEM_DUMP_COMMAND) { JFileChooser chooser = new JFileChooser(); File currentDirectory = TOptionsFrame.getCurrentDirectory(); if (currentDirectory != null) chooser.setCurrentDirectory(currentDirectory); chooser.setSelectedFile(new File(chooser.getCurrentDirectory(), "toy_memory.txt")); chooser.setAcceptAllFileFilterUsed(true); // This doesn't work in jdk1.3- chooser.setDragEnabled(true); chooser.addChoosableFileFilter(TXT_FILE_FILTER); chooser.setFileHidingEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setMultiSelectionEnabled(false); if (chooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) return false; currentDirectory = chooser.getCurrentDirectory(); if (currentDirectory != null) TOptionsFrame.setCurrentDirectory(currentDirectory); File file = chooser.getSelectedFile(); if (file.exists()) { int result = JOptionPane.showConfirmDialog( this, "The file \"" + file + "\" already exists.\n" + "Are you sure you want to save over it?", "Confirm Save As Command", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result != JOptionPane.YES_OPTION) return false; } try { FileWriter fileWriter = new FileWriter(file); fileWriter.write(virtualMachine.getMemDump()); fileWriter.close(); } catch (Exception e) { file = null; e.printStackTrace(); JOptionPane.showMessageDialog( this, "An error occurred when writing to the file \"" + file + "\".", "File I/O error", JOptionPane.ERROR_MESSAGE ); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CHANGE_EXECUTION_COMMAND) { TOptionsFrame.show(TOptionsFrame.EXECUTION_PERFORMANCE_NODE); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CLEAR_ODOMETER_COMMAND) { synchronized (odometerLock) { stepsTaken = 0; elapsedTime = 0; stepsTakenTextField.setText("0"); elapsedTimeTextField.setText("0.000 s"); } return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == CHANGE_CHECKING_COMMAND) { TOptionsFrame.show(TOptionsFrame.EDITING_CHECKING_NODE); return true; } //////////////////////////////////////////////////////////////////////////////////////////// if (command == HIDE_WARNINGS_COMMAND) { leftEditPane.setDividerLocation(1.0); return true; } throw new IllegalArgumentException(); } /** * Implement ActionListener to pass the command onto doCommand(). * * @see #doCommand(String, Object) */ public void actionPerformed(ActionEvent e) { if (e.getActionCommand() == WORKSPACE_COMMAND) { doCommand(WORKSPACE_COMMAND, ((WorkspaceMenuItem)e.getSource()).getIndex()); } else if (e.getActionCommand() == CHECK_SYNTAX_COMMAND) { doCommand(CHECK_SYNTAX_COMMAND, Boolean.TRUE); } else { doCommand(e.getActionCommand(), null); } } /** * Implement TextListener to update the other components when the document changes. */ public void textValueChanged(TextEvent e) { updateTitle(); programChanged = true; } /** * Implement ListSelectionListener to update the editTextArea selection when the list's selection * changes. */ public void valueChanged(ListSelectionEvent e) { int selectedIndex = warningList.getSelectedIndex(); if (selectedIndex != -1) { editTextArea.select( ((HighlightedDocument.Position)warningSelectionDots.get( selectedIndex )).getOffset(), ((HighlightedDocument.Position)warningSelectionMarks.get( selectedIndex )).getOffset() ); } } /** * Implement ChangeListener to listen to changes in the state of the virtual machine. */ public void stateChanged(ChangeEvent e) { boolean editMode = (mode == EDIT_MODE_COMMAND); boolean simMode = (mode == SIM_MODE_COMMAND); boolean isRunning = virtualMachine.isRunning(); boolean canGo = !isRunning && !virtualMachine.isDone() && !virtualMachine.needsInput(); editModeAction.setEnabled(!isRunning); debugModeAction.setEnabled(!isRunning); simModeAction.setEnabled(!isRunning); lookAction.setEnabled(simMode && !isRunning); loadAction.setEnabled(simMode && !isRunning); enterAction.setEnabled(simMode && !isRunning); resetAction.setEnabled(!editMode && !isRunning); stepAction.setEnabled(!editMode && canGo); runAction.setEnabled(!editMode && canGo); interruptAction.setEnabled(!editMode && isRunning); openStdinAction.setEnabled(!isRunning); saveStdinAction.setEnabled(!isRunning); saveStdoutAction.setEnabled(!editMode && !isRunning); saveMemDumpAction.setEnabled(!editMode && !isRunning); saveCoreDumpAction.setEnabled(!editMode && !isRunning); if (mode == DEBUG_MODE_COMMAND) { int lineDefined = program.getLineDefined( virtualMachine.getProgramCtr().getValue() & 0xFF, true ); if (debugTextArea.getHighlightedLine() != lineDefined) { debugTextArea.setHighlightedLine(lineDefined); debugTextArea.scrollToCaret(); } } } /** * This function is called by the TVirtualMachine's runner when it has completed the * previous batch of steps. * * @param virtualMachine The virtual machine whose status is being reported. * @param n The number of steps taken since the last update. * @param elapsedTime The number of milliseconds between the lastUpdate and the present. * @param willStop Wheter or not the TVirtualMachine will stop after this status update. * @return The number of additional steps to take before fireing more ChangeEvents and * producing another status update. If this is 0, the virtualMachine will stop. If this * is negative, a stack trace will be written to stderr and the virtualMachine will stop. */ public int statusUpdate(TVirtualMachine virtualMachine, int n, int elapsedTime, boolean willStop) { if (mode == DEBUG_MODE_COMMAND) { stepsTaken += n; this.elapsedTime += elapsedTime; if (virtualMachine.needsInput()) rightDebugPane.setSelectedComponent(debugStdinPane); else if (virtualMachine.hasEncounteredError()) rightDebugPane.setSelectedComponent(debugStdoutPane); stepsTakenTextField.setText(String.valueOf(stepsTaken)); int elapsedTimeSec = this.elapsedTime / 1000; int elapsedTimeRem = this.elapsedTime % 1000; if (elapsedTimeRem >= 100) elapsedTimeTextField.setText(elapsedTimeSec + "." + elapsedTimeRem + " s"); else if (elapsedTimeRem >= 10) elapsedTimeTextField.setText(elapsedTimeSec + ".0" + elapsedTimeRem + " s"); else elapsedTimeTextField.setText(elapsedTimeSec + ".00" + elapsedTimeRem + " s"); } else { simMemPane.scrollToPc(); } return TOptionsFrame.getRefreshRate(); } /** * This function is called by the TVirtualMachine's runner after it has recieved an order * for a batch of steps to be run. The next status update will not occur until after n * * getClockPeriod() milliseconds, where n was the number of steps taken. If the preferred * clock period is too fast, the next status update will occur as soon the batch of steps * is completed. * * @return The preferred number of milliseconds each step should take. */ public int getClockPeriod() { return TOptionsFrame.getClockPeriod(); } /** * Intercept WindowEvents to pick up WINDOW_CLOSING events. */ protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { doCommand(CLOSE_COMMAND, null); } super.processWindowEvent(e); } /** * TFrameAction is a generalizable action for the TFrame; basically, it relays all ActionEvents * to the doCommand() method. * * @author btsang * @version 7.1 */ protected class TFrameAction extends AbstractAction2 { /** * Creates a new TFrameAction. */ protected TFrameAction(String name, Icon icon, int mnemonic, KeyStroke accelerator, String command) { this(name, icon, mnemonic, accelerator, command, null); } /** * Creates a new TFrameAction. */ protected TFrameAction(String name, Icon icon, int mnemonic, KeyStroke accelerator, String command, Object extraInfo) { super(name, icon); if (name == null || command == null) throw new NullPointerException(); setMnemonic(mnemonic); setAccelerator(accelerator); setActionCommand(command); setExtraInfo(extraInfo); } /** * Implements ActionListener to perform the redo operation. */ public void actionPerformed(ActionEvent e) { doCommand(getActionCommand(), getExtraInfo()); } } /** * TWorkspaceMenuItem is a simple subclass of JRadioButtonMenuItem which keeps an index * property. * * @author btsang * @version 7.1 */ public static class WorkspaceMenuItem extends JRadioButtonMenuItem { private Integer index; /** * Constructs a new WorkspaceMenuItem. */ public WorkspaceMenuItem(int index) { super(); this.index = new Integer(index); } /** * Returns the index of the WorkspaceMenuItem. * * @return The Integer object corresponding to the int that this WorkspaceMenuItem was * constructed with. */ public Integer getIndex() { return index; } } /** * Runner is the implementation of Runnable which updates the warnings of all TFrames (if the * program had changed since the last syntax check). It is started and stopped by * TFrame.setAutoCheck() which is called by TOptionFrame when the user applies changes. * * @author btsang * @version 7.1 */ protected static class Runner implements Runnable { protected Thread runningThread; protected Runner() { } public void run() { Thread currentThread = Thread.currentThread(); while (runningThread == currentThread) { synchronized (FRAMES) { int length = FRAMES.size(); FRAMES_ARRAY = FRAMES.toArray(FRAMES_ARRAY); Object framesArray[] = FRAMES_ARRAY; for (int ctr = 0; runningThread == currentThread && ctr < length; ctr++) { TFrame frame = (TFrame)framesArray[ctr]; if (frame.programChanged) frame.doCommand(CHECK_SYNTAX_COMMAND, Boolean.FALSE); } } if (runningThread == currentThread) { try { Thread.sleep(1000); } catch (InterruptedException e) { runningThread = null; e.printStackTrace(); } } } } } }