/* Main.java * * Entry point of EduMIPS64 * (c) 2006 Andrea Spadaccini, Antonella Scandura, Vanni Rizzo * * This file is part of the EduMIPS64 project, and is released under the GNU * General Public License. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.edumips64; import org.edumips64.core.*; import org.edumips64.core.is.InstructionBuilder; import org.edumips64.img.*; import org.edumips64.ui.swing.*; import org.edumips64.utils.*; import org.edumips64.utils.io.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.logging.Logger; import java.util.logging.Handler; import java.io.File; import java.io.IOException; import javax.swing.*; import javax.swing.event.*; /** Entry point of EduMIPS64 * @author Andrea Spadaccini, Antonella Scandura, Vanni Rizzo * */ public class Main extends JApplet { public static String VERSION; public static String CODENAME; public static String build_date; public static String git_revision; private static CPU cpu; // The last created CPU Worker. Necessary for the Stop menu item. private static CPUSwingWorker cpuWorker; private static Parser parser; private static SymbolTable symTab; private static Memory memory; private static Dinero dinero; private static GUIFrontend front; private static ConfigStore configStore; private static JFileChooser jfc; private static JFrame f = null; private static JMenuItem open; private static JMenuItem reset; private static JMenuItem exit; private static JMenuItem single_cycle; private static JMenuItem run_to; private static JMenuItem multi_cycle; private static JMenuItem aboutUs; private static JMenuItem dinero_tracefile; private static JMenuItem dinFrontend; private static JMenuItem manual; private static JMenuItem settings; private static JMenuItem stop; private static StatusBar sb; private static JMenu file, lastfiles, exec, config, window, help, lang, tools; private static JCheckBoxMenuItem lang_en, lang_it; private static JCheckBoxMenuItem pipelineJCB, registersJCB, memoryJCB, codeJCB, cyclesJCB, statsJCB, ioJCB; public static GUIIO ioFrame; private static IOManager iom; private final static Logger log = Logger.getLogger(Main.class.getName()); private static Map<String, JInternalFrame> mapped_frames; private static java.util.List<JInternalFrame> ordered_frames; private static String openedFile = null; private static boolean debug_mode = false; private static JDesktopPane desk; private static void usage() { showVersion(); System.out.println(CurrentLocale.getString("HT.Options")); System.out.println(CurrentLocale.getString("HT.File")); System.out.println(CurrentLocale.getString("HT.Debug")); System.out.println(CurrentLocale.getString("HT.Help")); System.out.println(CurrentLocale.getString("HT.Reset")); System.out.println(CurrentLocale.getString("HT.Version")); } private static void showVersion() { System.out.println("EduMIPS64 version " + VERSION + " (codename: " + CODENAME + ", git revision " + git_revision + ", built on " + build_date + ") - Ciao 'mbare."); } // Parses the command-line arguments. // Returns the filename to open (if any) and sets parameters such as logging. If necessary, exits. static String parseArgsOrExit(String[] args) { // Checking CLI parameters. String toOpen = null; boolean printUsageAndExit = false, printVersionAndExit = false; if (args.length > 0) { for (int i = 0; i < args.length; ++i) { if (args[i].compareTo("-f") == 0 || args[i].compareTo("--file") == 0) { if (toOpen == null && ++i == args.length) { System.err.println(CurrentLocale.getString("HT.MissingFile") + "\n"); printUsageAndExit = true; } else if (toOpen != null) { System.err.println(CurrentLocale.getString("HT.MultipleFile") + "\n"); printUsageAndExit = true; } else { toOpen = args[i]; } } else if (args[i].compareTo("-d") == 0 || args[i].compareTo("--debug") == 0) { debug_mode = true; } else if (args[i].compareTo("-h") == 0 || args[i].compareTo("--help") == 0) { printUsageAndExit = true; } else if (args[i].compareTo("-v") == 0 || args[i].compareTo("--version") == 0) { printVersionAndExit = true; } else if (args[i].compareTo("-r") == 0 || args[i].compareTo("--reset") == 0) { configStore.resetConfiguration(); } else { System.err.println(CurrentLocale.getString("HT.UnrecognizedArgs") + ": " + args[i] + "\n"); printUsageAndExit = true; } if (printUsageAndExit) { usage(); System.exit(0); } if (printVersionAndExit) { showVersion(); System.exit(0); } } } if (!debug_mode) { // Disable logging message whose level is less than WARNING. Logger rootLogger = log.getParent(); for (Handler h : rootLogger.getHandlers()) { h.setLevel(java.util.logging.Level.WARNING); } } return toOpen; } public static void main(String args[]) { // Meta properties. VERSION = MetaInfo.get("Signature-Version"); CODENAME = MetaInfo.get("Codename"); build_date = MetaInfo.get("Build-Date"); git_revision = MetaInfo.get("Git-Revision"); String toOpen = parseArgsOrExit(args); // Configure logger format. System.setProperty("java.util.logging.SimpleFormatter.format", "%1$tm%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n"); showVersion(); // Creating the main JFrame JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); f = new JFrame(); f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // Maximizing the application Insets screenInsets = f.getToolkit().getScreenInsets(f.getGraphicsConfiguration()); Rectangle screenSize = f.getGraphicsConfiguration().getBounds(); Rectangle maxBounds = new Rectangle(screenInsets.left + screenSize.x, screenInsets.top + screenSize.y, screenSize.x + screenSize.width - screenInsets.right - screenInsets.left, screenSize.y + screenSize.height - screenInsets.bottom - screenInsets.top); f.setMaximizedBounds(maxBounds); f.setBounds(maxBounds); f.setLocation(0, 0); Main mm = new Main(); mm.init(); f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM")); f.setVisible(true); mm.start(); log.info("Simulator started"); if (toOpen != null) { resetSimulator(false); openFile(toOpen); addFileToRecentMenu(toOpen); } f.setExtendedState(f.getExtendedState() | JFrame.MAXIMIZED_BOTH); } private static void addFrame(String name, JInternalFrame f) { mapped_frames.put(name, f); ordered_frames.add(f); try { f.setFrameIcon(new ImageIcon(IMGLoader.getImage(name + ".png"))); } catch (IOException e) { e.printStackTrace(); } desk.add(f); f.setVisible(true); } public void init() { JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); LocalFileUtils lfu = new LocalFileUtils(); configStore = new JavaPrefsConfigStore(ConfigStore.defaults); CurrentLocale.setConfig(configStore); jfc = new JFileChooser(new File(configStore.getString(ConfigKey.LAST_DIR))); desk = new JDesktopPane(); Container cp = (f == null) ? getContentPane() : f.getContentPane(); cp.setLayout(new BorderLayout()); cp.add(createMenuBar(), BorderLayout.NORTH); Memory memory = new Memory(); cpu = new CPU(memory, configStore); cpu.setStatus(CPU.CPUStatus.READY); symTab = new SymbolTable(memory); iom = new IOManager(lfu, memory); dinero = new Dinero(memory); InstructionBuilder instructionBuilder = new InstructionBuilder(memory, iom, cpu, dinero, configStore); parser = new Parser(lfu, symTab, memory, instructionBuilder); front = new GUIFrontend(cpu, memory, configStore); // Internal Frames JInternalFrame pipeFrame = new JInternalFrame("Pipeline", true, false, true, true); pipeFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { pipelineJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { pipelineJCB.setState(true); } }); JInternalFrame registersFrame = new JInternalFrame(CurrentLocale.getString("REGISTERS"), true, false, true, true); registersFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { registersJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { registersJCB.setState(true); } }); JInternalFrame memoryFrame = new JInternalFrame(CurrentLocale.getString("MEMORY"), true, false, true, true); memoryFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { memoryJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { memoryJCB.setState(true); } }); JInternalFrame codeFrame = new JInternalFrame(CurrentLocale.getString("CODE"), true, false, true, true); codeFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { codeJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { codeJCB.setState(true); } }); JInternalFrame cyclesFrame = new JInternalFrame(CurrentLocale.getString("CYCLES"), true, false, true, true); cyclesFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { cyclesJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { cyclesJCB.setState(true); } }); JInternalFrame statsFrame = new JInternalFrame(CurrentLocale.getString("STATS"), true, false, true, true); statsFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { statsJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { statsJCB.setState(true); } }); ioFrame = new GUIIO(CurrentLocale.getString("IO"), true, false, true, true); ioFrame.addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameIconified(InternalFrameEvent e) { ioJCB.setState(false); } public void internalFrameDeiconified(InternalFrameEvent e) { ioJCB.setState(true); } }); // Set the IOManager StdOutput with a Proxy writer from GUIIO iom.setStdOutput(ioFrame.getWriter()); // Set the IOManager StdError with a Proxy writer from GUIIO iom.setStdError(ioFrame.getWriter()); // Set the IOManager StdInput with a Proxy reader from GUIIO iom.setStdInput(ioFrame.getReader()); // Needed for internal frames handling // TODO: The actual approach is a workaround. To do things in the right // way, a new class that derives from JInternalFrame should be created, // with the "name" and "priority" attributes, and every internal frame // should derive from it, in order to remove the need for those two // structures. But time is running out, this is not my main task but // only something I need in order to achieve my objective. Sorry. // --andrea mapped_frames = new HashMap<>(); ordered_frames = new ArrayList<>(); addFrame("cycles", cyclesFrame); addFrame("registers", registersFrame); addFrame("stats", statsFrame); addFrame("pipeline", pipeFrame); addFrame("memory", memoryFrame); addFrame("code", codeFrame); addFrame("io", ioFrame); // Setting icons for the main frame and for the internal frames try { if (f != null) { f.setIconImage(IMGLoader.getImage("ico.png")); } } catch (IOException e) { e.printStackTrace(); } front.setPipelineContainer(pipeFrame.getContentPane()); front.setRegistersContainer(registersFrame.getContentPane()); front.setDataContainer(memoryFrame.getContentPane()); front.setCodeContainer(codeFrame.getContentPane()); front.setCyclesContainer(cyclesFrame.getContentPane()); front.setStatisticsContainer(statsFrame.getContentPane()); sb = new StatusBar(); cp.add(sb.getComponent(), BorderLayout.SOUTH); cp.add(desk, BorderLayout.CENTER); changeShownMenuItems(cpu.getStatus()); } public void start() { // Auto-minimze the log window and the I/O window try { ioFrame.setIcon(true); } catch (java.beans.PropertyVetoException ignored) {} tileWindows(); } /** Gets a reference to the status bar */ public static StatusBar getSB() { return sb; } /** Updates the configuration parameters of CPUGUIThread */ public static void updateCGT() { cpuWorker.updateConfigValues(); } /** Changes the status of running menu items. * @param status a boolean */ public static void setRunningMenuItemsStatus(boolean status) { single_cycle.setEnabled(status); multi_cycle.setEnabled(status); run_to.setEnabled(status); } /** Changes the status of cache-related menu items. * @param status a boolean */ private static void setCacheMenuItemsStatus(boolean status) { tools.setEnabled(status); dinero_tracefile.setEnabled(status); dinFrontend.setEnabled(status); } /** Enables or disables the Stop menu item and the Settings menu item. * @param status boolean */ public static void setStopStatus(boolean status) { stop.setEnabled(status); settings.setEnabled(!status); file.setEnabled(!status); } /** Changes the menu items to show, according to the CPU status. * If the CPU status is READY, then we must make unavailable running menu * items and cache-related menu items; if it's RUNNING, we must show * running menu items but cache menu items should be hidden; in the HALTED * state, only cache-related menu items must be shown, while running menu * items must be hidden. * * @param s the new CPU status * */ public static void changeShownMenuItems(CPU.CPUStatus s) { if (s == CPU.CPUStatus.READY) { log.info("CPU Ready"); setCacheMenuItemsStatus(false); setRunningMenuItemsStatus(false); } else if (s == CPU.CPUStatus.RUNNING) { log.info("CPU Running"); setCacheMenuItemsStatus(false); setRunningMenuItemsStatus(true); } else if (s == CPU.CPUStatus.STOPPING) { log.info("CPU Stopping"); setCacheMenuItemsStatus(false); setRunningMenuItemsStatus(true); } else if (s == CPU.CPUStatus.HALTED) { log.info("CPU Halted"); setCacheMenuItemsStatus(true); setRunningMenuItemsStatus(false); } } /** Opens a file. */ private static void openFile(String file) { log.info("Trying to open " + file); cpu.reset(); symTab.reset(); dinero.reset(); try { // Aggiorniamo i componenti gai front.updateComponents(); front.represent(); } catch (Exception ex) { new ReportDialog(f, ex, CurrentLocale.getString("GUI_STEP_ERROR")); } try { log.info("Before parsing"); try { String absoluteFilename = new File(file).getAbsolutePath(); parser.parse(absoluteFilename); } catch (ParserMultiWarningException pmwe) { new ErrorDialog(f, pmwe.getExceptionList(), CurrentLocale.getString("GUI_PARSER_ERROR"), configStore.getBoolean(ConfigKey.WARNINGS)); } catch (NullPointerException e) { log.info("NullPointerException: " + e.toString()); e.printStackTrace(); } finally { log.info(symTab.toString()); } log.info("After parsing"); // The file has correctly been parsed cpu.setStatus(CPU.CPUStatus.RUNNING); log.info("Set the status to RUNNING"); // Let's fetch the first instruction cpuWorker = new CPUSwingWorker(cpu, front, f, configStore); cpuWorker.setSteps(1); cpuWorker.execute(); while (cpuWorker.isDone()) { Thread.sleep(200); } openedFile = file; log.info("File " + file + " successfully opened"); StringTokenizer token = new StringTokenizer(file, File.separator, false); String nome_file = null; while (token.hasMoreElements()) { nome_file = token.nextToken(); } f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM") + " - " + nome_file); } catch (ParserMultiException ex) { log.info("Error opening " + file); new ErrorDialog(f, ex.getExceptionList(), CurrentLocale.getString("GUI_PARSER_ERROR"), configStore.getBoolean(ConfigKey.WARNINGS)); openedFile = null; f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM")); resetSimulator(false); } catch (ReadException ex) { String tmpfile; if (ex.getMessage().contains("(")) { tmpfile = ex.getMessage().substring(0, ex.getMessage().indexOf("(")); } else { tmpfile = ex.getMessage(); } f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM")); log.info("File not found: " + tmpfile); JOptionPane.showMessageDialog(f, CurrentLocale.getString("FILE_NOT_FOUND") + ": " + tmpfile, "EduMIPS64 - " + CurrentLocale.getString("ERROR"), JOptionPane.ERROR_MESSAGE); } catch (Exception e) { f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM")); log.info("Error opening " + file); new ReportDialog(f, e, CurrentLocale.getString("ERROR")); } } /** Tiles windows. */ private static void tileWindows() { // First of all, we don't have to consider iconified frames, because // the frames to be tiled are the ones that aren't iconified java.util.List<JInternalFrame> list = new ArrayList<>(); for (JInternalFrame f : ordered_frames) { if (!f.isIcon()) { list.add(f); } } int count = list.size(); // Very special cases if (count == 0) { return; } Dimension size = desk.getSize(); if (count == 1) { desk.getDesktopManager().resizeFrame(list.get(0), 0, 0, size.width, size.height); } // Ok, let's start with the code. int maxFramesInARow = 3; // Maybe it'll be customizable... int rows = (new Double(Math.ceil(((double) count) / ((double) maxFramesInARow)))).intValue(); int cols = maxFramesInARow; // Optimization of the space if (count % 2 == 0 && count % maxFramesInARow != 0) { cols--; } int w = size.width / cols; int h = size.height / rows; int x = 0; int y = 0; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { int frame_number = (i * cols) + j; if (frame_number >= count) { break; } JInternalFrame f = list.get(frame_number); if (f.isIcon()) { continue; } desk.getDesktopManager().resizeFrame(f, x, y, w, h); x += w; } y += h; // start the next row x = 0; } } /** Sets the frame titles. Used when the locale is changed. */ private static void setFrameTitles() { if (f != null) { if (openedFile != null) { f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM") + " - " + openedFile); } else { f.setTitle("EduMIPS64 v. " + VERSION + " - " + CurrentLocale.getString("PROSIM")); } } for (Map.Entry<String, JInternalFrame>e : mapped_frames.entrySet()) { e.getValue().setTitle(CurrentLocale.getString(e.getKey().toUpperCase())); } } private static void resetSimulator(boolean reopenFile) { cpu.reset(); symTab.reset(); dinero.reset(); try { iom.reset(); } catch (IOException e1) { log.info("I/O error while resetting IOManager"); } cpu.setStatus(CPU.CPUStatus.READY); SwingUtilities.invokeLater(() -> { front.updateComponents(); front.represent(); }); if (openedFile != null && reopenFile) { openFile(openedFile); } changeShownMenuItems(cpu.getStatus()); } /** Sets the menu items captions, adding, if possible, the mnemonic. */ private static void initMenuItems() { setMenuItem(file, "Menu.FILE"); setMenuItem(exec, "Menu.EXECUTE"); setMenuItem(config, "Menu.CONFIGURE"); setMenuItem(window, "Menu.WINDOW"); setMenuItem(help, "Menu.HELP"); setMenuItem(lang, "Menu.CHANGE_LANGUAGE"); setMenuItem(tools, "Menu.TOOLS"); setMenuItem(open, "MenuItem.OPEN"); setMenuItem(lastfiles, "MenuItem.OPENLAST"); setMenuItem(reset, "MenuItem.RESET"); setMenuItem(exit, "MenuItem.EXIT"); setMenuItem(single_cycle, "MenuItem.SINGLE_CYCLE"); setMenuItem(run_to, "MenuItem.RUN_TO"); setMenuItem(multi_cycle, "MenuItem.MULTI_CYCLE"); setMenuItem(lang_en, "MenuItem.ENGLISH"); setMenuItem(lang_it, "MenuItem.ITALIAN"); setMenuItem(dinero_tracefile, "MenuItem.DIN_TRACEFILE"); setMenuItem(aboutUs, "MenuItem.ABOUT_US"); setMenuItem(dinFrontend, "MenuItem.DIN_FRONTEND"); setMenuItem(manual, "MenuItem.MANUAL"); setMenuItem(settings, "Config.ITEM"); setMenuItem(stop, "MenuItem.STOP"); setMenuItem(pipelineJCB, "PIPELINE"); setMenuItem(codeJCB, "CODE"); setMenuItem(cyclesJCB, "CYCLES"); setMenuItem(memoryJCB, "MEMORY"); setMenuItem(statsJCB, "STATS"); setMenuItem(registersJCB, "REGISTERS"); setMenuItem(ioJCB, "IO"); } /** Creates a new menu bar. * @return the menu bar */ private static JMenuBar createMenuBar() { JMenuBar mb = new JMenuBar(); // Creation of all menus and menu items file = new JMenu(); lastfiles = new JMenu(); exec = new JMenu(); config = new JMenu(); window = new JMenu(); help = new JMenu(); lang = new JMenu(); tools = new JMenu(); open = new JMenuItem(); reset = new JMenuItem(); exit = new JMenuItem(); dinero_tracefile = new JMenuItem(); single_cycle = new JMenuItem(); run_to = new JMenuItem(); multi_cycle = new JMenuItem(); stop = new JMenuItem(); JMenuItem tile; dinFrontend = new JMenuItem(); manual = new JMenuItem(); settings = new JMenuItem(); pipelineJCB = new JCheckBoxMenuItem(); codeJCB = new JCheckBoxMenuItem(); memoryJCB = new JCheckBoxMenuItem(); registersJCB = new JCheckBoxMenuItem(); statsJCB = new JCheckBoxMenuItem(); cyclesJCB = new JCheckBoxMenuItem(); ioJCB = new JCheckBoxMenuItem(); // Adding menus to the menu bar mb.add(file); mb.add(exec); mb.add(config); mb.add(tools); mb.add(window); mb.add(help); // ---------------- FILE MENU // Open file file.add(open); open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK)); open.addActionListener(e -> { int val = jfc.showOpenDialog(f); if (val == JFileChooser.APPROVE_OPTION) { String filename = jfc.getSelectedFile().getPath(); configStore.putString(ConfigKey.LAST_DIR, jfc.getCurrentDirectory().getAbsolutePath()); addFileToRecentMenu(filename); resetSimulator(false); openFile(filename); changeShownMenuItems(cpu.getStatus()); } }); // Add recently opened files menu items to the recent files submenu. for (String filename : Arrays.asList(configStore.getString(ConfigKey.FILES).split(File.pathSeparator))) { if (filename.length() > 0) { log.info("Adding '" + filename + "' to recently opened files."); addFileToRecentMenu(filename); } } file.add(lastfiles); // Reset the simulator and the CPU file.add(reset); reset.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK)); reset.addActionListener(e -> resetSimulator(true)); // Write Dinero Tracefile file.add(dinero_tracefile); dinero_tracefile.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_MASK)); dinero_tracefile.addActionListener(e -> { jfc.setSelectedFile(new File(openedFile + ".xdin")); int val = jfc.showSaveDialog(f); if (val == JFileChooser.APPROVE_OPTION) { String filename = jfc.getSelectedFile().getPath(); try { LocalWriter w = new LocalWriter(filename, false); dinero.writeTraceData(w); w.close(); log.info("Wrote dinero tracefile"); } catch (Exception ex) { ex.printStackTrace(); log.info("Exception in DineroTracefile: " + ex); } } }); // Exit file.add(exit); exit.addActionListener(e -> System.exit(0)); // ---------------- EXECUTE MENU // Execute a single simulation step exec.add(single_cycle); single_cycle.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0)); single_cycle.addActionListener(e -> { cpuWorker = new CPUSwingWorker(cpu, front, f, configStore); cpuWorker.setSteps(1); cpuWorker.execute(); }); // Execute the whole program exec.add(run_to); run_to.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F4, 0)); run_to.addActionListener(e -> { cpuWorker = new CPUSwingWorker(cpu, front, f, configStore); cpuWorker.setSteps(-1); cpuWorker.execute(); }); // Execute a fixed number of steps exec.add(multi_cycle); multi_cycle.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F8, 0)); multi_cycle.addActionListener(e -> { cpuWorker = new CPUSwingWorker(cpu, front, f, configStore); cpuWorker.setSteps(configStore.getInt(ConfigKey.N_STEPS)); cpuWorker.execute(); }); // Stops the execution exec.add(stop); stop.setEnabled(false); stop.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F9, 0)); stop.addActionListener(e -> { if (cpuWorker != null) { cpuWorker.stopExecution(); } }); // ---------------- CONFIGURE MENU config.add(settings); settings.addActionListener(e -> new GUIConfig(f, configStore)); // ---------------- LANGUAGE MENU config.add(lang); try { lang_en = new JCheckBoxMenuItem( CurrentLocale.getString("MenuItem.ENGLISH"), new ImageIcon(IMGLoader.getImage("en.png")), configStore.getString(ConfigKey.LANGUAGE).equals("en")); } catch (IOException e) { e.printStackTrace(); } lang.add(lang_en); lang_en.addActionListener(e -> { lang_en.setState(true); lang_it.setState(false); configStore.putString(ConfigKey.LANGUAGE, "en"); initMenuItems(); setFrameTitles(); front.updateLanguageStrings(); // f.setVisible(true); }); try { lang_it = new JCheckBoxMenuItem( CurrentLocale.getString("MenuItem.ITALIAN"), new ImageIcon(IMGLoader.getImage("it.png")), configStore.getString(ConfigKey.LANGUAGE).equals("it")); lang.add(lang_it); } catch (IOException e) { e.printStackTrace(); } lang_it.addActionListener(e -> { lang_it.setState(true); lang_en.setState(false); configStore.putString(ConfigKey.LANGUAGE, "it"); initMenuItems(); setFrameTitles(); front.updateLanguageStrings(); // f.setVisible(true); }); // ---------------- HELP MENU manual = new JMenuItem(); help.add(manual); manual.addActionListener(e -> { try { GUIHelp.showHelp(null, "id"); } catch (Exception exx) { new ReportDialog(null, exx, "MIAO"); } }); aboutUs = new JMenuItem(CurrentLocale.getString("MenuItem.ABOUT_US")); help.add(aboutUs); aboutUs.addActionListener(e -> { GUIAbout ab = new GUIAbout(null); //ab.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); ab.setVisible(true); }); // ---------------- TOOLS MENU dinFrontend.setEnabled(false); dinFrontend.addActionListener(e -> { JDialog dinFrame = new DineroFrontend(f, dinero, configStore); dinFrame.setModal(true); dinFrame.setVisible(true); }); tools.add(dinFrontend); // ---------------- WINDOW MENU // tile = new JMenuItem("Tile"); tile.addActionListener(e -> tileWindows()); window.add(tile); window.addSeparator(); pipelineJCB.setText(CurrentLocale.getString("pipeline".toUpperCase())); pipelineJCB.setState(true); pipelineJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("pipeline").isIcon(); try { mapped_frames.get("pipeline").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(pipelineJCB); cyclesJCB.setText(CurrentLocale.getString("cycles".toUpperCase())); cyclesJCB.setState(true); cyclesJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("cycles").isIcon(); try { mapped_frames.get("cycles").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(cyclesJCB); registersJCB.setText(CurrentLocale.getString("registers".toUpperCase())); registersJCB.setState(true); registersJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("registers").isIcon(); try { mapped_frames.get("registers").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(registersJCB); statsJCB.setText(CurrentLocale.getString("stats".toUpperCase())); statsJCB.setState(true); statsJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("stats").isIcon(); try { mapped_frames.get("stats").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(statsJCB); memoryJCB.setText(CurrentLocale.getString("memory".toUpperCase())); memoryJCB.setState(true); memoryJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("memory").isIcon(); try { mapped_frames.get("memory").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(memoryJCB); codeJCB.setText(CurrentLocale.getString("code".toUpperCase())); codeJCB.setState(true); codeJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("code").isIcon(); try { mapped_frames.get("code").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(codeJCB); ioJCB.setText(CurrentLocale.getString("log".toUpperCase())); ioJCB.setState(true); ioJCB.addActionListener(e -> { boolean cur_state = mapped_frames.get("io").isIcon(); try { mapped_frames.get("io").setIcon(!cur_state); } catch (java.beans.PropertyVetoException ignored) { } }); window.add(ioJCB); initMenuItems(); return mb; } /** add a new JMenuItem in recent file menu at the position pos for the file "namefile"*/ private static void addFileToRecentMenu(final String filename) { JMenuItem item = new JMenuItem(filename); item.addActionListener(e -> { resetSimulator(false); openFile(filename); addFileToRecentMenu(filename); changeShownMenuItems(cpu.getStatus()); }); // Add at the top of the list. lastfiles.insert(item, 0); // Remove, if present, the old entry pointing to the file just opened. for (int i = 1; i < lastfiles.getItemCount(); ++i) { String cur = ((JMenuItem)lastfiles.getMenuComponent(i)).getText(); if (cur.equals(item.getText())) { lastfiles.remove(i); } } // Trim length. if (lastfiles.getItemCount() > 6) { lastfiles.remove(6); } // Update configuration. StringBuilder files = new StringBuilder(); for (Component c : lastfiles.getMenuComponents()) { if (c instanceof JMenuItem) { files.append(((JMenuItem) c).getText()).append(File.pathSeparator); } } files = new StringBuilder(files.substring(0, files.length() - 1)); configStore.putString(ConfigKey.FILES, files.toString()); } /** Sets the caption of the menu item, adding, if possible, the mnemonic */ private static void setMenuItem(JMenuItem item, String caption) { String localCaption = CurrentLocale.getString(caption); int pos = localCaption.indexOf("_"); if (pos >= 0) { char mnemonic = localCaption.charAt(pos + 1); // The KeyEvent.VK_* constants refer to uppercase letters, so we // need to make the mnemonic uppercase. mnemonic = Character.toUpperCase(mnemonic); item.setMnemonic((int) mnemonic); // Deleting the _ character StringBuilder newLocalCaption = new StringBuilder(); for (int i = 0; i < localCaption.length(); ++i) if (localCaption.charAt(i) != '_') { newLocalCaption.append(localCaption.charAt(i)); } localCaption = newLocalCaption.toString(); } item.setText(localCaption); } public static GUIFrontend getGUIFrontend() { return front; } public static void startPB() { sb.startPB(); } public static void stopPB() { sb.stopPB(); } }