From 77d6d683ae321b3b696ae29f9fecfd70b4f7ba3f Mon Sep 17 00:00:00 2001 From: patrick Date: Thu, 31 Jul 2014 09:54:59 -0400 Subject: [PATCH] Increased poll time on reload to 1s Added boolean reloadEnabled which can be set to false to disable reloading (currently always true) Editted checkModified (called if and only if a close is requested) to check if the close will be successful (i.e. if it will return true) Added code in checkModified to trigger the stopping of the reload thread when this editor is closed --- app/src/processing/app/Editor.java | 1173 +++++++++++++--------------- 1 file changed, 526 insertions(+), 647 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index ed264f78a..410cbfeec 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -1,24 +1,24 @@ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* - Part of the Processing project - http://processing.org + Part of the Processing project - http://processing.org - Copyright (c) 2004-12 Ben Fry and Casey Reas - Copyright (c) 2001-04 Massachusetts Institute of Technology + Copyright (c) 2004-12 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 + as published by the Free Software Foundation. - 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. + 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 -*/ + 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 processing.app; @@ -47,15 +47,16 @@ import javax.swing.undo.*; */ public abstract class Editor extends JFrame implements RunnerListener { protected Base base; + protected EditorState state; + protected Mode mode; // otherwise, if the window is resized with the message label // set to blank, it's preferredSize() will be fukered - static protected final String EMPTY = - " " + - " " + - " "; + static protected final String EMPTY = " " + + " " + + " "; /** * true if this file has not yet been given a name by the user @@ -63,22 +64,31 @@ public abstract class Editor extends JFrame implements RunnerListener { // private boolean untitled; private PageFormat pageFormat; + private PrinterJob printerJob; // file and sketch menus for re-inserting items private JMenu fileMenu; + // private JMenuItem saveMenuItem; // private JMenuItem saveAsMenuItem; private JMenu sketchMenu; protected EditorHeader header; + protected EditorToolbar toolbar; + protected JEditTextArea textarea; + protected EditorStatus status; + protected JSplitPane splitPane; + protected JPanel consolePanel; + protected EditorConsole console; + protected EditorLineStatus lineStatus; // currently opened program @@ -89,48 +99,60 @@ public abstract class Editor extends JFrame implements RunnerListener { // undo fellers private JMenuItem undoItem, redoItem; + protected UndoAction undoAction; + protected RedoAction redoAction; + /** the currently selected tab's undo manager */ private UndoManager undo; + // used internally for every edit. Groups hotkey-event text manipulations and // groups multi-character inputs into a single undos. private CompoundEdit compoundEdit; + // timer to decide when to group characters into an undo private Timer timer; + private TimerTask endUndoEvent; + // true if inserting text, false if removing text private boolean isInserting; + // maintain caret position during undo operations private final Stack caretUndoStack = new Stack(); + private final Stack caretRedoStack = new Stack(); private FindReplace find; + JMenu toolsMenu; + JMenu modeMenu; ArrayList coreTools; + public ArrayList contribTools; - // protected Editor(final Base base, String path, int[] location, final Mode mode) { - protected Editor(final Base base, String path, EditorState state, final Mode mode) { + protected Editor(final Base base, String path, EditorState state, + final Mode mode) { super("Processing", state.checkConfig()); this.base = base; this.state = state; this.mode = mode; - Toolkit.setIcon(this); // TODO should this be per-mode? + Toolkit.setIcon(this); // TODO should this be per-mode? // Install default actions for Run, Present, etc. // resetHandlers(); // add listener to handle window close box hit event addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - base.handleClose(Editor.this, false); - } - }); + public void windowClosing(WindowEvent e) { + base.handleClose(Editor.this, false); + } + }); // don't close the window when clicked, the app will take care // of that via the handleQuitInternal() methods // http://dev.processing.org/bugs/show_bug.cgi?id=440 @@ -138,29 +160,29 @@ public abstract class Editor extends JFrame implements RunnerListener { // When bringing a window to front, let the Base know addWindowListener(new WindowAdapter() { - public void windowActivated(WindowEvent e) { + public void windowActivated(WindowEvent e) { // EditorConsole.systemOut.println("editor window activated"); - base.handleActivated(Editor.this); + base.handleActivated(Editor.this); // mode.handleActivated(Editor.this); - fileMenu.insert(base.getSketchbookMenu(), 2); - fileMenu.insert(base.getRecentMenu(), 3); + fileMenu.insert(base.getSketchbookMenu(), 2); + fileMenu.insert(base.getRecentMenu(), 3); // fileMenu.insert(mode.getExamplesMenu(), 3); - sketchMenu.insert(mode.getImportMenu(), 4); - mode.insertToolbarRecentMenu(); - } + sketchMenu.insert(mode.getImportMenu(), 4); + mode.insertToolbarRecentMenu(); + } - // added for 1.0.5 - // http://dev.processing.org/bugs/show_bug.cgi?id=1260 - public void windowDeactivated(WindowEvent e) { + // added for 1.0.5 + // http://dev.processing.org/bugs/show_bug.cgi?id=1260 + public void windowDeactivated(WindowEvent e) { // EditorConsole.systemErr.println("editor window deactivated"); // mode.handleDeactivated(Editor.this); - fileMenu.remove(base.getSketchbookMenu()); - fileMenu.remove(base.getRecentMenu()); + fileMenu.remove(base.getSketchbookMenu()); + fileMenu.remove(base.getRecentMenu()); // fileMenu.remove(mode.getExamplesMenu()); - sketchMenu.remove(mode.getImportMenu()); - mode.removeToolbarRecentMenu(); - } - }); + sketchMenu.remove(mode.getImportMenu()); + mode.removeToolbarRecentMenu(); + } + }); timer = new Timer(); @@ -237,6 +259,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // end an undo-chunk any time the caret moves unless it's when text is edited textarea.addCaretListener(new CaretListener() { String lastText = textarea.getText(); + public void caretUpdate(CaretEvent e) { String newText = textarea.getText(); if (lastText.equals(newText) && isDirectEdit()) { @@ -255,8 +278,11 @@ public abstract class Editor extends JFrame implements RunnerListener { state.apply(this); // Set the minimum size for the editor window - setMinimumSize(new Dimension(Preferences.getInteger("editor.window.width.min"), - Preferences.getInteger("editor.window.height.min"))); + setMinimumSize(new Dimension( + Preferences + .getInteger("editor.window.width.min"), + Preferences + .getInteger("editor.window.height.min"))); // Bring back the general options for the editor applyPreferences(); @@ -282,7 +308,6 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - /** * Broken out to get modes working for GSOC, but this needs a longer-term * solution where the listeners are handled properly. @@ -291,22 +316,18 @@ public abstract class Editor extends JFrame implements RunnerListener { return new JEditTextArea(new PdeTextAreaDefaults(mode)); } - public EditorState getEditorState() { return state; } - public void removeRecent() { base.removeRecent(this); } - public void addRecent() { base.handleRecent(this); } - /** * Handles files dragged & dropped from the desktop and into the editor * window. Dragging files into the editor window is the same as using @@ -322,12 +343,12 @@ public abstract class Editor extends JFrame implements RunnerListener { int successful = 0; try { - DataFlavor uriListFlavor = - new DataFlavor("text/uri-list;class=java.lang.String"); + DataFlavor uriListFlavor = new DataFlavor( + "text/uri-list;class=java.lang.String"); if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { - java.util.List list = (java.util.List) - transferable.getTransferData(DataFlavor.javaFileListFlavor); + java.util.List list = (java.util.List) transferable + .getTransferData(DataFlavor.javaFileListFlavor); for (int i = 0; i < list.size(); i++) { File file = (File) list.get(i); if (sketch.addFile(file)) { @@ -337,10 +358,11 @@ public abstract class Editor extends JFrame implements RunnerListener { } else if (transferable.isDataFlavorSupported(uriListFlavor)) { // Some platforms (Mac OS X and Linux, when this began) preferred // this method of moving files. - String data = (String)transferable.getTransferData(uriListFlavor); + String data = (String) transferable.getTransferData(uriListFlavor); String[] pieces = PApplet.splitTokens(data, "\r\n"); for (int i = 0; i < pieces.length; i++) { - if (pieces[i].startsWith("#")) continue; + if (pieces[i].startsWith("#")) + continue; String path = null; if (pieces[i].startsWith("file:///")) { @@ -354,8 +376,10 @@ public abstract class Editor extends JFrame implements RunnerListener { } } } catch (Exception e) { - Base.showWarning("Drag & Drop Problem", - "An error occurred while trying to add files to the sketch.", e); + Base + .showWarning("Drag & Drop Problem", + "An error occurred while trying to add files to the sketch.", + e); return false; } @@ -372,17 +396,14 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - public Base getBase() { return base; } - public Mode getMode() { return mode; } - protected void initModeMenu() { modeMenu = new JMenu(); ButtonGroup modeGroup = new ButtonGroup(); @@ -410,24 +431,18 @@ public abstract class Editor extends JFrame implements RunnerListener { modeMenu.add(addLib); } - public JMenu getModeMenu() { return modeMenu; } - - // public Settings getTheme() { // return mode.getTheme(); // } - abstract public EditorToolbar createToolbar(); - abstract public Formatter createFormatter(); - // protected void setPlacement(int[] location) { // setBounds(location[0], location[1], location[2], location[3]); // if (location[4] != 0) { @@ -452,74 +467,59 @@ public abstract class Editor extends JFrame implements RunnerListener { // return location; // } - protected void setDividerLocation(int pos) { splitPane.setDividerLocation(pos); } - protected int getDividerLocation() { return splitPane.getDividerLocation(); } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** - * Read and apply new values from the preferences, either because - * the app is just starting up, or the user just finished messing - * with things in the Preferences window. + * Read and apply new values from the preferences, either because the app is + * just starting up, or the user just finished messing with things in the + * Preferences window. */ protected void applyPreferences() { // Update fonts and other items controllable from the prefs textarea.getPainter().updateAppearance(); textarea.repaint(); - + console.updateAppearance(); - + // All of this code was specific to using an external editor. /* -// // apply the setting for 'use external editor' -// boolean external = Preferences.getBoolean("editor.external"); -// textarea.setEditable(!external); -// saveMenuItem.setEnabled(!external); -// saveAsMenuItem.setEnabled(!external); - - TextAreaPainter painter = textarea.getPainter(); -// if (external) { -// // disable line highlight and turn off the caret when disabling -// Color color = mode.getColor("editor.external.bgcolor"); -// painter.setBackground(color); -// painter.setLineHighlightEnabled(false); -// textarea.setCaretVisible(false); -// } else { - Color color = mode.getColor("editor.bgcolor"); - painter.setBackground(color); - boolean highlight = Preferences.getBoolean("editor.linehighlight"); - painter.setLineHighlightEnabled(highlight); - textarea.setCaretVisible(true); -// } - - // apply changes to the font size for the editor -// painter.setFont(Preferences.getFont("editor.font")); - - // in case tab expansion stuff has changed - // removing this, just checking prefs directly instead -// listener.applyPreferences(); - - // in case moved to a new location - // For 0125, changing to async version (to be implemented later) - //sketchbook.rebuildMenus(); - // For 0126, moved into Base, which will notify all editors. - //base.rebuildMenusAsync(); + * // // apply the setting for 'use external editor' // boolean external = + * Preferences.getBoolean("editor.external"); // + * textarea.setEditable(!external); // saveMenuItem.setEnabled(!external); + * // saveAsMenuItem.setEnabled(!external); + * + * TextAreaPainter painter = textarea.getPainter(); // if (external) { // // + * disable line highlight and turn off the caret when disabling // Color + * color = mode.getColor("editor.external.bgcolor"); // + * painter.setBackground(color); // painter.setLineHighlightEnabled(false); + * // textarea.setCaretVisible(false); // } else { Color color = + * mode.getColor("editor.bgcolor"); painter.setBackground(color); boolean + * highlight = Preferences.getBoolean("editor.linehighlight"); + * painter.setLineHighlightEnabled(highlight); + * textarea.setCaretVisible(true); // } + * + * // apply changes to the font size for the editor // + * painter.setFont(Preferences.getFont("editor.font")); + * + * // in case tab expansion stuff has changed // removing this, just + * checking prefs directly instead // listener.applyPreferences(); + * + * // in case moved to a new location // For 0125, changing to async version + * (to be implemented later) //sketchbook.rebuildMenus(); // For 0126, moved + * into Base, which will notify all editors. //base.rebuildMenusAsync(); */ } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - protected void buildMenuBar() { JMenuBar menubar = new JMenuBar(); menubar = new JMenuBar(); @@ -554,10 +554,8 @@ public abstract class Editor extends JFrame implements RunnerListener { setJMenuBar(menubar); } - abstract public JMenu buildFileMenu(); - // public JMenu buildFileMenu(Editor editor) { // return buildFileMenu(editor, null); // } @@ -566,25 +564,24 @@ public abstract class Editor extends JFrame implements RunnerListener { // // most of these items are per-mode // protected JMenu buildFileMenu(Editor editor, JMenuItem[] exportItems) { - protected JMenu buildFileMenu(JMenuItem[] exportItems) { JMenuItem item; JMenu fileMenu = new JMenu("File"); item = Toolkit.newJMenuItem("New", 'N'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleNew(); - } - }); + public void actionPerformed(ActionEvent e) { + base.handleNew(); + } + }); fileMenu.add(item); item = Toolkit.newJMenuItem("Open...", 'O'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleOpenPrompt(); - } - }); + public void actionPerformed(ActionEvent e) { + base.handleOpenPrompt(); + } + }); fileMenu.add(item); fileMenu.add(base.getSketchbookMenu()); @@ -673,17 +670,14 @@ public abstract class Editor extends JFrame implements RunnerListener { return fileMenu; } - // public void setSaveItem(JMenuItem item) { // saveMenuItem = item; // } - // public void setSaveAsItem(JMenuItem item) { // saveAsMenuItem = item; // } - protected JMenu buildEditMenu() { JMenu menu = new JMenu("Edit"); JMenuItem item; @@ -696,7 +690,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // http://code.google.com/p/processing/issues/detail?id=363 if (Base.isWindows()) { redoItem = Toolkit.newJMenuItem("Redo", 'Y'); - } else { // Linux and OS X + } else { // Linux and OS X redoItem = Toolkit.newJMenuItemShift("Redo", 'Z'); } redoItem.addActionListener(redoAction = new RedoAction()); @@ -707,107 +701,98 @@ public abstract class Editor extends JFrame implements RunnerListener { // TODO "cut" and "copy" should really only be enabled // if some text is currently selected item = Toolkit.newJMenuItem("Cut", 'X'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCut(); - } - }); - menu.add(item); - - item = Toolkit.newJMenuItem("Copy", 'C'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - textarea.copy(); - } - }); - menu.add(item); - - item = Toolkit.newJMenuItemShift("Copy as HTML", 'C'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCopyAsHTML(); - } - }); - menu.add(item); - - item = Toolkit.newJMenuItem("Paste", 'V'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - textarea.paste(); - sketch.setModified(true); - } - }); - menu.add(item); - - item = Toolkit.newJMenuItem("Select All", 'A'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - textarea.selectAll(); - } - }); - menu.add(item); - - /* - menu.addSeparator(); - - item = Toolkit.newJMenuItem("Delete Selected Lines", 'D'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - handleDeleteLines(); + handleCut(); } }); menu.add(item); - item = new JMenuItem("Move Selected Lines Up"); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, Event.ALT_MASK)); + item = Toolkit.newJMenuItem("Copy", 'C'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleMoveLines(true); - } - }); + public void actionPerformed(ActionEvent e) { + textarea.copy(); + } + }); menu.add(item); - item = new JMenuItem("Move Selected Lines Down"); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, Event.ALT_MASK)); + item = Toolkit.newJMenuItemShift("Copy as HTML", 'C'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleMoveLines(false); - } - }); + public void actionPerformed(ActionEvent e) { + handleCopyAsHTML(); + } + }); menu.add(item); + + item = Toolkit.newJMenuItem("Paste", 'V'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.paste(); + sketch.setModified(true); + } + }); + menu.add(item); + + item = Toolkit.newJMenuItem("Select All", 'A'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.selectAll(); + } + }); + menu.add(item); + + /* + * menu.addSeparator(); + * + * item = Toolkit.newJMenuItem("Delete Selected Lines", 'D'); + * item.addActionListener(new ActionListener() { public void + * actionPerformed(ActionEvent e) { handleDeleteLines(); } }); + * menu.add(item); + * + * item = new JMenuItem("Move Selected Lines Up"); + * item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + * Event.ALT_MASK)); item.addActionListener(new ActionListener() { public + * void actionPerformed(ActionEvent e) { handleMoveLines(true); } }); + * menu.add(item); + * + * item = new JMenuItem("Move Selected Lines Down"); + * item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + * Event.ALT_MASK)); item.addActionListener(new ActionListener() { public + * void actionPerformed(ActionEvent e) { handleMoveLines(false); } }); + * menu.add(item); */ menu.addSeparator(); item = Toolkit.newJMenuItem("Auto Format", 'T'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleAutoFormat(); - } + public void actionPerformed(ActionEvent e) { + handleAutoFormat(); + } }); menu.add(item); item = Toolkit.newJMenuItem("Comment/Uncomment", '/'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCommentUncomment(); - } + public void actionPerformed(ActionEvent e) { + handleCommentUncomment(); + } }); menu.add(item); item = Toolkit.newJMenuItem("Increase Indent", ']'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleIndentOutdent(true); - } + public void actionPerformed(ActionEvent e) { + handleIndentOutdent(true); + } }); menu.add(item); item = Toolkit.newJMenuItem("Decrease Indent", '['); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleIndentOutdent(false); - } + public void actionPerformed(ActionEvent e) { + handleIndentOutdent(false); + } }); menu.add(item); @@ -815,57 +800,55 @@ public abstract class Editor extends JFrame implements RunnerListener { item = Toolkit.newJMenuItem("Find...", 'F'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (find == null) { - find = new FindReplace(Editor.this); - } - //new FindReplace(Editor.this).show(); - find.setVisible(true); + public void actionPerformed(ActionEvent e) { + if (find == null) { + find = new FindReplace(Editor.this); } - }); + //new FindReplace(Editor.this).show(); + find.setVisible(true); + } + }); menu.add(item); // TODO find next should only be enabled after a // search has actually taken place item = Toolkit.newJMenuItem("Find Next", 'G'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (find != null) { - find.findNext(); - } + public void actionPerformed(ActionEvent e) { + if (find != null) { + find.findNext(); } - }); + } + }); menu.add(item); item = Toolkit.newJMenuItemShift("Find Previous", 'G'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (find != null) { - find.findPrevious(); - } + public void actionPerformed(ActionEvent e) { + if (find != null) { + find.findPrevious(); } - }); + } + }); menu.add(item); // For Arduino and Mac, this should be command-E, but that currently conflicts with Export Applet item = Toolkit.newJMenuItemAlt("Use Selection for Find", 'F'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (find == null) { - find = new FindReplace(Editor.this); - } - find.setFindText(getSelectedText()); + public void actionPerformed(ActionEvent e) { + if (find == null) { + find = new FindReplace(Editor.this); } - }); + find.setFindText(getSelectedText()); + } + }); menu.add(item); return menu; } - abstract public JMenu buildSketchMenu(); - protected JMenu buildSketchMenu(JMenuItem[] runItems) { JMenuItem item; sketchMenu = new JMenu("Sketch"); @@ -880,26 +863,26 @@ public abstract class Editor extends JFrame implements RunnerListener { item = Toolkit.newJMenuItem("Show Sketch Folder", 'K'); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Base.openFolder(sketch.getFolder()); - } - }); + public void actionPerformed(ActionEvent e) { + Base.openFolder(sketch.getFolder()); + } + }); sketchMenu.add(item); item.setEnabled(Base.openFolderAvailable()); item = new JMenuItem("Add File..."); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - sketch.handleAddFile(); - } - }); + public void actionPerformed(ActionEvent e) { + sketch.handleAddFile(); + } + }); sketchMenu.add(item); sketchMenu.addSeparator(); // final Editor editorName = this; - - sketchMenu.addMenuListener(new MenuListener() { + + sketchMenu.addMenuListener(new MenuListener() { // Menu Listener that populates the menu only when the menu is opened List menuList = new ArrayList(); @@ -910,17 +893,18 @@ public abstract class Editor extends JFrame implements RunnerListener { JMenuItem item; for (final Editor editor : base.getEditors()) { //if (Editor.this.getSketch().getName().trim().contains(editor2.getSketch().getName().trim())) - if (getSketch().getMainFilePath().equals(editor.getSketch().getMainFilePath())) { + if (getSketch().getMainFilePath().equals(editor.getSketch() + .getMainFilePath())) { item = new JCheckBoxMenuItem(editor.getSketch().getName()); item.setSelected(true); } else { item = new JMenuItem(editor.getSketch().getName()); } - item.setText(editor.getSketch().getName() + - " (" + editor.getMode().getTitle() + ")"); + item.setText(editor.getSketch().getName() + " (" + + editor.getMode().getTitle() + ")"); // Action listener to bring the appropriate sketch in front - item.addActionListener(new ActionListener() { + item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -953,10 +937,8 @@ public abstract class Editor extends JFrame implements RunnerListener { return sketchMenu; } - abstract public void handleImportLibrary(String jarPath); - public JMenu getToolMenu() { if (toolsMenu == null) { rebuildToolMenu(); @@ -964,13 +946,11 @@ public abstract class Editor extends JFrame implements RunnerListener { return toolsMenu; } - // protected void rebuildToolList() { // coreTools = ToolContribution.list(Base.getToolsFolder(), true); // contribTools = ToolContribution.list(Base.getSketchbookToolsFolder(), true); // } - public void rebuildToolMenu() { if (toolsMenu == null) { toolsMenu = new JMenu("Tools"); @@ -996,7 +976,6 @@ public abstract class Editor extends JFrame implements RunnerListener { toolsMenu.add(item); } - // /** // * Attempt to init or run a Tool from the safety of a try/catch block that // * will report errors to the user. @@ -1028,8 +1007,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // } // return false; // } - - + void addToolItem(final Tool tool, HashMap toolItems) { String title = tool.getMenuTitle(); final JMenuItem item = new JMenuItem(title); @@ -1040,24 +1018,24 @@ public abstract class Editor extends JFrame implements RunnerListener { tool.run(); } catch (NoSuchMethodError nsme) { - statusError("\"" + tool.getMenuTitle() + "\" is not" + - "compatible with this version of Processing"); + statusError("\"" + tool.getMenuTitle() + "\" is not" + + "compatible with this version of Processing"); //nsme.printStackTrace(); Base.log("Incompatible tool found during tool.run()", nsme); item.setEnabled(false); } catch (Exception ex) { - statusError("An error occurred inside \"" + tool.getMenuTitle() + "\""); + statusError("An error occurred inside \"" + tool.getMenuTitle() + + "\""); ex.printStackTrace(); item.setEnabled(false); - } + } } }); //menu.add(item); toolItems.put(title, item); } - protected void addTools(JMenu menu, ArrayList tools) { HashMap toolItems = new HashMap(); @@ -1066,31 +1044,35 @@ public abstract class Editor extends JFrame implements RunnerListener { tool.init(Editor.this); // If init() fails, the item won't be added to the menu addToolItem(tool, toolItems); - + // With the exceptions, we can't call statusError because the window // isn't completely set up yet. Also not gonna pop up a warning because // people may still be running different versions of Processing. // TODO Once the dust settles on 2.x, change this to Base.showError() // and open the Tools folder instead of showing System.err.println(). - + } catch (NoSuchMethodError nsme) { - System.err.println("\"" + tool.getMenuTitle() + "\" is not " + - "compatible with this version of Processing"); - System.err.println("The " + nsme.getMessage() + " method no longer exists."); + System.err.println("\"" + tool.getMenuTitle() + "\" is not " + + "compatible with this version of Processing"); + System.err.println("The " + nsme.getMessage() + + " method no longer exists."); Base.log("Incompatible Tool found during tool.init()", nsme); } catch (NoClassDefFoundError ncdfe) { - System.err.println("\"" + tool.getMenuTitle() + "\" is not " + - "compatible with this version of Processing"); - System.err.println("The " + ncdfe.getMessage() + " class is no longer available."); + System.err.println("\"" + tool.getMenuTitle() + "\" is not " + + "compatible with this version of Processing"); + System.err.println("The " + ncdfe.getMessage() + + " class is no longer available."); Base.log("Incompatible Tool found during tool.init()", ncdfe); } catch (Error err) { - System.err.println("An error occurred inside \"" + tool.getMenuTitle() + "\""); + System.err.println("An error occurred inside \"" + tool.getMenuTitle() + + "\""); err.printStackTrace(); } catch (Exception ex) { - System.err.println("An exception occurred inside \"" + tool.getMenuTitle() + "\""); + System.err.println("An exception occurred inside \"" + + tool.getMenuTitle() + "\""); ex.printStackTrace(); } } @@ -1105,7 +1087,6 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - /** * Override this if you want a special menu for your particular 'mode'. */ @@ -1113,7 +1094,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return null; } - protected void addToolMenuItem(JMenu menu, String className) { try { Class toolClass = Class.forName(className); @@ -1137,7 +1117,6 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - protected JMenu addInternalTools(JMenu menu) { // JMenuItem item; // item = createToolMenuItem("processing.app.tools.AutoFormatTool"); @@ -1175,54 +1154,37 @@ public abstract class Editor extends JFrame implements RunnerListener { return menu; } + /* + * // testing internal web server to serve up docs from a zip file item = new + * JMenuItem("Web Server Test"); item.addActionListener(new ActionListener() { + * public void actionPerformed(ActionEvent e) { //WebServer ws = new + * WebServer(); SwingUtilities.invokeLater(new Runnable() { public void run() + * { try { int port = + * WebServer.launch("/Users/fry/coconut/processing/build/shared/reference.zip" + * ); Base.openURL("http://127.0.0.1:" + port + "/reference/setup_.html"); + * + * } catch (IOException e1) { e1.printStackTrace(); } } }); } }); + * menu.add(item); + */ /* - // testing internal web server to serve up docs from a zip file - item = new JMenuItem("Web Server Test"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - //WebServer ws = new WebServer(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - try { - int port = WebServer.launch("/Users/fry/coconut/processing/build/shared/reference.zip"); - Base.openURL("http://127.0.0.1:" + port + "/reference/setup_.html"); - - } catch (IOException e1) { - e1.printStackTrace(); - } - } - }); - } - }); - menu.add(item); - */ - - /* - item = new JMenuItem("Browser Test"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - //Base.openURL("http://processing.org/learning/gettingstarted/"); - //JFrame browserFrame = new JFrame("Browser"); - BrowserStartup bs = new BrowserStartup("jar:file:/Users/fry/coconut/processing/build/shared/reference.zip!/reference/setup_.html"); - bs.initUI(); - bs.launch(); - } - }); - menu.add(item); - */ - + * item = new JMenuItem("Browser Test"); item.addActionListener(new + * ActionListener() { public void actionPerformed(ActionEvent e) { + * //Base.openURL("http://processing.org/learning/gettingstarted/"); //JFrame + * browserFrame = new JFrame("Browser"); BrowserStartup bs = new + * BrowserStartup( + * "jar:file:/Users/fry/coconut/processing/build/shared/reference.zip!/reference/setup_.html" + * ); bs.initUI(); bs.launch(); } }); menu.add(item); + */ abstract public JMenu buildHelpMenu(); - public void showReference(String filename) { File file = new File(mode.getReferenceFolder(), filename); // Prepend with file:// and also encode spaces & other characters Base.openURL(file.toURI().toString()); } - static public void showChanges() { // http://code.google.com/p/processing/issues/detail?id=1520 if (!Base.isCommandLine()) { @@ -1230,10 +1192,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - class UndoAction extends AbstractAction { public UndoAction() { super("Undo"); @@ -1259,7 +1219,8 @@ public abstract class Editor extends JFrame implements RunnerListener { updateUndoState(); redoAction.updateRedoState(); if (sketch != null) { - sketch.setModified(!getText().equals(sketch.getCurrentCode().getSavedProgram())); + sketch.setModified(!getText().equals(sketch.getCurrentCode() + .getSavedProgram())); } } @@ -1284,7 +1245,6 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - class RedoAction extends AbstractAction { public RedoAction() { super("Redo"); @@ -1309,7 +1269,8 @@ public abstract class Editor extends JFrame implements RunnerListener { updateRedoState(); undoAction.updateUndoState(); if (sketch != null) { - sketch.setModified(!getText().equals(sketch.getCurrentCode().getSavedProgram())); + sketch.setModified(!getText().equals(sketch.getCurrentCode() + .getSavedProgram())); } } @@ -1327,16 +1288,13 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - // these will be done in a more generic way soon, more like: // setHandler("action name", Runnable); // but for the time being, working out the kinks of how many things to // abstract from the editor in this fashion. - // public void setHandlers(Runnable runHandler, Runnable presentHandler, // Runnable stopHandler, // Runnable exportHandler, Runnable exportAppHandler) { @@ -1347,7 +1305,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // this.exportAppHandler = exportAppHandler; // } - // public void resetHandlers() { // runHandler = new DefaultRunHandler(); // presentHandler = new DefaultPresentHandler(); @@ -1356,10 +1313,8 @@ public abstract class Editor extends JFrame implements RunnerListener { // exportAppHandler = new DefaultExportAppHandler(); // } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** * Gets the current sketch object. */ @@ -1367,10 +1322,9 @@ public abstract class Editor extends JFrame implements RunnerListener { return sketch; } - /** - * Get the JEditTextArea object for use (not recommended). This should only - * be used in obscure cases that really need to hack the internals of the + * Get the JEditTextArea object for use (not recommended). This should only be + * used in obscure cases that really need to hack the internals of the * JEditTextArea. Most tools should only interface via the get/set functions * found in this class. This will maintain compatibility with future releases, * which will not use JEditTextArea. @@ -1379,7 +1333,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea; } - /** * Get the contents of the current buffer. Used by the Sketch class. */ @@ -1387,7 +1340,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getText(); } - /** * Get a range of text from the current buffer. */ @@ -1395,7 +1347,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getText(start, stop - start); } - /** * Replace the entire contents of the front-most tab. */ @@ -1405,7 +1356,6 @@ public abstract class Editor extends JFrame implements RunnerListener { stopCompoundEdit(); } - public void insertText(String what) { startCompoundEdit(); int caret = getCaretOffset(); @@ -1414,10 +1364,9 @@ public abstract class Editor extends JFrame implements RunnerListener { stopCompoundEdit(); } - /** - * Called to update the text but not switch to a different set of code - * (which would affect the undo manager). + * Called to update the text but not switch to a different set of code (which + * would affect the undo manager). */ // public void setText2(String what, int start, int stop) { // beginCompoundEdit(); @@ -1432,17 +1381,14 @@ public abstract class Editor extends JFrame implements RunnerListener { // textarea.requestFocus(); // get the caret blinking // } - public String getSelectedText() { return textarea.getSelectedText(); } - public void setSelectedText(String what) { textarea.setSelectedText(what); } - public void setSelection(int start, int stop) { // make sure that a tool isn't asking for a bad location start = PApplet.constrain(start, 0, textarea.getDocumentLength()); @@ -1451,18 +1397,16 @@ public abstract class Editor extends JFrame implements RunnerListener { textarea.select(start, stop); } - /** - * Get the position (character offset) of the caret. With text selected, - * this will be the last character actually selected, no matter the direction - * of the selection. That is, if the user clicks and drags to select lines - * 7 up to 4, then the caret position will be somewhere on line four. + * Get the position (character offset) of the caret. With text selected, this + * will be the last character actually selected, no matter the direction of + * the selection. That is, if the user clicks and drags to select lines 7 up + * to 4, then the caret position will be somewhere on line four. */ public int getCaretOffset() { return textarea.getCaretPosition(); } - /** * True if some text is currently selected. */ @@ -1470,7 +1414,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.isSelectionActive(); } - /** * Get the beginning point of the current selection. */ @@ -1478,7 +1421,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getSelectionStart(); } - /** * Get the end point of the current selection. */ @@ -1486,7 +1428,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getSelectionStop(); } - /** * Get text for a specified line. */ @@ -1494,7 +1435,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getLineText(line); } - /** * Replace the text on a specified line. */ @@ -1505,7 +1445,6 @@ public abstract class Editor extends JFrame implements RunnerListener { stopCompoundEdit(); } - /** * Get character offset for the start of a given line of text. */ @@ -1513,7 +1452,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getLineStartOffset(line); } - /** * Get character offset for end of a given line of text. */ @@ -1521,7 +1459,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getLineStopOffset(line); } - /** * Get the number of lines in the currently displayed buffer. */ @@ -1529,7 +1466,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return textarea.getLineCount(); } - /** * Use before a manipulating text to group editing operations together as a * single undo. Use stopCompoundEdit() once finished. @@ -1539,7 +1475,6 @@ public abstract class Editor extends JFrame implements RunnerListener { compoundEdit = new CompoundEdit(); } - /** * Use with startCompoundEdit() to group edit operations in a single undo. */ @@ -1555,23 +1490,20 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - public int getScrollPosition() { return textarea.getVerticalScrollPosition(); } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** - * Switch between tabs, this swaps out the Document object - * that's currently being manipulated. + * Switch between tabs, this swaps out the Document object that's currently + * being manipulated. */ protected void setCode(SketchCode code) { SyntaxDocument document = (SyntaxDocument) code.getDocument(); - if (document == null) { // this document not yet inited + if (document == null) { // this document not yet inited document = new SyntaxDocument(); code.setDocument(document); @@ -1612,34 +1544,33 @@ public abstract class Editor extends JFrame implements RunnerListener { // connect the undo listener to the editor document.addUndoableEditListener(new UndoableEditListener() { - public void undoableEditHappened(UndoableEditEvent e) { - // if an edit is in progress, reset the timer - if (endUndoEvent != null) { - endUndoEvent.cancel(); - endUndoEvent = null; - startTimerEvent(); - } - - // if this edit is just getting started, create a compound edit - if (compoundEdit == null) { - startCompoundEdit(); - startTimerEvent(); - } - - compoundEdit.addEdit(e.getEdit()); - undoAction.updateUndoState(); - redoAction.updateRedoState(); + public void undoableEditHappened(UndoableEditEvent e) { + // if an edit is in progress, reset the timer + if (endUndoEvent != null) { + endUndoEvent.cancel(); + endUndoEvent = null; + startTimerEvent(); } - }); + + // if this edit is just getting started, create a compound edit + if (compoundEdit == null) { + startCompoundEdit(); + startTimerEvent(); + } + + compoundEdit.addEdit(e.getEdit()); + undoAction.updateUndoState(); + redoAction.updateRedoState(); + } + }); } // update the document object that's in use - textarea.setDocument(document, - code.getSelectionStart(), code.getSelectionStop(), - code.getScrollPosition()); + textarea.setDocument(document, code.getSelectionStart(), + code.getSelectionStop(), code.getScrollPosition()); // textarea.requestFocus(); // get the caret blinking - textarea.requestFocusInWindow(); // required for caret blinking + textarea.requestFocusInWindow(); // required for caret blinking this.undo = code.getUndo(); undoAction.updateUndoState(); @@ -1675,7 +1606,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** * Implements Edit → Cut. */ @@ -1684,7 +1614,6 @@ public abstract class Editor extends JFrame implements RunnerListener { sketch.setModified(true); } - /** * Implements Edit → Copy. */ @@ -1692,13 +1621,11 @@ public abstract class Editor extends JFrame implements RunnerListener { textarea.copy(); } - public void handleCopyAsHTML() { textarea.copyAsHTML(); statusNotice("Code formatted as HTML has been copied to the clipboard."); } - /** * Implements Edit → Paste. */ @@ -1707,7 +1634,6 @@ public abstract class Editor extends JFrame implements RunnerListener { sketch.setModified(true); } - /** * Implements Edit → Select All. */ @@ -1721,88 +1647,69 @@ public abstract class Editor extends JFrame implements RunnerListener { // * with the line beneath // */ /* - public void handleMoveLines(boolean moveUp) { - startCompoundEdit(); - - int startLine = textarea.getSelectionStartLine(); - int stopLine = textarea.getSelectionStopLine(); - - // if more than one line is selected and none of the characters of the end - // line are selected, don't move that line - if (startLine != stopLine - && textarea.getSelectionStop() == textarea.getLineStartOffset(stopLine)) - stopLine--; - - int replacedLine = moveUp ? startLine - 1 : stopLine + 1; - if (replacedLine < 0 || replacedLine >= textarea.getLineCount()) - return; - - final String source = getText(); - - int replaceStart = textarea.getLineStartOffset(replacedLine); - int replaceEnd = textarea.getLineStopOffset(replacedLine); - if (replaceEnd == source.length() + 1) - replaceEnd--; - - int selectionStart = textarea.getLineStartOffset(startLine); - int selectionEnd = textarea.getLineStopOffset(stopLine); - if (selectionEnd == source.length() + 1) - selectionEnd--; - - String replacedText = source.substring(replaceStart, replaceEnd); - String selectedText = source.substring(selectionStart, selectionEnd); - if (replacedLine == textarea.getLineCount() - 1) { - replacedText += "\n"; - selectedText = selectedText.substring(0, selectedText.length() - 1); - } else if (stopLine == textarea.getLineCount() - 1) { - selectedText += "\n"; - replacedText = replacedText.substring(0, replacedText.length() - 1); - } - - int newSelectionStart, newSelectionEnd; - if (moveUp) { - // Change the selection, then change the line above - textarea.select(selectionStart, selectionEnd); - textarea.setSelectedText(replacedText); - - textarea.select(replaceStart, replaceEnd); - textarea.setSelectedText(selectedText); - - newSelectionStart = textarea.getLineStartOffset(startLine - 1); - newSelectionEnd = textarea.getLineStopOffset(stopLine - 1) - 1; - } else { - // Change the line beneath, then change the selection - textarea.select(replaceStart, replaceEnd); - textarea.setSelectedText(selectedText); - - textarea.select(selectionStart, selectionEnd); - textarea.setSelectedText(replacedText); - - newSelectionStart = textarea.getLineStartOffset(startLine + 1); - newSelectionEnd = textarea.getLineStopOffset(stopLine + 1) - 1; - } - - textarea.select(newSelectionStart, newSelectionEnd); - stopCompoundEdit(); - } - */ - + * public void handleMoveLines(boolean moveUp) { startCompoundEdit(); + * + * int startLine = textarea.getSelectionStartLine(); int stopLine = + * textarea.getSelectionStopLine(); + * + * // if more than one line is selected and none of the characters of the end + * // line are selected, don't move that line if (startLine != stopLine && + * textarea.getSelectionStop() == textarea.getLineStartOffset(stopLine)) + * stopLine--; + * + * int replacedLine = moveUp ? startLine - 1 : stopLine + 1; if (replacedLine + * < 0 || replacedLine >= textarea.getLineCount()) return; + * + * final String source = getText(); + * + * int replaceStart = textarea.getLineStartOffset(replacedLine); int + * replaceEnd = textarea.getLineStopOffset(replacedLine); if (replaceEnd == + * source.length() + 1) replaceEnd--; + * + * int selectionStart = textarea.getLineStartOffset(startLine); int + * selectionEnd = textarea.getLineStopOffset(stopLine); if (selectionEnd == + * source.length() + 1) selectionEnd--; + * + * String replacedText = source.substring(replaceStart, replaceEnd); String + * selectedText = source.substring(selectionStart, selectionEnd); if + * (replacedLine == textarea.getLineCount() - 1) { replacedText += "\n"; + * selectedText = selectedText.substring(0, selectedText.length() - 1); } else + * if (stopLine == textarea.getLineCount() - 1) { selectedText += "\n"; + * replacedText = replacedText.substring(0, replacedText.length() - 1); } + * + * int newSelectionStart, newSelectionEnd; if (moveUp) { // Change the + * selection, then change the line above textarea.select(selectionStart, + * selectionEnd); textarea.setSelectedText(replacedText); + * + * textarea.select(replaceStart, replaceEnd); + * textarea.setSelectedText(selectedText); + * + * newSelectionStart = textarea.getLineStartOffset(startLine - 1); + * newSelectionEnd = textarea.getLineStopOffset(stopLine - 1) - 1; } else { // + * Change the line beneath, then change the selection + * textarea.select(replaceStart, replaceEnd); + * textarea.setSelectedText(selectedText); + * + * textarea.select(selectionStart, selectionEnd); + * textarea.setSelectedText(replacedText); + * + * newSelectionStart = textarea.getLineStartOffset(startLine + 1); + * newSelectionEnd = textarea.getLineStopOffset(stopLine + 1) - 1; } + * + * textarea.select(newSelectionStart, newSelectionEnd); stopCompoundEdit(); } + */ /* - public void handleDeleteLines() { - int startLine = textarea.getSelectionStartLine(); - int stopLine = textarea.getSelectionStopLine(); - - int start = textarea.getLineStartOffset(startLine); - int end = textarea.getLineStopOffset(stopLine); - if (end == getText().length() + 1) - end--; - - textarea.select(start, end); - textarea.setSelectedText(""); - } - */ - + * public void handleDeleteLines() { int startLine = + * textarea.getSelectionStartLine(); int stopLine = + * textarea.getSelectionStopLine(); + * + * int start = textarea.getLineStartOffset(startLine); int end = + * textarea.getLineStopOffset(stopLine); if (end == getText().length() + 1) + * end--; + * + * textarea.select(start, end); textarea.setSelectedText(""); } + */ public void handleAutoFormat() { final String source = getText(); @@ -1811,7 +1718,7 @@ public abstract class Editor extends JFrame implements RunnerListener { final String formattedText = createFormatter().format(source); // save current (rough) selection point int selectionEnd = getSelectionStop(); - + // boolean wasVisible = // textarea.getSelectionStopLine() >= textarea.getFirstLine() && // textarea.getSelectionStopLine() < textarea.getLastLine(); @@ -1829,7 +1736,7 @@ public abstract class Editor extends JFrame implements RunnerListener { int scrollPos = textarea.getVerticalScrollPosition(); setText(formattedText); setSelection(selectionEnd, selectionEnd); - + // Put the scrollbar position back, otherwise it jumps on each format. // Since we're not doing a good job of maintaining position anyway, // a more complicated workaround here is fairly pointless. @@ -1854,10 +1761,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - abstract public String getCommentPrefix(); - protected void handleCommentUncomment() { startCompoundEdit(); @@ -1917,17 +1822,14 @@ public abstract class Editor extends JFrame implements RunnerListener { sketch.setModified(true); } - public void handleIndent() { handleIndentOutdent(true); } - public void handleOutdent() { handleIndentOutdent(false); } - public void handleIndentOutdent(boolean indent) { int tabSize = Preferences.getInteger("editor.tabs.size"); String tabString = Editor.EMPTY.substring(0, tabSize); @@ -1955,7 +1857,7 @@ public abstract class Editor extends JFrame implements RunnerListener { textarea.select(location, location); textarea.setSelectedText(tabString); - } else { // outdent + } else { // outdent int last = Math.min(location + tabSize, textarea.getDocumentLength()); textarea.select(location, last); // Don't eat code if it's not indented @@ -1972,7 +1874,6 @@ public abstract class Editor extends JFrame implements RunnerListener { sketch.setModified(true); } - static public boolean checkParen(char[] array, int index, int stop) { // boolean paren = false; // int stepper = i + 1; @@ -2009,15 +1910,14 @@ public abstract class Editor extends JFrame implements RunnerListener { return false; } - protected boolean functionable(char c) { return (c == '_') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } - /** - * Check the current selection for reference. If no selection is active, + * Check the current selection for reference. If no selection is active, * expand the current selection. + * * @return */ protected String referenceCheck(boolean selectIfFound) { @@ -2029,7 +1929,7 @@ public abstract class Editor extends JFrame implements RunnerListener { start = temp; } char[] c = textarea.getText().toCharArray(); - + // System.out.println("checking reference"); if (start == stop) { while (start > 0 && functionable(c[start - 1])) { @@ -2051,8 +1951,7 @@ public abstract class Editor extends JFrame implements RunnerListener { } return ref; } - - + protected void handleFindReference() { String ref = referenceCheck(true); if (ref != null) { @@ -2066,55 +1965,38 @@ public abstract class Editor extends JFrame implements RunnerListener { } } } - - + /* - protected void handleFindReference() { - String text = textarea.getSelectedText().trim(); - - if (text.length() == 0) { - statusNotice("First select a word to find in the reference."); - - } else { - char[] c = textarea.getText().toCharArray(); - int after = Math.max(textarea.getSelectionStart(), textarea.getSelectionStop()); - if (checkParen(c, after, c.length)) { - text += "_"; - System.out.println("looking up ref for " + text); - } - String referenceFile = mode.lookupReference(text); - System.out.println("reference file is " + referenceFile); - if (referenceFile == null) { - statusNotice("No reference available for \"" + text + "\""); - } else { - showReference(referenceFile + ".html"); - } - } - } - - - protected void handleFindReference() { - String text = textarea.getSelectedText().trim(); - - if (text.length() == 0) { - statusNotice("First select a word to find in the reference."); - - } else { - String referenceFile = mode.lookupReference(text); - //System.out.println("reference file is " + referenceFile); - if (referenceFile == null) { - statusNotice("No reference available for \"" + text + "\""); - } else { - showReference(referenceFile + ".html"); - } - } - } - */ - + * protected void handleFindReference() { String text = + * textarea.getSelectedText().trim(); + * + * if (text.length() == 0) { + * statusNotice("First select a word to find in the reference."); + * + * } else { char[] c = textarea.getText().toCharArray(); int after = + * Math.max(textarea.getSelectionStart(), textarea.getSelectionStop()); if + * (checkParen(c, after, c.length)) { text += "_"; + * System.out.println("looking up ref for " + text); } String referenceFile = + * mode.lookupReference(text); System.out.println("reference file is " + + * referenceFile); if (referenceFile == null) { + * statusNotice("No reference available for \"" + text + "\""); } else { + * showReference(referenceFile + ".html"); } } } + * + * + * protected void handleFindReference() { String text = + * textarea.getSelectedText().trim(); + * + * if (text.length() == 0) { + * statusNotice("First select a word to find in the reference."); + * + * } else { String referenceFile = mode.lookupReference(text); + * //System.out.println("reference file is " + referenceFile); if + * (referenceFile == null) { statusNotice("No reference available for \"" + + * text + "\""); } else { showReference(referenceFile + ".html"); } } } + */ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** * Set the location of the sketch run window. Used by Runner to update the * Editor about window drag events while the sketch is running. @@ -2123,7 +2005,6 @@ public abstract class Editor extends JFrame implements RunnerListener { sketchWindowLocation = p; } - /** * Get the last location of the sketch's run window. Used by Runner to make * the window show up in the same location as when it was last closed. @@ -2132,42 +2013,45 @@ public abstract class Editor extends JFrame implements RunnerListener { return sketchWindowLocation; } - // public void internalCloseRunner() { // mode.internalCloseRunner(this); // } - /** * Check if the sketch is modified and ask user to save changes. + * * @return false if canceling the close/quit operation */ protected boolean checkModified() { - if (!sketch.isModified()) return true; + boolean ret; + if (!sketch.isModified()){ + stopReloadThread = true; + return true; + } // As of Processing 1.0.10, this always happens immediately. // http://dev.processing.org/bugs/show_bug.cgi?id=1456 // With Java 7u40 on OS X, need to bring the window forward. toFront(); - + String prompt = "Save changes to " + sketch.getName() + "? "; if (!Base.isMacOS()) { - int result = - JOptionPane.showConfirmDialog(this, prompt, "Close", - JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE); + int result = JOptionPane + .showConfirmDialog(this, prompt, "Close", + JOptionPane.YES_NO_CANCEL_OPTION, + JOptionPane.QUESTION_MESSAGE); if (result == JOptionPane.YES_OPTION) { - return handleSave(true); + ret = handleSave(true); } else if (result == JOptionPane.NO_OPTION) { - return true; // ok to continue + ret = true; // ok to continue - } else if (result == JOptionPane.CANCEL_OPTION || - result == JOptionPane.CLOSED_OPTION) { - return false; + } else if (result == JOptionPane.CANCEL_OPTION + || result == JOptionPane.CLOSED_OPTION) { + ret = false; } else { throw new IllegalStateException(); @@ -2184,20 +2068,17 @@ public abstract class Editor extends JFrame implements RunnerListener { // Pane formatting adapted from the quaqua guide // http://www.randelshofer.ch/quaqua/guide/joptionpane.html - JOptionPane pane = - new JOptionPane(" " + - " " + - "Do you want to save changes to this sketch
" + - " before closing?
" + - "

If you don't save, your changes will be lost.", - JOptionPane.QUESTION_MESSAGE); + JOptionPane pane = new JOptionPane(" " + + " " + + "Do you want to save changes to this sketch
" + + " before closing?
" + + "

If you don't save, your changes will be lost.", + JOptionPane.QUESTION_MESSAGE); - String[] options = new String[] { - "Save", "Cancel", "Don't Save" - }; + String[] options = new String[] { "Save", "Cancel", "Don't Save" }; pane.setOptions(options); // highlight the safest option ala apple hig @@ -2212,22 +2093,26 @@ public abstract class Editor extends JFrame implements RunnerListener { dialog.setVisible(true); Object result = pane.getValue(); - if (result == options[0]) { // save (and close/quit) - return handleSave(true); + if (result == options[0]) { // save (and close/quit) + ret = handleSave(true); - } else if (result == options[2]) { // don't save (still close/quit) - return true; + } else if (result == options[2]) { // don't save (still close/quit) + ret = true; - } else { // cancel? - return false; + } else { // cancel? + ret = false; } } + if (ret) { + //the sketch is closing + stopReloadThread = true; + } + return ret; } - /** - * Open a sketch from a particular path, but don't check to save changes. - * Used by Sketch.saveAs() to re-open a sketch after the "Save As" + * Open a sketch from a particular path, but don't check to save changes. Used + * by Sketch.saveAs() to re-open a sketch after the "Save As" */ // protected void handleOpenUnchecked(String path, int codeIndex, // int selStart, int selStop, int scrollPos) { @@ -2242,7 +2127,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // textarea.setScrollPosition(scrollPos); // } - /** * Second stage of open, occurs after having checked to see if the * modifications (if any) to the previous sketch need to be saved. @@ -2271,37 +2155,32 @@ public abstract class Editor extends JFrame implements RunnerListener { + mode.getDefaultExtension(), null); return false; } else { - final String properParent = - file.getName().substring(0, file.getName().lastIndexOf('.')); - - Object[] options = { "OK", "Cancel" }; - String prompt = - "The file \"" + file.getName() + "\" needs to be inside\n" + - "a sketch folder named \"" + properParent + "\".\n" + - "Create this folder, move the file, and continue?"; + final String properParent = file.getName().substring(0, + file.getName() + .lastIndexOf('.')); - int result = JOptionPane.showOptionDialog(this, - prompt, - "Moving", + Object[] options = { "OK", "Cancel" }; + String prompt = "The file \"" + file.getName() + + "\" needs to be inside\n" + "a sketch folder named \"" + properParent + + "\".\n" + "Create this folder, move the file, and continue?"; + + int result = JOptionPane.showOptionDialog(this, prompt, "Moving", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0]); + null, options, options[0]); if (result == JOptionPane.YES_OPTION) { // create properly named folder File properFolder = new File(file.getParent(), properParent); if (properFolder.exists()) { - Base.showWarning("Error", - "A folder named \"" + properParent + "\" " + - "already exists. Can't open sketch.", null); + Base.showWarning("Error", "A folder named \"" + properParent + "\" " + + "already exists. Can't open sketch.", null); return false; } if (!properFolder.mkdirs()) { //throw new IOException("Couldn't create sketch folder"); - Base.showWarning("Error", - "Could not create the sketch folder.", null); + Base + .showWarning("Error", "Could not create the sketch folder.", null); return false; } // copy the sketch inside @@ -2332,7 +2211,7 @@ public abstract class Editor extends JFrame implements RunnerListener { return false; } initFileChangeListener(); - + header.rebuild(); updateTitle(); // Disable untitled setting from previous document, if any @@ -2352,20 +2231,29 @@ public abstract class Editor extends JFrame implements RunnerListener { // return false; // } } - //true when the file is saved, before the next scan for updates private boolean saved; - + private boolean didReload; - + + //TODO set to appropriate value + private boolean reloadEnabled=true; + //the time between polls in ms - private final long FILE_CHECK_DELAY = 100; - + private final long FILE_CHECK_DELAY = 1000; + + private boolean stopReloadThread = false; + //the key which is being used to poll the fs for changes private WatchKey key = null; private void initFileChangeListener() { + //if it is disabled, don't bother starting one + if (!reloadEnabled) { + return; + } + try { WatchService watchService = FileSystems.getDefault().newWatchService(); key = sketch.getFolder().toPath() @@ -2382,6 +2270,7 @@ public abstract class Editor extends JFrame implements RunnerListener { //if the key is null for some reason, don't bother attaching a listener to it, they can deal without one if (finKey != null) { //the key can now be polled for changes in the files + stopReloadThread = false; Thread th = new Thread(new Runnable() { @Override public void run() { @@ -2393,6 +2282,16 @@ public abstract class Editor extends JFrame implements RunnerListener { } catch (InterruptedException e) { } List> events = finKey.pollEvents(); + + //called when a sketch is closed + if (stopReloadThread) { + break; + } + //if it is disabled after being started, stop it + if (!reloadEnabled) { + break; + } + processFileEvents(events); //if the directory was deleted, then quit the loop @@ -2420,12 +2319,12 @@ public abstract class Editor extends JFrame implements RunnerListener { //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX //this makes things.... complicated //System.out.println(e.context()); - + //if the file was saved, don't prompt anything if (saved) break; //if we already reloaded in this cycle, then don't reload again - if (didReload){ + if (didReload) { break; } if (e.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY)) { @@ -2450,10 +2349,9 @@ public abstract class Editor extends JFrame implements RunnerListener { saved = false; } - /** - * Set the title of the PDE window based on the current sketch, i.e. - * something like "sketch_070752a - Processing 0126" + * Set the title of the PDE window based on the current sketch, i.e. something + * like "sketch_070752a - Processing 0126" */ public void updateTitle() { setTitle(sketch.getName() + " | Processing " + Base.getVersionName()); @@ -2468,15 +2366,14 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - /** - * Actually handle the save command. If 'immediately' is set to false, - * this will happen in another thread so that the message area - * will update and the save button will stay highlighted while the - * save is happening. If 'immediately' is true, then it will happen - * immediately. This is used during a quit, because invokeLater() - * won't run properly while a quit is happening. This fixes - * Bug 276. + * Actually handle the save command. If 'immediately' is set to false, this + * will happen in another thread so that the message area will update and the + * save button will stay highlighted while the save is happening. If + * 'immediately' is true, then it will happen immediately. This is used during + * a quit, because invokeLater() won't run properly while a quit is happening. + * This fixes Bug + * 276. */ public boolean handleSave(boolean immediately) { // handleStop(); // 0136 @@ -2490,15 +2387,14 @@ public abstract class Editor extends JFrame implements RunnerListener { } else { EventQueue.invokeLater(new Runnable() { - public void run() { - handleSaveImpl(); - } - }); + public void run() { + handleSaveImpl(); + } + }); } return true; } - protected void handleSaveImpl() { statusNotice("Saving..."); try { @@ -2520,7 +2416,6 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - public boolean handleSaveAs() { statusNotice("Saving..."); try { @@ -2541,7 +2436,6 @@ public abstract class Editor extends JFrame implements RunnerListener { return true; } - /** * Handler for File → Page Setup. */ @@ -2557,7 +2451,6 @@ public abstract class Editor extends JFrame implements RunnerListener { //System.out.println("page format is " + pageFormat); } - /** * Handler for File → Print. */ @@ -2591,17 +2484,17 @@ public abstract class Editor extends JFrame implements RunnerListener { //printerJob = null; // clear this out? } - /** - * Grab current contents of the sketch window, advance the console, - * stop any other running sketches... not in that order. + * Grab current contents of the sketch window, advance the console, stop any + * other running sketches... not in that order. */ public void prepareRun() { internalCloseRunner(); statusEmpty(); // do this to advance/clear the terminal window / dos prompt / etc - for (int i = 0; i < 10; i++) System.out.println(); + for (int i = 0; i < 10; i++) + System.out.println(); // clear the console on each run, unless the user doesn't want to if (Preferences.getBoolean("console.auto_clear")) { @@ -2622,20 +2515,16 @@ public abstract class Editor extends JFrame implements RunnerListener { // } } - /** - * Halt the current runner for whatever reason. Might be the VM dying, - * the window closing, an error... + * Halt the current runner for whatever reason. Might be the VM dying, the + * window closing, an error... */ abstract public void internalCloseRunner(); - abstract public void deactivateRun(); - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** * Show an error in the status bar. */ @@ -2645,7 +2534,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // toolbar.deactivate(EditorToolbar.RUN); } - /** * Show an exception in the editor status bar. */ @@ -2700,7 +2588,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // e.printStackTrace(); } - /** * Show a notice message in the editor status bar. */ @@ -2708,29 +2595,25 @@ public abstract class Editor extends JFrame implements RunnerListener { status.notice(msg); } - public void clearNotice(String msg) { if (status.message.equals(msg)) { statusEmpty(); } } - /** * Returns the current notice message in the editor status bar. */ - public String getStatusMessage(){ + public String getStatusMessage() { return status.message; } - - + /** - * Returns the current mode of the editor status bar: NOTICE, ERR or EDIT. + * Returns the current mode of the editor status bar: NOTICE, ERR or EDIT. */ - public int getStatusMode(){ + public int getStatusMode() { return status.mode; } - /** * Clear the status area. @@ -2739,73 +2622,69 @@ public abstract class Editor extends JFrame implements RunnerListener { statusNotice(EMPTY); } - public void startIndeterminate() { status.startIndeterminate(); } - public void stopIndeterminate() { status.stopIndeterminate(); } - public void statusHalt() { // stop called by someone else } - public boolean isHalted() { return false; } - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** * Returns the edit popup menu. */ class TextAreaPopup extends JPopupMenu { JMenuItem cutItem; - JMenuItem copyItem; - JMenuItem discourseItem; - JMenuItem referenceItem; + JMenuItem copyItem; + + JMenuItem discourseItem; + + JMenuItem referenceItem; public TextAreaPopup() { JMenuItem item; cutItem = new JMenuItem("Cut"); cutItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCut(); - } + public void actionPerformed(ActionEvent e) { + handleCut(); + } }); this.add(cutItem); copyItem = new JMenuItem("Copy"); copyItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCopy(); - } - }); + public void actionPerformed(ActionEvent e) { + handleCopy(); + } + }); this.add(copyItem); discourseItem = new JMenuItem("Copy as HTML"); discourseItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCopyAsHTML(); - } - }); + public void actionPerformed(ActionEvent e) { + handleCopyAsHTML(); + } + }); this.add(discourseItem); item = new JMenuItem("Paste"); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handlePaste(); - } - }); + public void actionPerformed(ActionEvent e) { + handlePaste(); + } + }); this.add(item); item = new JMenuItem("Select All"); @@ -2820,25 +2699,25 @@ public abstract class Editor extends JFrame implements RunnerListener { item = new JMenuItem("Comment/Uncomment"); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleCommentUncomment(); - } + public void actionPerformed(ActionEvent e) { + handleCommentUncomment(); + } }); this.add(item); item = new JMenuItem("Increase Indent"); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleIndentOutdent(true); - } + public void actionPerformed(ActionEvent e) { + handleIndentOutdent(true); + } }); this.add(item); item = new JMenuItem("Decrease Indent"); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleIndentOutdent(false); - } + public void actionPerformed(ActionEvent e) { + handleIndentOutdent(false); + } }); this.add(item); @@ -2846,10 +2725,10 @@ public abstract class Editor extends JFrame implements RunnerListener { referenceItem = new JMenuItem("Find in Reference"); referenceItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleFindReference(); - } - }); + public void actionPerformed(ActionEvent e) { + handleFindReference(); + } + }); this.add(referenceItem); } @@ -2874,7 +2753,7 @@ public abstract class Editor extends JFrame implements RunnerListener { cutItem.setEnabled(active); copyItem.setEnabled(active); discourseItem.setEnabled(active); - + referenceItem.setEnabled(referenceCheck(false) != null); super.show(component, x, y); }