From 15953c16f98fffdff70646e5cba891352bd79a49 Mon Sep 17 00:00:00 2001 From: benfry Date: Sun, 27 Jun 2010 00:06:12 +0000 Subject: [PATCH] start working on modes, half give-up; also make it possible to have no windows open on macosx --- app/src/processing/app/Base.java | 305 +++++++++++++++--- app/src/processing/app/Editor.java | 237 +++----------- app/src/processing/app/EditorHeader.java | 6 +- app/src/processing/app/EditorToolbar.java | 61 +++- app/src/processing/app/Preferences.java | 2 +- .../processing/app/macosx/ThinkDifferent.java | 34 +- 6 files changed, 383 insertions(+), 262 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 20bd1b424..6b2d2c9a9 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -96,6 +96,8 @@ public class Base { java.util.List editors = Collections.synchronizedList(new ArrayList()); Editor activeEditor; + // a lone file menu to be used when all sketch windows are closed + static public JMenu defaultFileMenu; static public void main(final String[] args) { @@ -201,14 +203,16 @@ public class Base { public Base(String[] args) { - platform.init(this); - // Get paths for the libraries and examples in the Processing folder //String workingDirectory = System.getProperty("user.dir"); examplesFolder = getContentFile("examples"); librariesFolder = getContentFile("libraries"); toolsFolder = getContentFile("tools"); + // Put this after loading the examples, so that building the default file + // menu works on Mac OS X (since it needs examplesFolder to be set). + platform.init(this); + // Get the sketchbook path, and make sure it's set properly String sketchbookPath = Preferences.get("sketchbook.path"); @@ -395,6 +399,214 @@ public class Base { */ + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + /** Command on Mac OS X, Ctrl on Windows and Linux */ + static final int SHORTCUT_KEY_MASK = + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + /** Command-W on Mac OS X, Ctrl-W on Windows and Linux */ + static final KeyStroke WINDOW_CLOSE_KEYSTROKE = + KeyStroke.getKeyStroke('W', SHORTCUT_KEY_MASK); + /** Command-Option on Mac OS X, Ctrl-Alt on Windows and Linux */ + static final int SHORTCUT_ALT_KEY_MASK = ActionEvent.ALT_MASK | + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + + + /** + * A software engineer, somewhere, needs to have his abstraction + * taken away. In some countries they jail or beat people for crafting + * the sort of API that would require a five line helper function + * just to set the shortcut key for a menu item. + */ + static public JMenuItem newJMenuItem(String title, int what) { + JMenuItem menuItem = new JMenuItem(title); + int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); + return menuItem; + } + + + /** + * Like newJMenuItem() but adds shift as a modifier for the shortcut. + */ + static public JMenuItem newJMenuItemShift(String title, int what) { + JMenuItem menuItem = new JMenuItem(title); + int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + modifiers |= ActionEvent.SHIFT_MASK; + menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); + return menuItem; + } + + + /** + * Same as newJMenuItem(), but adds the ALT (on Linux and Windows) + * or OPTION (on Mac OS X) key as a modifier. + */ + static public JMenuItem newJMenuItemAlt(String title, int what) { + JMenuItem menuItem = new JMenuItem(title); + //int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); + //menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); + menuItem.setAccelerator(KeyStroke.getKeyStroke(what, SHORTCUT_ALT_KEY_MASK)); + return menuItem; + } + + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + + static JMenu sketchbookMenu; + static JMenu examplesMenu; + static JMenu importMenu; + + + public JMenu buildFileMenu(final Editor editor) { + JMenuItem item; + JMenu fileMenu = new JMenu("File"); + + item = newJMenuItem("New", 'N'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleNew(); + } + }); + fileMenu.add(item); + + item = newJMenuItem("Open...", 'O'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleOpenPrompt(); + } + }); + fileMenu.add(item); + + if (sketchbookMenu == null) { + sketchbookMenu = new JMenu("Sketchbook"); + rebuildSketchbookMenu(sketchbookMenu); + } + fileMenu.add(sketchbookMenu); + + if (examplesMenu == null) { + examplesMenu = new JMenu("Examples"); + rebuildExamplesMenu(examplesMenu); + } + fileMenu.add(examplesMenu); + + item = newJMenuItem("Close", 'W'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleClose(editor); + } + }); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + item = newJMenuItem("Save", 'S'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handleSave(false); + } + }); + editor.setSaveItem(item); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + item = newJMenuItemShift("Save As...", 'S'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handleSaveAs(); + } + }); + editor.setSaveAsItem(item); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + item = newJMenuItem("Export", 'E'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handleExport(); + } + }); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + item = newJMenuItemShift("Export Application", 'E'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handleExportApplication(); + } + }); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + fileMenu.addSeparator(); + + item = newJMenuItemShift("Page Setup", 'P'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handlePageSetup(); + } + }); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + item = newJMenuItem("Print", 'P'); + if (editor != null) { + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + editor.handlePrint(); + } + }); + } else { + item.setEnabled(false); + } + fileMenu.add(item); + + // Mac OS X already has its own preferences and quit menu. + // That's right! Think different, b*tches! + if (!Base.isMacOS()) { + fileMenu.addSeparator(); + + item = newJMenuItem("Preferences", ','); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handlePrefs(); + } + }); + fileMenu.add(item); + + fileMenu.addSeparator(); + + item = newJMenuItem("Quit", 'Q'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + handleQuit(); + } + }); + fileMenu.add(item); + } + return fileMenu; + } + + // ................................................................. @@ -721,27 +933,29 @@ public class Base { // if (Preferences.getBoolean("sketchbook.closing_last_window_quits") || // (editor.untitled && !editor.getSketch().isModified())) { if (Base.isMacOS()) { - Object[] options = { "OK", "Cancel" }; - String prompt = - " " + - " " + - "Are you sure you want to Quit?" + - "

Closing the last open sketch will quit Processing."; + if (defaultFileMenu == null) { + Object[] options = { "OK", "Cancel" }; + String prompt = + " " + + " " + + "Are you sure you want to Quit?" + + "

Closing the last open sketch will quit Processing."; - int result = JOptionPane.showOptionDialog(editor, - prompt, - "Quit", - JOptionPane.YES_NO_OPTION, - JOptionPane.QUESTION_MESSAGE, - null, - options, - options[0]); - if (result == JOptionPane.NO_OPTION || - result == JOptionPane.CLOSED_OPTION) { - return false; + int result = JOptionPane.showOptionDialog(editor, + prompt, + "Quit", + JOptionPane.YES_NO_OPTION, + JOptionPane.QUESTION_MESSAGE, + null, + options, + options[0]); + if (result == JOptionPane.NO_OPTION || + result == JOptionPane.CLOSED_OPTION) { + return false; + } } } @@ -752,8 +966,17 @@ public class Base { // Save out the current prefs state Preferences.save(); - // Since this wasn't an actual Quit event, call System.exit() - System.exit(0); + if (defaultFileMenu == null) { + // Since this wasn't an actual Quit event, call System.exit() + System.exit(0); + + } else { + editor.setVisible(false); + editor.dispose(); + defaultFileMenu.insert(Base.sketchbookMenu, 2); + defaultFileMenu.insert(Base.examplesMenu, 3); + activeEditor = null; + } } else { // More than one editor window open, @@ -837,7 +1060,7 @@ public class Base { EventQueue.invokeLater(new Runnable() { public void run() { //System.out.println("starting rebuild"); - rebuildSketchbookMenu(Editor.sketchbookMenu); + rebuildSketchbookMenu(sketchbookMenu); rebuildToolbarMenu(Editor.toolbarMenu); //System.out.println("done with rebuild"); } @@ -852,7 +1075,7 @@ public class Base { //System.out.println("rebuilding toolbar menu"); // Add the single "Open" item - item = Editor.newJMenuItem("Open...", 'O'); + item = newJMenuItem("Open...", 'O'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleOpenPrompt(); @@ -863,8 +1086,8 @@ public class Base { // Add a list of all sketches and subfolders try { - //boolean sketches = addSketches(menu, getSketchbookFolder(), true); - boolean sketches = addSketches(menu, getSketchbookFolder()); + boolean sketches = addSketches(menu, getSketchbookFolder(), true); + //boolean sketches = addSketches(menu, getSketchbookFolder()); if (sketches) menu.addSeparator(); } catch (IOException e) { e.printStackTrace(); @@ -873,8 +1096,8 @@ public class Base { //System.out.println("rebuilding examples menu"); // Add each of the subfolders of examples directly to the menu try { - //addSketches(menu, examplesFolder, true); - addSketches(menu, examplesFolder); + addSketches(menu, examplesFolder, true); + //addSketches(menu, examplesFolder); } catch (IOException e) { e.printStackTrace(); } @@ -886,15 +1109,15 @@ public class Base { //new Exception().printStackTrace(); try { menu.removeAll(); - //addSketches(menu, getSketchbookFolder(), false); - addSketches(menu, getSketchbookFolder()); + addSketches(menu, getSketchbookFolder(), false); + //addSketches(menu, getSketchbookFolder()); } catch (IOException e) { e.printStackTrace(); } } - public void rebuildImportMenu(JMenu importMenu) { + public void rebuildImportMenu() { //JMenu importMenu) { //System.out.println("rebuilding import menu"); importMenu.removeAll(); @@ -928,8 +1151,8 @@ public class Base { //System.out.println("rebuilding examples menu"); try { menu.removeAll(); - //addSketches(menu, examplesFolder, false); - addSketches(menu, examplesFolder); + addSketches(menu, examplesFolder, false); + //addSketches(menu, examplesFolder); } catch (IOException e) { e.printStackTrace(); } @@ -942,7 +1165,8 @@ public class Base { * should replace the sketch in the current window, or false when the * sketch should open in a new window. */ - protected boolean addSketches(JMenu menu, File folder) throws IOException { + protected boolean addSketches(JMenu menu, File folder, + final boolean replaceExisting) throws IOException { // skip .DS_Store files, etc (this shouldn't actually be necessary) if (!folder.isDirectory()) return false; @@ -959,8 +1183,11 @@ public class Base { public void actionPerformed(ActionEvent e) { String path = e.getActionCommand(); if (new File(path).exists()) { -// if (openReplaces) { - if ((e.getModifiers() & ActionEvent.SHIFT_MASK) == 0) { + boolean replace = replaceExisting; + if ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) { + replace = !replace; + } + if (replace) { handleOpenReplace(path); } else { handleOpen(path); @@ -1016,7 +1243,7 @@ public class Base { // needs to be separate var // otherwise would set ifound to false //boolean found = addSketches(submenu, subfolder, openReplaces); //, false); - boolean found = addSketches(submenu, subfolder); //, false); + boolean found = addSketches(submenu, subfolder, false); if (found) { menu.add(submenu); ifound = true; diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index bf51eb440..f374d441b 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -56,16 +56,6 @@ public class Editor extends JFrame implements RunnerListener { " " + " "; - /** Command on Mac OS X, Ctrl on Windows and Linux */ - static final int SHORTCUT_KEY_MASK = - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - /** Command-W on Mac OS X, Ctrl-W on Windows and Linux */ - static final KeyStroke WINDOW_CLOSE_KEYSTROKE = - KeyStroke.getKeyStroke('W', SHORTCUT_KEY_MASK); - /** Command-Option on Mac OS X, Ctrl-Alt on Windows and Linux */ - static final int SHORTCUT_ALT_KEY_MASK = ActionEvent.ALT_MASK | - Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - /** * true if this file has not yet been given a name by the user */ @@ -82,9 +72,6 @@ public class Editor extends JFrame implements RunnerListener { // these menus are shared so that they needn't be rebuilt for all windows // each time a sketch is created, renamed, or moved. static JMenu toolbarMenu; - static JMenu sketchbookMenu; - static JMenu examplesMenu; - static JMenu importMenu; EditorHeader header; EditorStatus status; @@ -105,7 +92,7 @@ public class Editor extends JFrame implements RunnerListener { private Point sketchWindowLocation; private Runner runtime; - private JMenuItem exportAppItem; +// private JMenuItem exportAppItem; private JMenuItem saveMenuItem; private JMenuItem saveAsMenuItem; @@ -153,19 +140,19 @@ public class Editor extends JFrame implements RunnerListener { public void windowActivated(WindowEvent e) { // EditorConsole.systemOut.println("editor window activated"); base.handleActivated(Editor.this); - // re-add the sub-menus that are shared by all windows - fileMenu.insert(sketchbookMenu, 2); - fileMenu.insert(examplesMenu, 3); - sketchMenu.insert(importMenu, 4); +// // re-add the sub-menus that are shared by all windows + fileMenu.insert(Base.sketchbookMenu, 2); + fileMenu.insert(Base.examplesMenu, 3); + sketchMenu.insert(Base.importMenu, 4); } // 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"); - fileMenu.remove(sketchbookMenu); - fileMenu.remove(examplesMenu); - sketchMenu.remove(importMenu); + fileMenu.remove(Base.sketchbookMenu); + fileMenu.remove(Base.examplesMenu); + sketchMenu.remove(Base.importMenu); } }); @@ -430,7 +417,7 @@ public class Editor extends JFrame implements RunnerListener { protected void buildMenuBar() { JMenuBar menubar = new JMenuBar(); menubar = new JMenuBar(); - menubar.add(buildFileMenu()); + menubar.add(fileMenu = base.buildFileMenu(this)); menubar.add(buildEditMenu()); menubar.add(buildSketchMenu()); menubar.add(buildToolsMenu()); @@ -439,131 +426,21 @@ public class Editor extends JFrame implements RunnerListener { } - protected JMenu buildFileMenu() { - JMenuItem item; - fileMenu = new JMenu("File"); + public void setSaveItem(JMenuItem item) { + saveMenuItem = item; + } + - item = newJMenuItem("New", 'N'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleNew(); - } - }); - fileMenu.add(item); - - item = Editor.newJMenuItem("Open...", 'O'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleOpenPrompt(); - } - }); - fileMenu.add(item); - - if (sketchbookMenu == null) { - sketchbookMenu = new JMenu("Sketchbook"); - base.rebuildSketchbookMenu(sketchbookMenu); - } - fileMenu.add(sketchbookMenu); - - if (examplesMenu == null) { - examplesMenu = new JMenu("Examples"); - base.rebuildExamplesMenu(examplesMenu); - } - fileMenu.add(examplesMenu); - - item = Editor.newJMenuItem("Close", 'W'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleClose(Editor.this); - } - }); - fileMenu.add(item); - - saveMenuItem = newJMenuItem("Save", 'S'); - saveMenuItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleSave(false); - } - }); - fileMenu.add(saveMenuItem); - - saveAsMenuItem = newJMenuItemShift("Save As...", 'S'); - saveAsMenuItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleSaveAs(); - } - }); - fileMenu.add(saveAsMenuItem); - - item = newJMenuItem("Export", 'E'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleExport(); - } - }); - fileMenu.add(item); - - exportAppItem = newJMenuItemShift("Export Application", 'E'); - exportAppItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - //buttons.activate(EditorButtons.EXPORT); - //SwingUtilities.invokeLater(new Runnable() { - //public void run() { - handleExportApplication(); - //}}); - } - }); - fileMenu.add(exportAppItem); - - fileMenu.addSeparator(); - - item = newJMenuItemShift("Page Setup", 'P'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handlePageSetup(); - } - }); - fileMenu.add(item); - - item = newJMenuItem("Print", 'P'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handlePrint(); - } - }); - fileMenu.add(item); - - // macosx already has its own preferences and quit menu - if (!Base.isMacOS()) { - fileMenu.addSeparator(); - - item = newJMenuItem("Preferences", ','); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handlePrefs(); - } - }); - fileMenu.add(item); - - fileMenu.addSeparator(); - - item = newJMenuItem("Quit", 'Q'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - base.handleQuit(); - } - }); - fileMenu.add(item); - } - return fileMenu; + public void setSaveAsItem(JMenuItem item) { + saveAsMenuItem = item; } - + protected JMenu buildSketchMenu() { JMenuItem item; sketchMenu = new JMenu("Sketch"); - item = newJMenuItem("Run", 'R'); + item = Base.newJMenuItem("Run", 'R'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleRun(false); @@ -571,7 +448,7 @@ public class Editor extends JFrame implements RunnerListener { }); sketchMenu.add(item); - item = newJMenuItemShift("Present", 'R'); + item = Base.newJMenuItemShift("Present", 'R'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleRun(true); @@ -589,13 +466,14 @@ public class Editor extends JFrame implements RunnerListener { sketchMenu.addSeparator(); - if (importMenu == null) { - importMenu = new JMenu("Import Library..."); - base.rebuildImportMenu(importMenu); + if (Base.importMenu == null) { + Base.importMenu = new JMenu("Import Library..."); + //base.rebuildImportMenu(importMenu); + base.rebuildImportMenu(); } - sketchMenu.add(importMenu); + sketchMenu.add(Base.importMenu); - item = newJMenuItem("Show Sketch Folder", 'K'); + item = Base.newJMenuItem("Show Sketch Folder", 'K'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Base.openFolder(sketch.getFolder()); @@ -883,7 +761,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItemShift("Find in Reference", 'F'); + item = Base.newJMenuItemShift("Find in Reference", 'F'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (textarea.isSelectionActive()) { @@ -901,7 +779,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Visit Processing.org", '5'); + item = Base.newJMenuItem("Visit Processing.org", '5'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Base.openURL("http://processing.org/"); @@ -929,11 +807,11 @@ public class Editor extends JFrame implements RunnerListener { JMenu menu = new JMenu("Edit"); JMenuItem item; - undoItem = newJMenuItem("Undo", 'Z'); + undoItem = Base.newJMenuItem("Undo", 'Z'); undoItem.addActionListener(undoAction = new UndoAction()); menu.add(undoItem); - redoItem = newJMenuItem("Redo", 'Y'); + redoItem = Base.newJMenuItem("Redo", 'Y'); redoItem.addActionListener(redoAction = new RedoAction()); menu.add(redoItem); @@ -941,7 +819,7 @@ public class Editor extends JFrame implements RunnerListener { // TODO "cut" and "copy" should really only be enabled // if some text is currently selected - item = newJMenuItem("Cut", 'X'); + item = Base.newJMenuItem("Cut", 'X'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleCut(); @@ -949,7 +827,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Copy", 'C'); + item = Base.newJMenuItem("Copy", 'C'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { textarea.copy(); @@ -957,7 +835,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItemShift("Copy as HTML", 'C'); + item = Base.newJMenuItemShift("Copy as HTML", 'C'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // SwingUtilities.invokeLater(new Runnable() { @@ -969,7 +847,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Paste", 'V'); + item = Base.newJMenuItem("Paste", 'V'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { textarea.paste(); @@ -978,7 +856,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Select All", 'A'); + item = Base.newJMenuItem("Select All", 'A'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { textarea.selectAll(); @@ -988,7 +866,7 @@ public class Editor extends JFrame implements RunnerListener { menu.addSeparator(); - item = newJMenuItem("Comment/Uncomment", '/'); + item = Base.newJMenuItem("Comment/Uncomment", '/'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleCommentUncomment(); @@ -996,7 +874,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Increase Indent", ']'); + item = Base.newJMenuItem("Increase Indent", ']'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleIndentOutdent(true); @@ -1004,7 +882,7 @@ public class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = newJMenuItem("Decrease Indent", '['); + item = Base.newJMenuItem("Decrease Indent", '['); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleIndentOutdent(false); @@ -1014,7 +892,7 @@ public class Editor extends JFrame implements RunnerListener { menu.addSeparator(); - item = newJMenuItem("Find...", 'F'); + item = Base.newJMenuItem("Find...", 'F'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (find == null) { @@ -1028,7 +906,7 @@ public class Editor extends JFrame implements RunnerListener { // TODO find next should only be enabled after a // search has actually taken place - item = newJMenuItem("Find Next", 'G'); + item = Base.newJMenuItem("Find Next", 'G'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { if (find != null) { @@ -1044,45 +922,6 @@ public class Editor extends JFrame implements RunnerListener { } - /** - * A software engineer, somewhere, needs to have his abstraction - * taken away. In some countries they jail or beat people for writing - * the sort of API that would require a five line helper function - * just to set the command key for a menu item. - */ - static public JMenuItem newJMenuItem(String title, int what) { - JMenuItem menuItem = new JMenuItem(title); - int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); - return menuItem; - } - - - /** - * Like newJMenuItem() but adds shift as a modifier for the key command. - */ - static public JMenuItem newJMenuItemShift(String title, int what) { - JMenuItem menuItem = new JMenuItem(title); - int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - modifiers |= ActionEvent.SHIFT_MASK; - menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); - return menuItem; - } - - - /** - * Same as newJMenuItem(), but adds the ALT (on Linux and Windows) - * or OPTION (on Mac OS X) key as a modifier. - */ - static public JMenuItem newJMenuItemAlt(String title, int what) { - JMenuItem menuItem = new JMenuItem(title); - //int modifiers = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); - //menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); - menuItem.setAccelerator(KeyStroke.getKeyStroke(what, SHORTCUT_ALT_KEY_MASK)); - return menuItem; - } - - // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/app/src/processing/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java index 1dc7d4422..90e06715c 100644 --- a/app/src/processing/app/EditorHeader.java +++ b/app/src/processing/app/EditorHeader.java @@ -288,7 +288,7 @@ public class EditorHeader extends JComponent { */ //item = new JMenuItem("New Tab"); - item = Editor.newJMenuItemShift("New Tab", 'N'); + item = Base.newJMenuItemShift("New Tab", 'N'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { editor.getSketch().handleNewCode(); @@ -324,7 +324,7 @@ public class EditorHeader extends JComponent { item = new JMenuItem("Previous Tab"); KeyStroke ctrlAltLeft = - KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Editor.SHORTCUT_ALT_KEY_MASK); + KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Base.SHORTCUT_ALT_KEY_MASK); item.setAccelerator(ctrlAltLeft); // this didn't want to work consistently /* @@ -338,7 +338,7 @@ public class EditorHeader extends JComponent { item = new JMenuItem("Next Tab"); KeyStroke ctrlAltRight = - KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Editor.SHORTCUT_ALT_KEY_MASK); + KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Base.SHORTCUT_ALT_KEY_MASK); item.setAccelerator(ctrlAltRight); /* item.addActionListener(new ActionListener() { diff --git a/app/src/processing/app/EditorToolbar.java b/app/src/processing/app/EditorToolbar.java index 3120aef46..9f593b501 100644 --- a/app/src/processing/app/EditorToolbar.java +++ b/app/src/processing/app/EditorToolbar.java @@ -3,13 +3,12 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2004-09 Ben Fry and Casey Reas + Copyright (c) 2004-10 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 as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -93,6 +92,15 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key Color statusColor; boolean shiftPressed; + +// Color modeButtonColor; +// Font modeTextFont; +// Color modeTextColor; +// String modeTitle = "JAVA"; //"Java"; +// String modeTitle = "ANDROID"; //"Java"; +// int modeX1, modeY1; +// int modeX2, modeY2; + public EditorToolbar(Editor editor, JMenu menu) { this.editor = editor; @@ -115,10 +123,15 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key statusFont = Theme.getFont("buttons.status.font"); statusColor = Theme.getColor("buttons.status.color"); +// modeButtonColor = Theme.getColor("mode.button.bgcolor"); +// modeTextFont = Theme.getFont("mode.button.font"); +// modeTextColor = Theme.getColor("mode.button.color"); + addMouseListener(this); addMouseMotionListener(this); } + protected void loadButtons() { Image allButtons = Base.getThemeImage("buttons.gif", this); buttonImages = new Image[BUTTON_COUNT][3]; @@ -134,7 +147,8 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key } } } - + + @Override public void paintComponent(Graphics screen) { // this data is shared by all EditorToolbar instances @@ -181,22 +195,39 @@ public class EditorToolbar extends JComponent implements MouseInputListener, Key g.setColor(statusColor); g.setFont(statusFont); - /* - // if i ever find the guy who wrote the java2d api, i will hurt him. - * - * whereas I love the Java2D API. --jdf. lol. - * - Graphics2D g2 = (Graphics2D) g; - FontRenderContext frc = g2.getFontRenderContext(); - float statusW = (float) statusFont.getStringBounds(status, frc).getWidth(); - float statusX = (getSize().width - statusW) / 2; - g2.drawString(status, statusX, statusY); - */ + // If I ever find the guy who wrote the Java2D API, I will hurt him. +// Graphics2D g2 = (Graphics2D) g; +// FontRenderContext frc = g2.getFontRenderContext(); +// float statusW = (float) statusFont.getStringBounds(status, frc).getWidth(); +// float statusX = (getSize().width - statusW) / 2; +// g2.drawString(status, statusX, statusY); + if (currentRollover != -1) { int statusY = (BUTTON_HEIGHT + g.getFontMetrics().getAscent()) / 2; String status = shiftPressed ? titleShift[currentRollover] : title[currentRollover]; g.drawString(status, buttonCount * BUTTON_WIDTH + 3 * BUTTON_GAP, statusY); } + +//// Color modeButtonColor; +//// Font modeTextFont; +//// Color modeTextColor; +// g.setFont(modeTextFont); +// FontMetrics metrics = g.getFontMetrics(); +// int modeH = metrics.getAscent(); +// int modeW = metrics.stringWidth(modeTitle); +// final int modeGapH = 6; +// final int modeGapV = 3; +// modeX2 = getWidth() - 16; +// modeX1 = modeX2 - (modeGapH + modeW + modeGapH); +// modeY1 = (getHeight() - modeH)/2 - modeGapV; +// modeY2 = modeY1 + modeH + modeGapV*2; +//// g.setColor(modeButtonColor); +//// g.fillRect(modeX1, modeY1, modeX2 - modeX1, modeY2 - modeY1); +//// g.setColor(modeTextColor); +//// g.drawString(modeTitle, modeX1 + modeGapH, modeY2 - modeGapV); +// g.setColor(modeButtonColor); +// g.drawRect(modeX1, modeY1, modeX2 - modeX1, modeY2 - modeY1); +// g.drawString(modeTitle, modeX1 + modeGapH, modeY2 - modeGapV); screen.drawImage(offscreen, 0, 0, null); diff --git a/app/src/processing/app/Preferences.java b/app/src/processing/app/Preferences.java index 8f410a29f..0220a2ecc 100644 --- a/app/src/processing/app/Preferences.java +++ b/app/src/processing/app/Preferences.java @@ -456,7 +456,7 @@ public class Preferences { pain.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { //System.out.println(e); - KeyStroke wc = Editor.WINDOW_CLOSE_KEYSTROKE; + KeyStroke wc = Base.WINDOW_CLOSE_KEYSTROKE; if ((e.getKeyCode() == KeyEvent.VK_ESCAPE) || (KeyStroke.getKeyStrokeForEvent(e).equals(wc))) { disposeFrame(); diff --git a/app/src/processing/app/macosx/ThinkDifferent.java b/app/src/processing/app/macosx/ThinkDifferent.java index f0c13cbba..734141495 100644 --- a/app/src/processing/app/macosx/ThinkDifferent.java +++ b/app/src/processing/app/macosx/ThinkDifferent.java @@ -3,12 +3,11 @@ /* Part of the Processing project - http://processing.org - Copyright (c) 2007 Ben Fry and Casey Reas + Copyright (c) 2007-2010 Ben Fry and Casey Reas This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + the Free Software Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -22,13 +21,16 @@ package processing.app.macosx; +import java.lang.reflect.Method; +import javax.swing.JMenu; +import javax.swing.JMenuBar; import processing.app.Base; import com.apple.eawt.*; /** - * Deal with issues related to thinking different. This handles the basic + * Deal with issues related to thinking differently. This handles the basic * Mac OS X menu commands (and apple events) for open, about, prefs, etc. * * Based on OSXAdapter.java from Apple DTS. @@ -51,7 +53,7 @@ public class ThinkDifferent implements ApplicationListener { static protected void init(Base base) { if (application == null) { //application = new com.apple.eawt.Application(); - application = com.apple.eawt.Application.getApplication(); + application = Application.getApplication(); } if (adapter == null) { adapter = new ThinkDifferent(base); @@ -59,6 +61,28 @@ public class ThinkDifferent implements ApplicationListener { application.addApplicationListener(adapter); application.setEnabledAboutMenu(true); application.setEnabledPreferencesMenu(true); + + // Set the menubar to be used when nothing else is open. http://j.mp/dkZmka + // http://developer.apple.com/mac/library/documentation/Java/Reference/ + // JavaSE6_AppleExtensionsRef/api/com/apple/eawt/Application.html + // Only available since Java for Mac OS X 10.6 Update 1, and + // Java for Mac OS X 10.5 Update 6, so need to load this dynamically + try { + // com.apple.eawt.Application.setDefaultMenuBar(JMenuBar) + Class appClass = Application.class; + Method method = + appClass.getMethod("setDefaultMenuBar", new Class[] { JMenuBar.class }); + if (method != null) { + JMenuBar defaultMenuBar = new JMenuBar(); + JMenu fileMenu = base.buildFileMenu(null); + defaultMenuBar.add(fileMenu); + method.invoke(application, new Object[] { defaultMenuBar }); + // This is kind of a gross way to do this, but the alternatives? Hrm. + Base.defaultFileMenu = fileMenu; + } + } catch (Exception e) { + e.printStackTrace(); // oh well nevermind + } }