From 1964bf65cb13f2d20fa3aaac295ff2e6fd7989b9 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Tue, 22 Jan 2019 18:28:43 -0500 Subject: [PATCH] rewrite key stroke handling; now multi-platform, overridable by prefs --- app/src/processing/app/ui/Editor.java | 19 ++---- app/src/processing/app/ui/EditorHeader.java | 34 ++-------- app/src/processing/app/ui/Toolkit.java | 66 ++++++++++++++----- build/shared/lib/languages/PDE.properties | 3 + java/src/processing/mode/java/JavaEditor.java | 9 +-- todo.txt | 1 + 6 files changed, 66 insertions(+), 66 deletions(-) diff --git a/app/src/processing/app/ui/Editor.java b/app/src/processing/app/ui/Editor.java index 8da45570c..e71775d5d 100644 --- a/app/src/processing/app/ui/Editor.java +++ b/app/src/processing/app/ui/Editor.java @@ -881,13 +881,8 @@ public abstract class Editor extends JFrame implements RunnerListener { undoItem = Toolkit.newJMenuItem(undoAction = new UndoAction(), 'Z'); menu.add(undoItem); - // Gotta follow them interface guidelines - // http://code.google.com/p/processing/issues/detail?id=363 - if (Platform.isWindows()) { - redoItem = Toolkit.newJMenuItem(redoAction = new RedoAction(), 'Y'); - } else { // Linux and OS X - redoItem = Toolkit.newJMenuItemShift(redoAction = new RedoAction(), 'Z'); - } + redoItem = new JMenuItem(redoAction = new RedoAction()); + redoItem.setAccelerator(Toolkit.getKeyStrokeExt("menu.edit.redo")); menu.add(redoItem); menu.addSeparator(); @@ -956,8 +951,7 @@ public abstract class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = Toolkit.newJMenuItem(Language.text("menu.edit.comment_uncomment"), - Language.text("menu.edit.comment_uncomment.keystroke")); + item = Toolkit.newJMenuItemExt("menu.edit.comment_uncomment"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleCommentUncomment(); @@ -965,9 +959,7 @@ public abstract class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = Toolkit.newJMenuItem("\u2192 " + Language.text("menu.edit.increase_indent"), - Language.text("menu.edit.increase_indent.keystroke")); - + item = Toolkit.newJMenuItemExt("menu.edit.increase_indent"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleIndentOutdent(true); @@ -975,8 +967,7 @@ public abstract class Editor extends JFrame implements RunnerListener { }); menu.add(item); - item = Toolkit.newJMenuItem("\u2190 " + Language.text("menu.edit.decrease_indent"), - Language.text("menu.edit.decrease_indent.keystroke")); + item = Toolkit.newJMenuItemExt("menu.edit.decrease_indent"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleIndentOutdent(false); diff --git a/app/src/processing/app/ui/EditorHeader.java b/app/src/processing/app/ui/EditorHeader.java index 32a4cc7ea..32a73189d 100644 --- a/app/src/processing/app/ui/EditorHeader.java +++ b/app/src/processing/app/ui/EditorHeader.java @@ -494,51 +494,29 @@ public class EditorHeader extends JComponent { // KeyEvent.VK_LEFT and VK_RIGHT will make Windows beep - final String prevTab = Language.text("editor.header.previous_tab"); - if (Platform.isLinux()) { - item = Toolkit.newJMenuItem(prevTab, KeyEvent.VK_PAGE_UP); - } else { - //item = Toolkit.newJMenuItemAlt(prevTab, KeyEvent.VK_LEFT); - item = Toolkit.newJMenuItem(prevTab, Language.text("editor.header.previous_tab.keystroke")); - } + mapKey = "editor.header.previous_tab"; + item = Toolkit.newJMenuItemExt(mapKey); action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { editor.getSketch().handlePrevCode(); } }; - mapKey = "editor.header.previous_tab"; - if (Platform.isLinux()) { - keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, Toolkit.SHORTCUT_KEY_MASK); - } else { - //keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Toolkit.SHORTCUT_ALT_KEY_MASK); - keyStroke = KeyStroke.getKeyStroke(Language.text("editor.header.previous_tab.keystroke")); - } + keyStroke = item.getAccelerator(); inputMap.put(keyStroke, mapKey); actionMap.put(mapKey, action); item.addActionListener(action); menu.add(item); - final String nextTab = Language.text("editor.header.next_tab"); - if (Platform.isLinux()) { - item = Toolkit.newJMenuItem(nextTab, KeyEvent.VK_PAGE_DOWN); - } else { - //item = Toolkit.newJMenuItemAlt(nextTab, KeyEvent.VK_RIGHT); - item = Toolkit.newJMenuItem(nextTab, Language.text("editor.header.next_tab.keystroke")); - } + mapKey = "editor.header.next_tab"; + item = Toolkit.newJMenuItemExt(mapKey); action = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { editor.getSketch().handleNextCode(); } }; - mapKey = "editor.header.next_tab"; - if (Platform.isLinux()) { - keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, Toolkit.SHORTCUT_KEY_MASK); - } else { - //keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Toolkit.SHORTCUT_ALT_KEY_MASK); - keyStroke = KeyStroke.getKeyStroke(Language.text("editor.header.next_tab.keystroke")); - } + keyStroke = item.getAccelerator(); inputMap.put(keyStroke, mapKey); actionMap.put(mapKey, action); item.addActionListener(action); diff --git a/app/src/processing/app/ui/Toolkit.java b/app/src/processing/app/ui/Toolkit.java index b49987a46..31a63e570 100644 --- a/app/src/processing/app/ui/Toolkit.java +++ b/app/src/processing/app/ui/Toolkit.java @@ -103,6 +103,8 @@ public class Toolkit { static public final KeyStroke WINDOW_CLOSE_KEYSTROKE = KeyStroke.getKeyStroke('W', SHORTCUT_KEY_MASK); + static final String BAD_KEYSTROKE = + "'%s' is not understood, please re-read the Java reference for KeyStroke"; /** * Standardized width for buttons. Mac OS X 10.3 wants 70 as its default, @@ -118,16 +120,36 @@ public class Toolkit { /** - * A software engineer, somewhere, needs to have their abstraction - * taken away. Who crafts the sort of API that would require a - * five-line helper function just to set the shortcut key for a - * menu item? + * Return the correct KeyStroke per locale and platform. + * Also checks for any additional overrides in preferences.txt. + * @param base the localization key for the menu item + * (.keystroke and .platform will be added to the end) + * @return KeyStroke for base + .keystroke + .platform + * (or the value from preferences) or null if none found */ - static public JMenuItem newJMenuItem(String title, int what) { - JMenuItem menuItem = new JMenuItem(title); - int modifiers = awtToolkit.getMenuShortcutKeyMask(); - menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); - return menuItem; + static public KeyStroke getKeyStrokeExt(String base) { + String key = base + ".keystroke"; + + // see if there's an override in preferences.txt + String sequence = Preferences.get(key); + if (sequence != null) { + KeyStroke ks = KeyStroke.getKeyStroke(sequence); + if (ks != null) { + return ks; // user did good, we're all set + + } else { + System.err.format(BAD_KEYSTROKE, sequence); + } + } + + sequence = Language.text(key + "." + Platform.getName()); + KeyStroke ks = KeyStroke.getKeyStroke(sequence); + if (ks == null) { + // this can only happen if user has screwed up their language files + System.err.format(BAD_KEYSTROKE, sequence); + //return KeyStroke.getKeyStroke(0, 0); // badness + } + return ks; } @@ -138,22 +160,30 @@ public class Toolkit { * @param sequence the name, as outlined by the KeyStroke API * @param fallback what to use if getKeyStroke() comes back null */ - static public JMenuItem newJMenuItem(String title, - String sequence) { - JMenuItem menuItem = new JMenuItem(title); - KeyStroke ks = KeyStroke.getKeyStroke(sequence); + static public JMenuItem newJMenuItemExt(String base) { + JMenuItem menuItem = new JMenuItem(Language.text(base)); + KeyStroke ks = getKeyStrokeExt(base); // will print error if necessary if (ks != null) { menuItem.setAccelerator(ks); - - } else { - System.err.println("'" + sequence + "' is not understood, " + - "pleae re-read the Java reference for KeyStroke"); - //ks = KeyStroke.getKeyStroke(fallback); } return menuItem; } + /** + * A software engineer, somewhere, needs to have their abstraction + * taken away. Who crafts 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 = awtToolkit.getMenuShortcutKeyMask(); + menuItem.setAccelerator(KeyStroke.getKeyStroke(what, modifiers)); + return menuItem; + } + + /** * @param action: use an Action, which sets the title, reaction * and enabled-ness all by itself. diff --git a/build/shared/lib/languages/PDE.properties b/build/shared/lib/languages/PDE.properties index fe575d780..afc34f28f 100644 --- a/build/shared/lib/languages/PDE.properties +++ b/build/shared/lib/languages/PDE.properties @@ -31,6 +31,9 @@ menu.file.quit = Quit menu.edit = Edit menu.edit.undo = Undo menu.edit.redo = Redo +menu.edit.redo.keystroke.macosx = shift meta pressed Z +menu.edit.redo.keystroke.windows = meta pressed Y +menu.edit.redo.keystroke.linux = shift ctrl pressed Z menu.edit.action.addition = addition menu.edit.action.deletion = deletion menu.edit.cut = Cut diff --git a/java/src/processing/mode/java/JavaEditor.java b/java/src/processing/mode/java/JavaEditor.java index 53723ff02..1e68198fd 100644 --- a/java/src/processing/mode/java/JavaEditor.java +++ b/java/src/processing/mode/java/JavaEditor.java @@ -1384,8 +1384,7 @@ public class JavaEditor extends Editor { // }); // debugMenu.add(item); - item = Toolkit.newJMenuItem(Language.text("menu.debug.step"), - Language.text("menu.debug.step.keystroke")); + item = Toolkit.newJMenuItemExt("menu.debug.step"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleStep(0); @@ -1394,8 +1393,7 @@ public class JavaEditor extends Editor { debugMenu.add(item); item.setEnabled(false); - item = Toolkit.newJMenuItem(Language.text("menu.debug.step_into"), - Language.text("menu.debug.step_into.keystroke")); + item = Toolkit.newJMenuItemExt("menu.debug.step_into"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleStep(ActionEvent.SHIFT_MASK); @@ -1404,8 +1402,7 @@ public class JavaEditor extends Editor { debugMenu.add(item); item.setEnabled(false); - item = Toolkit.newJMenuItem(Language.text("menu.debug.step_out"), - Language.text("menu.debug.step_out.keystroke")); + item = Toolkit.newJMenuItemExt("menu.debug.step_out"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { handleStep(ActionEvent.ALT_MASK); diff --git a/todo.txt b/todo.txt index eed92ada5..b90555f80 100755 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,7 @@ 0268 (3.5.2) _ shortcuts not working on Windows/Linux (using meta) _ https://github.com/processing/processing/issues/5763 +_ update https://github.com/processing/processing/wiki/Localization#shortcuts-and-key-bindings _ Find in Reference disabled for various keywords (draw, for, if, catch, while)