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); }