diff --git a/processing/app/PdeBase.java b/processing/app/PdeBase.java index 0748526aa..ab31f2481 100644 --- a/processing/app/PdeBase.java +++ b/processing/app/PdeBase.java @@ -55,16 +55,13 @@ public class PdeBase extends JFrame implements ActionListener static final String VERSION = "0068 Alpha"; //static Properties properties; + PdePreferences preferences; static Properties keywords; // keyword -> reference html lookup //static Frame frame; // now 'this' static String encoding; static Image icon; - protected UndoAction undoAction; - protected RedoAction redoAction; - static public UndoManager undo = new UndoManager(); // editor needs this guy - // indicator that this is the first time this feller has used p5 static boolean firstTime; @@ -274,100 +271,7 @@ public class PdeBase extends JFrame implements ActionListener // edit menu - - menu = new Menu("Edit"); - - undoItem = new MenuItem("Undo", new MenuShortcut('Z')); - undoItem.addActionListener(undoAction = new UndoAction()); - menu.add(undoItem); - - redoItem = new MenuItem("Redo", new MenuShortcut('Y')); - redoItem.addActionListener(redoAction = new RedoAction()); - menu.add(redoItem); - - menu.addSeparator(); - - // "cut" and "copy" should really only be enabled if some text - // is currently selected - item = new MenuItem("Cut", new MenuShortcut('X')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.textarea.cut(); - } - }); - menu.add(item); - - item = new MenuItem("Copy", new MenuShortcut('C')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.textarea.copy(); - } - }); - menu.add(item); - - item = new MenuItem("Paste", new MenuShortcut('V')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.textarea.paste(); - } - }); - menu.add(item); - - item = new MenuItem("Select All", new MenuShortcut('A')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.textarea.selectAll(); - } - }); - menu.add(item); - - beautifyMenuItem = new MenuItem("Beautify", new MenuShortcut('B')); - beautifyMenuItem.addActionListener(this); - menu.add(beautifyMenuItem); - - menu.addSeparator(); - - item = new MenuItem("Find...", new MenuShortcut('F')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.find(); - } - }); - menu.add(item); - - item = new MenuItem("Find Next", new MenuShortcut('G')); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - editor.findNext(); - } - }); - menu.add(item); - - item = new MenuItem("Find in Reference", new MenuShortcut('F', true)); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (editor.textarea.isSelectionActive()) { - String text = editor.textarea.getSelectedText(); - if (text.length() == 0) { - editor.message("First select a word to find in the reference."); - - } else { - String referenceFile = (String) keywords.get(text); - if (referenceFile == null) { - editor.message("No reference available for \"" + text + "\""); - } else { - showReference(referenceFile); - } - } - } - } - }); - menu.add(item); - - menubar.add(menu); - - Document document = editor.textarea.getDocument(); - document.addUndoableEditListener(new MyUndoableEditListener()); + menubar.add(editor.buildEditMenu()); // sketch menu @@ -466,15 +370,34 @@ public class PdeBase extends JFrame implements ActionListener this.setMenuBar(menubar); + // load preferences and finish up + // handle layout - - //Insets insets = frame.getInsets(); - //Toolkit tk = Toolkit.getDefaultToolkit(); - //Dimension screen = tk.getScreenSize(); - this.pack(); // maybe this should be before the setBounds call + // do window placement before loading sketch stuff + restorePreferences(); + + // now that everything is set up, open last-used sketch, etc. + editor.restorePreferences(); + + show(); + } + // antidote for overthought swing api mess for setting accelerators + + static public JMenuItem newMenuItem(String title, char what) { + return newMenuItem(title, what, false); + } + + static public JMenuItem newMenuItem(String title, char what, boolean shift) { + JMenuItem menuItem = new JMenuItem(title); + menuItem.setAccelerator(KeyStroke.getKeyStroke(what, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | (shift ? ActionEvent.SHIFT_MASK : 0))); + return menuItem; + } + + + public void restorePreferences() { // figure out window placement Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); @@ -509,90 +432,24 @@ public class PdeBase extends JFrame implements ActionListener PdePreferences.getInteger("last.window.height")); } - // now that everything is set up, open last-used sketch, etc. - editor.init(); + applyPreferences(); + } + + public void applyPreferences() { rebuildSketchbookMenu(sketchbookMenu); - //buildSerialMenu(); - this.show(); // added back in for pde } - //This one listens for edits that can be undone. - protected class MyUndoableEditListener implements UndoableEditListener { - public void undoableEditHappened(UndoableEditEvent e) { - //Remember the edit and update the menus. - undo.addEdit(e.getEdit()); - undoAction.updateUndoState(); - redoAction.updateRedoState(); - //System.out.println("setting sketch to modified"); - //if (!editor.sketchModified) editor.setSketchModified(true); - } + public void storePreferences() { + Rectangle bounds = getBounds(); + PdePreferences.setInteger("last.window.x", bounds.x); + PdePreferences.setInteger("last.window.y", bounds.y); + PdePreferences.setInteger("last.window.width", bounds.width); + PdePreferences.setInteger("last.window.height", bounds.height); } - class UndoAction extends AbstractAction { - public UndoAction() { - super("Undo"); - this.setEnabled(false); - } - - public void actionPerformed(ActionEvent e) { - try { - undo.undo(); - } catch (CannotUndoException ex) { - //System.out.println("Unable to undo: " + ex); - //ex.printStackTrace(); - } - updateUndoState(); - redoAction.updateRedoState(); - } - - protected void updateUndoState() { - if (undo.canUndo()) { - this.setEnabled(true); - undoItem.setEnabled(true); - putValue(Action.NAME, undo.getUndoPresentationName()); - } else { - this.setEnabled(false); - undoItem.setEnabled(false); - putValue(Action.NAME, "Undo"); - } - } - } - - - class RedoAction extends AbstractAction { - public RedoAction() { - super("Redo"); - this.setEnabled(false); - } - - public void actionPerformed(ActionEvent e) { - try { - undo.redo(); - } catch (CannotRedoException ex) { - //System.out.println("Unable to redo: " + ex); - //ex.printStackTrace(); - } - updateRedoState(); - undoAction.updateUndoState(); - } - - protected void updateRedoState() { - if (undo.canRedo()) { - this.setEnabled(true); - redoItem.setEnabled(true); - putValue(Action.NAME, undo.getRedoPresentationName()); - } else { - this.setEnabled(false); - redoItem.setEnabled(false); - putValue(Action.NAME, "Redo"); - } - } - } - - // listener for sketchbk items uses getParent() to figure out // the directories above it @@ -624,7 +481,7 @@ public class PdeBase extends JFrame implements ActionListener sketchbookFolder = new File(PdePreferences.get("sketchbook.path", "sketchbook")); - sketchbookPath = sketchbookFolder.getCanonicalPath(); + sketchbookPath = sketchbookFolder.getAbsolutePath(); if (!sketchbookFolder.exists()) { System.err.println("sketchbook folder doesn't exist, " + "making a new one"); @@ -703,7 +560,7 @@ public class PdeBase extends JFrame implements ActionListener String list[] = folder.list(); SketchbookMenuListener listener = - new SketchbookMenuListener(folder.getCanonicalPath()); + new SketchbookMenuListener(folder.getAbsolutePath()); boolean ifound = false; @@ -865,25 +722,42 @@ public class PdeBase extends JFrame implements ActionListener window.show(); } + + /** + * Show the (already created on app init) preferences window. + */ public void handlePrefs() { - new PdePreferences(); - /* - JOptionPane.showMessageDialog(this, //frame, - "Preferences are in the 'lib' folder\n" + - "inside text files named pde.properties\n" + - "and pde_" + platforms[platform] + - ".properties", - "Preferences", - JOptionPane.INFORMATION_MESSAGE); - */ - //System.out.println("now showing preferences"); + // make sure this blocks until finished + preferences.showFrame(); + + // may need to rebuild sketch and other menus + applyPreferences(); + + // next have editor do its thing + editor.appyPreferences(); } + + /** + * Quit, but first ask user if it's ok. Also store preferences + * to disk just in case they want to quit. Final exit() happens + * in PdeEditor since it has the callback from PdeEditorStatus. + */ public void handleQuit() { + storePreferences(); + editor.storePreferences(); + + // this will save the prefs even if quit is cancelled, but who cares + PdePreferences.save(); + + // check to see if the person actually wants to quit editor.doQuit(); } + /** + * Handle menu selections. + */ public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); //System.out.println(command); @@ -953,6 +827,10 @@ public class PdeBase extends JFrame implements ActionListener } + /** + * Given the reference filename from the keywords list, + * builds a URL and passes it to openURL. + */ static public void showReference(String referenceFile) { String currentDir = System.getProperty("user.dir"); openURL(currentDir + File.separator + @@ -1029,13 +907,8 @@ public class PdeBase extends JFrame implements ActionListener #endif } else if (platform == LINUX) { - //String currentDir = System.getProperty("user.dir"); - //Runtime.getRuntime().exec("mozilla "+ currentDir + - // "/reference/index.html"); - // another wild ass guess - - // probably need to replace spaces or use quotes here - Runtime.getRuntime().exec("mozilla " + url); + // how's mozilla sound to ya, laddie? + Runtime.getRuntime().exec(new String[] { "mozilla", url }); } else { System.err.println("unspecified platform"); @@ -1053,7 +926,7 @@ public class PdeBase extends JFrame implements ActionListener */ static public void openFolder(File file) { try { - String folder = file.getCanonicalPath(); + String folder = file.getAbsolutePath(); if (platform == WINDOWS) { // doesn't work diff --git a/processing/app/PdeEditor.java b/processing/app/PdeEditor.java index 816c0b5bb..dc5569f97 100644 --- a/processing/app/PdeEditor.java +++ b/processing/app/PdeEditor.java @@ -119,6 +119,11 @@ public class PdeEditor extends JPanel { static final String TEMP_CLASS = "Temporary"; + // undo fellers + protected UndoAction undoAction; + protected RedoAction redoAction; + static public UndoManager undo = new UndoManager(); // editor needs this guy + public PdeEditor(PdeBase base) { this.base = base; @@ -188,6 +193,10 @@ public class PdeEditor extends JPanel { PdeEditorListener listener = new PdeEditorListener(this, textarea); textarea.pdeEditorListener = listener; + // set the undo stuff for this feller + Document document = textarea.getDocument(); + document.addUndoableEditListener(new PdeUndoableEditListener()); + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); if ((PdeBase.platform == PdeBase.MACOSX) || (PdeBase.platform == PdeBase.MACOS9)) { @@ -278,12 +287,14 @@ public class PdeEditor extends JPanel { /** * Post-constructor setup for the editor area. Loads the last * sketch that was used (if any), and restores other Editor settings. + * The complement to "storePreferences", this is called when the + * application is first launched. */ - public void initPreferences() { - // load the last program that was in use + public void restorePreferences() { + // last sketch that was in use String sketchName = PdePreferences.get("last.sketch.name"); - String sketchDir = PdePreferences.get("last.sketch.directory"); + String sketchDir = PdePreferences.get("last.sketch.path"); if (sketchName != null) { if (new File(sketchDir + File.separator + sketchName).exists()) { @@ -294,19 +305,20 @@ public class PdeEditor extends JPanel { } } - // get the location for the console/editor area divider - + // location for the console/editor area divider int location = PdePreferences.getInteger("last.divider.location"); splitPane.setDividerLocation(location); // read the preferences that are settable in the preferences window - applyPreferences() } + /** + * Apply changes to preferences that come from changes + * by the user in the preferences window. + */ public void applyPreferences() { - // apply the setting for 'use external editor' boolean external = getBoolean("editor.external"); @@ -329,12 +341,198 @@ public class PdeEditor extends JPanel { painter.lineHighlight = PdePreferences.getBoolean("editor.program.linehighlight"); textarea.setCaretVisible(true); } - - - // } + /** + * Store preferences about the editor's current state. + * Called when the application is quitting. + */ + public void storePreferences() { + // last sketch that was in use + PdePreferences.put("last.sketch.name", sketchName); + PdePreference.put("last.sketch.path", sketchDir.getAbsolutePath()); + + // location for the console/editor area divider + int location = splitPane.getDividerLocation(); + PdePreferences.setInteger("last.divider.location", location); + } + + + // ................................................................... + + + public JMenu buildEditMenu() { + JMenu menu = new JMenu("Edit"); + JMenuItem item; + + undoItem = PdeBase.newMenuItem("Undo", 'Z'); + undoItem.addActionListener(undoAction = new UndoAction()); + menu.add(undoItem); + + redoItem = PdeBase.newMenuItem("Redo", 'Y'); + redoItem.addActionListener(redoAction = new RedoAction()); + menu.add(redoItem); + + menu.addSeparator(); + + // "cut" and "copy" should really only be enabled + // if some text is currently selected + item = PdeBase.newMenuItem("Cut", 'X'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.cut(); + } + }); + menu.add(item); + + item = PdeBase.newMenuItem("Copy", 'C'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.copy(); + } + }); + menu.add(item); + + item = PdeBase.newMenuItem("Paste", 'V'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.paste(); + } + }); + menu.add(item); + + item = PdeBase.newMenuItem("Select All", 'A'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + textarea.selectAll(); + } + }); + menu.add(item); + + beautifyMenuItem = PdeBase.newMenuItem("Beautify", 'B'); + beautifyMenuItem.addActionListener(this); + menu.add(beautifyMenuItem); + + menu.addSeparator(); + + item = PdeBase.newMenuItem("Find...", 'F'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + find(); + } + }); + menu.add(item); + + item = PdeBase.newMenuItem("Find Next", 'G'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + findNext(); + } + }); + menu.add(item); + + item = PdeBase.newMenuItem("Find in Reference", 'F', true); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (textarea.isSelectionActive()) { + String text = textarea.getSelectedText(); + if (text.length() == 0) { + message("First select a word to find in the reference."); + + } else { + String referenceFile = (String) keywords.get(text); + if (referenceFile == null) { + message("No reference available for \"" + text + "\""); + } else { + showReference(referenceFile); + } + } + } + } + }); + menu.add(item); + } + + + // This one listens for edits that can be undone. + protected class PdeUndoableEditListener implements UndoableEditListener { + public void undoableEditHappened(UndoableEditEvent e) { + //Remember the edit and update the menus. + undo.addEdit(e.getEdit()); + undoAction.updateUndoState(); + redoAction.updateRedoState(); + //System.out.println("setting sketch to modified"); + //if (!editor.sketchModified) editor.setSketchModified(true); + } + } + + + class UndoAction extends AbstractAction { + public UndoAction() { + super("Undo"); + this.setEnabled(false); + } + + public void actionPerformed(ActionEvent e) { + try { + undo.undo(); + } catch (CannotUndoException ex) { + //System.out.println("Unable to undo: " + ex); + //ex.printStackTrace(); + } + updateUndoState(); + redoAction.updateRedoState(); + } + + protected void updateUndoState() { + if (undo.canUndo()) { + this.setEnabled(true); + undoItem.setEnabled(true); + putValue(Action.NAME, undo.getUndoPresentationName()); + } else { + this.setEnabled(false); + undoItem.setEnabled(false); + putValue(Action.NAME, "Undo"); + } + } + } + + + class RedoAction extends AbstractAction { + public RedoAction() { + super("Redo"); + this.setEnabled(false); + } + + public void actionPerformed(ActionEvent e) { + try { + undo.redo(); + } catch (CannotRedoException ex) { + //System.out.println("Unable to redo: " + ex); + //ex.printStackTrace(); + } + updateRedoState(); + undoAction.updateUndoState(); + } + + protected void updateRedoState() { + if (undo.canRedo()) { + this.setEnabled(true); + redoItem.setEnabled(true); + putValue(Action.NAME, undo.getRedoPresentationName()); + } else { + this.setEnabled(false); + redoItem.setEnabled(false); + putValue(Action.NAME, "Redo"); + } + } + } + + + // ................................................................... + + protected void changeText(String what, boolean emptyUndo) { textarea.setText(what); @@ -1683,10 +1881,10 @@ public class PdeEditor extends JPanel { } } } - PdePreferences.save(); + //PdePreferences.save(); //System.out.println("exiting here"); - System.exit(0); + //System.exit(0); } diff --git a/processing/app/PdePreferences.java b/processing/app/PdePreferences.java index 3b6fa554b..165547eee 100644 --- a/processing/app/PdePreferences.java +++ b/processing/app/PdePreferences.java @@ -169,7 +169,7 @@ public class PdePreferences extends JComponent { } catch (Exception e) { showError("Error reading preferences", "Error reading the preferences file. Please delete\n" + - perferencesFile.getCanonicalPath() + "\n" + + perferencesFile.getAbsolutePath() + "\n" + "and restart Processing.", e); } } @@ -177,7 +177,8 @@ public class PdePreferences extends JComponent { // setup frame for the prefs - frame = new JFrame("Preferences"); + //frame = new JFrame("Preferences"); + frame = new JDialog("Preferences"); frame.setResizable(false); Container pain = this; @@ -225,13 +226,8 @@ public class PdePreferences extends JComponent { int returned = fc.showOpenDialog(new JDialog()); if (returned == JFileChooser.APPROVE_OPTION) { - try { - File file = fc.getSelectedFile(); - sketchbookLocationField.setText(file.getCanonicalPath()); - - } catch (IOException e) { - e.printStackTrace(); - } + File file = fc.getSelectedFile(); + sketchbookLocationField.setText(file.getAbsolutePath()); } } }); @@ -312,7 +308,8 @@ public class PdePreferences extends JComponent { textarea.setBounds(left, top, d.width, d.height); top += d.height + BETWEEN; - // OK Cancel maybe these should be next to the message? + + // [ OK ] [ Cancel ] maybe these should be next to the message? button = new JButton(PROMPT_OK); button.addActionListener(new ActionListener() { @@ -377,6 +374,20 @@ public class PdePreferences extends JComponent { } + // change settings based on what was chosen in the prefs + + public void applyFrame() { + //editor.setExternalEditor(getBoolean("editor.external")); + // put each of the settings into the table + + putBoolean("sketchbook.prompt", sketchPrompBox.getSelected()); + + put("sketchbook.path", sketchbookLocation.getText()); + + putBoolean("editor.external", externalEditorBox.getSelected()); + } + + public void showFrame() { // reset all settings to their actual status @@ -444,14 +455,6 @@ public class PdePreferences extends JComponent { - // change settings based on what was chosen in the prefs - - public void apply() { - //editor.setExternalEditor(getBoolean("editor.external")); - // put each of the settings into the table - } - - // ................................................................. @@ -482,6 +485,8 @@ public class PdePreferences extends JComponent { #endif } + base.storePreferences(); + Properties skprops = new Properties(); //Rectangle window = PdeBase.frame.getBounds(); @@ -497,7 +502,7 @@ public class PdePreferences extends JComponent { skprops.put("last.screen.h", String.valueOf(screen.height)); skprops.put("last.sketch.name", sketchName); - skprops.put("last.sketch.directory", sketchDir.getCanonicalPath()); + skprops.put("last.sketch.directory", sketchDir.getAbsolutePath()); //skprops.put("user.name", userName); skprops.put("last.divider.location", diff --git a/processing/todo.txt b/processing/todo.txt index 61137edaa..523334efe 100644 --- a/processing/todo.txt +++ b/processing/todo.txt @@ -1,5 +1,6 @@ 0068 X ifdef JDK14 around a piece of 1.4 specific window code +X use mozilla for opening urls in linux, switched to more compatible exec() _ "add library" menu item and submenu _ iterate through the 'library' folders