/******************************************************************************* * openDLX - A DLX/MIPS processor simulator. * Copyright (C) 2013 The openDLX project, University of Augsburg, Germany * Project URL: <https://sourceforge.net/projects/opendlx> * Development branch: <https://github.com/smetzlaff/openDLX> * * * 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 3 of the License, or * 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, see <LICENSE>. If not, see * <http://www.gnu.org/licenses/>. ******************************************************************************/ package openDLX.gui.internalframes.concreteframes.editor; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextPane; import javax.swing.JToolBar; import javax.swing.event.UndoableEditEvent; import javax.swing.event.UndoableEditListener; import javax.swing.text.BadLocationException; import javax.swing.text.DefaultHighlighter; import javax.swing.text.Highlighter; import javax.swing.undo.*; import openDLX.gui.GUI_CONST.OpenDLXSimState; import openDLX.gui.MainFrame; import openDLX.gui.command.EventCommandLookUp; import openDLX.gui.command.userLevel.CommandClearEditor; import openDLX.gui.command.userLevel.CommandLoadAndRunFile; import openDLX.gui.command.userLevel.CommandLoadFile; import openDLX.gui.command.userLevel.CommandPerformEditorRedo; import openDLX.gui.command.userLevel.CommandPerformEditorUndo; import openDLX.gui.command.userLevel.CommandRunFromEditor; import openDLX.gui.command.userLevel.CommandSave; import openDLX.gui.internalframes.FrameConfiguration; import openDLX.gui.internalframes.OpenDLXSimInternalFrame; import openDLX.gui.internalframes.factories.InternalFrameFactory; @SuppressWarnings("serial") public final class EditorFrame extends OpenDLXSimInternalFrame implements ActionListener, KeyListener, UndoableEditListener { //the editor frame is a singleton private MainFrame mf; //default size values private final int size_x = 250; private final int size_y = 300; //text area //private JTextArea input; //buttons private JButton run; private JButton load; private JButton loadandrun; private JButton save; private JButton clear; /* TODO * For now the undo/redo functionality is limited to * - character based actions */ private JButton undo; private JButton redo; private static EditorFrame instance = null; private JTextArea jta; private UndoManager undoMgr; private CommandPerformEditorUndo undoCommand; private CommandPerformEditorRedo redoCommand; private int saved_state_hash; private String editor_frame_title; private EditorFrame(String title, MainFrame mf) { super(title, true); editor_frame_title = title; this.mf = mf; initialize(); } public static EditorFrame getInstance(MainFrame mf) { if (instance == null) { instance = new EditorFrame(InternalFrameFactory.getFrameName(EditorFrame.class), mf); FrameConfiguration fc = new FrameConfiguration(instance); fc.loadFrameConfiguration(); } return instance; } @Override protected void initialize() { super.initialize(); setLayout(new BorderLayout()); // input = new JTextArea(); //input.setSize(size_x, size_y); //JScrollPane scroll = new JScrollPane(input); new JTextPane(); // JTextPane jtp = new JTextPane(); /* * final JScrollPane jsp = new JScrollPane(); jtp.setEditorKitForContentType("text/openDLX", new OpenDLXSimEditorKit()); jtp.setContentType("text/openDLX"); jtp.getDocument().addDocumentListener(new DocumentListener() { public String getText() { int caretPosition = jtp.getDocument().getLength(); Element root = jtp.getDocument().getDefaultRootElement(); String text = "1" + System.getProperty("line.separator"); for (int i = 2; i < root.getElementIndex(caretPosition) + 2; i++) { text += i + System.getProperty("line.separator"); } return text; } @Override public void changedUpdate(DocumentEvent de) { lines.setText(getText()); jsp.repaint(); System.out.println(getParent()); } @Override public void insertUpdate(DocumentEvent de) { lines.setText(getText()); jsp.repaint(); System.out.println(getParent()); } @Override public void removeUpdate(DocumentEvent de) { lines.setText(getText()); jsp.repaint(); System.out.println(getParent()); } }); */ jta = new JTextArea(); setSavedState(); JScrollPane scrollPane = new JScrollPane(jta); TextNumberingPanel tln = new TextNumberingPanel(jta); jta.addKeyListener(this); jta.getDocument().addUndoableEditListener(this); scrollPane.setRowHeaderView(tln); add(scrollPane, BorderLayout.CENTER); run = createButton("Assemble", "Assemble and Run [ALT+A]", KeyEvent.VK_A, "/img/icons/tango/run.png"); load = createButton("Load", "Load Program [CRTL+O]", KeyEvent.VK_O, "/img/icons/tango/load.png"); loadandrun = createButton("Load and Run", "Load Program and Run [CRTL+R]", KeyEvent.VK_O, "/img/icons/tango/loadandrun.png"); save = createButton("Save As...", "Save Program As... [ALT+S]", KeyEvent.VK_S, "/img/icons/tango/saveas.png"); clear = createButton("Clear", "Clear All [ALT+C]", KeyEvent.VK_C, "/img/icons/tango/clear.png"); undo = createButton("Undo", "Undo [CTRL+Z]", KeyEvent.VK_U, "/img/icons/tango/undo.png"); redo = createButton("Redo", "Redo [CTRL+SHIFT+Z]", KeyEvent.VK_R, "/img/icons/tango/redo.png"); // if parameter command = null, command is not yet implemented and should be implemented soon EventCommandLookUp.put(run, new CommandRunFromEditor(this)); EventCommandLookUp.put(load, new CommandLoadFile(mf)); EventCommandLookUp.put(loadandrun, new CommandLoadAndRunFile(mf)); EventCommandLookUp.put(save, new CommandSave()); EventCommandLookUp.put(clear, new CommandClearEditor()); // EventCommandLookUp.put(undo, undoCommand); // EventCommandLookUp.put(redo, redoCommand); run.addActionListener(this); load.addActionListener(this); loadandrun.addActionListener(this); save.addActionListener(this); clear.addActionListener(this); undo.addActionListener(this); redo.addActionListener(this); // TODO deactivate toolbar when simulator is in run mode JToolBar toolBar = new JToolBar("Editor toolbar"); toolBar.add(run); toolBar.add(load); toolBar.add(loadandrun); toolBar.add(save); toolBar.add(clear); toolBar.add(undo); toolBar.add(redo); toolBar.setFloatable(false); toolBar.setRollover(false); toolBar.setFocusable(false); add(toolBar, BorderLayout.PAGE_START); setPreferredSize(new Dimension(size_x, size_y)); pack(); setVisible(true); } @Override public void actionPerformed(ActionEvent e) { clean(); EventCommandLookUp.get(e.getSource()).execute(); } @Override public void undoableEditHappened(UndoableEditEvent e) { undoMgr.addEdit(e.getEdit()); } @Override public void update() { } public String getText() { return jta.getText(); } public void setText(String text) { jta.setText(text); } public void insertText(String text) { String tmp = jta.getText(); tmp += text; jta.setText(tmp); } public void colorLine(int l) { Highlighter.HighlightPainter redPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.red); try { System.out.println(l); int startIndex = jta.getLineStartOffset(l); int endIndex = jta.getLineEndOffset(l); jta.getHighlighter().addHighlight(startIndex, endIndex, redPainter); } catch (BadLocationException ble) { System.err.println("Failed coloring editor line"); } } @Override public void clean() { jta.getHighlighter().removeAllHighlights(); } public void validateButtons(OpenDLXSimState currentState) { if (currentState == OpenDLXSimState.RUNNING) { run.setEnabled(false); clear.setEnabled(false); save.setEnabled(false); } else { run.setEnabled(true); clear.setEnabled(true); save.setEnabled(true); } } public void setSavedState() { saved_state_hash = getTextHash(); updateTitle(); } private int getTextHash() { // TODO hashCode() might not be the the most suitable function to safe the editor state return getText().hashCode(); } public boolean isTextSaved() { return (saved_state_hash == getTextHash()); } @Override public void keyReleased(KeyEvent arg0) { updateTitle(); } @Override public void keyTyped(KeyEvent arg0) { // Unused } @Override public void keyPressed(KeyEvent arg0) { // Unused } private void updateTitle() { if(!isTextSaved()) { setTitle("*"+editor_frame_title); } else { setTitle(editor_frame_title); } } public void setUndoManager(UndoManager UndoMgr) { undoMgr = UndoMgr; undoCommand = new CommandPerformEditorUndo(undoMgr); redoCommand = new CommandPerformEditorRedo(undoMgr); EventCommandLookUp.put(undo, undoCommand); EventCommandLookUp.put(redo, redoCommand); } private JButton createButton(String name, String tooltip, int mnemonic, String icon_path) { JButton button = new JButton(); URL icon_url; if((icon_path != null) && ((icon_url = getClass().getResource(icon_path)) != null)) { button.setIcon(new ImageIcon(icon_url)); } else { button.setText(name); } button.setMnemonic(mnemonic); button.setToolTipText(tooltip); button.setFocusable(false); return button; } }