From 29c1edd2737a40ab01a43eb890d2e695e252860e Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Wed, 1 Apr 2015 14:57:56 -0400 Subject: [PATCH] fix for #3074, opening prefs from shortcut marks sketch as modified --- app/src/processing/app/Editor.java | 167 ++++++------- app/src/processing/app/Toolkit.java | 224 +++++++++--------- .../app/syntax/DefaultInputHandler.java | 0 .../app/syntax/PdeInputHandler.java | 48 +++- java/src/processing/mode/java/JavaEditor.java | 25 +- .../mode/java/JavaInputHandler.java | 24 +- 6 files changed, 263 insertions(+), 225 deletions(-) mode change 100644 => 100755 app/src/processing/app/Editor.java mode change 100644 => 100755 app/src/processing/app/Toolkit.java mode change 100644 => 100755 app/src/processing/app/syntax/DefaultInputHandler.java mode change 100644 => 100755 app/src/processing/app/syntax/PdeInputHandler.java mode change 100644 => 100755 java/src/processing/mode/java/JavaEditor.java mode change 100644 => 100755 java/src/processing/mode/java/JavaInputHandler.java diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java old mode 100644 new mode 100755 index ca4c2a1e4..ff84c6e43 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -55,7 +55,7 @@ public abstract class Editor extends JFrame implements RunnerListener { static public final int RIGHT_GUTTER = 20; static public final int GUTTER_MARGIN = 3; - + // Otherwise, if the window is resized with the message label // set to blank, its preferredSize() will be fuckered static protected final String EMPTY = @@ -119,7 +119,7 @@ public abstract class Editor extends JFrame implements RunnerListener { ArrayList coreTools; public ArrayList contribTools; - + Image backgroundGradient; @@ -131,7 +131,7 @@ public abstract class Editor extends JFrame implements RunnerListener { this.mode = mode; Toolkit.setIcon(this); // TODO should this be per-mode? - + // Install default actions for Run, Present, etc. // resetHandlers(); @@ -149,7 +149,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // When bringing a window to front, let the Base know addWindowListener(new WindowAdapter() { // int importIndex; - + public void windowActivated(WindowEvent e) { base.handleActivated(Editor.this); fileMenu.insert(base.getRecentMenu(), 2); @@ -193,7 +193,7 @@ public abstract class Editor extends JFrame implements RunnerListener { //contentPain.setBorder(new EmptyBorder(0, 0, 0, 0)); //System.out.println(contentPain.getBorder()); JPanel contentPain = new JPanel(); - + // JFrame f = new JFrame(); // f.setContentPane(new JPanel() { // @Override @@ -270,25 +270,25 @@ public abstract class Editor extends JFrame implements RunnerListener { // remove an ugly border around anything in a SplitPane !$*&!% UIManager.getDefaults().put("SplitPane.border", BorderFactory.createEmptyBorder()); - // override the look of the SplitPane so that it's identical across OSes + // override the look of the SplitPane so that it's identical across OSes splitPane.setUI(new BasicSplitPaneUI() { public BasicSplitPaneDivider createDefaultDivider() { return new BasicSplitPaneDivider(this) { final Color dividerColor = mode.getColor("divider.color"); //new Color(204, 204, 204); final Color dotColor = mode.getColor("divider.dot.color"); //new Color(80, 80, 80); int dotSize = mode.getInteger("divider.dot.diameter"); //3; - + @Override public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - + final int w = getSize().width; final int h = getSize().height; g.setColor(dividerColor); g.fillRect(0, 0, w, h); - + g.setColor(dotColor); int x = w/2 - dotSize/2; int y = h/2 - dotSize/2; @@ -297,7 +297,7 @@ public abstract class Editor extends JFrame implements RunnerListener { }; } }); - + // EditorConsole.systemOut.println("divider default size is " + splitPane.getDividerSize()); // // the default size on windows is too small and kinda ugly // int dividerSize = Preferences.getInteger("editor.divider.size"); @@ -359,12 +359,12 @@ public abstract class Editor extends JFrame implements RunnerListener { if (!loaded) { sketch = null; } - + //add a window listener to watch for changes to the files in the sketch if (Preferences.getBoolean("editor.watcher")) { addWindowFocusListener(new ChangeDetector(this)); } - + } @@ -378,6 +378,9 @@ public abstract class Editor extends JFrame implements RunnerListener { * solution where the listeners are handled properly. */ protected JEditTextArea createTextArea() { + return new JEditTextArea(new PdeTextAreaDefaults(mode), + new PdeInputHandler()); + /* return new JEditTextArea(new PdeTextAreaDefaults(mode), new PdeInputHandler()) { // this is a kludge that needs to be removed [fry 150120] public void processKeyEvent(KeyEvent evt) { @@ -386,12 +389,13 @@ public abstract class Editor extends JFrame implements RunnerListener { super.processKeyEvent(evt); if (inputHandler != null) { - // Prevent sketch being marked modified cia ctrl-, on Windows/Linux - if ((evt.getModifiers() & InputEvent.CTRL_MASK) != 0 && + // Prevent sketch being marked modified cia ctrl-, on Windows/Linux + if ((evt.getModifiers() & InputEvent.CTRL_MASK) != 0 && evt.getKeyChar() == ',') { + System.out.println("skipping " + evt); return; } - switch (evt.getID()) { + switch (evt.getID()) { case KeyEvent.KEY_TYPED: inputHandler.keyTyped(evt); break; @@ -405,6 +409,7 @@ public abstract class Editor extends JFrame implements RunnerListener { } } }; + */ } @@ -511,7 +516,7 @@ public abstract class Editor extends JFrame implements RunnerListener { "Please save the sketch before changing the mode.", null); - // Re-select the old checkbox, because it was automatically + // Re-select the old checkbox, because it was automatically // updated by Java, even though the Mode could not be changed. // https://github.com/processing/processing/issues/2615 for (Component c : modeMenu.getPopupMenu().getComponents()) { @@ -619,10 +624,10 @@ public abstract class Editor extends JFrame implements RunnerListener { // 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. + + // All of this code was specific to using an external editor. /* // // apply the setting for 'use external editor' // boolean external = Preferences.getBoolean("editor.external"); @@ -719,9 +724,9 @@ public abstract class Editor extends JFrame implements RunnerListener { fileMenu.add(item); // fileMenu.add(base.getSketchbookMenu()); - + item = Toolkit.newJMenuItemShift(Language.text("menu.file.sketchbook"), 'K'); - item.addActionListener(new ActionListener() { + item.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { mode.showSketchbookFrame(); @@ -988,16 +993,16 @@ public abstract class Editor extends JFrame implements RunnerListener { } }); menu.add(item); - + // Update copy/cut state on selection/de-selection menu.addMenuListener(new MenuListener() { - + @Override public void menuCanceled(MenuEvent e) { copyItems.setEnabled(true); cutItems.setEnabled(true); } - + @Override public void menuDeselected(MenuEvent e) { copyItems.setEnabled(true); @@ -1051,8 +1056,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } // 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(); @@ -1067,11 +1072,11 @@ public abstract class Editor extends JFrame implements RunnerListener { } else { item = new JMenuItem(editor.getSketch().getName()); } - item.setText(editor.getSketch().getName() + + 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) { editor.setState(Frame.NORMAL); @@ -1172,13 +1177,13 @@ public abstract class Editor extends JFrame implements RunnerListener { // tool.run(); // } // return true; -// +// // } catch (NoSuchMethodError nsme) { // System.out.println("tool is " + tool + " "); // statusError("\"" + tool.getMenuTitle() + "\" " + // "is not compatible with this version of Processing"); // nsme.printStackTrace(); -// +// // } catch (Exception ex) { // statusError("An error occurred inside \"" + tool.getMenuTitle() + "\""); // ex.printStackTrace(); @@ -1188,8 +1193,8 @@ 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); @@ -1210,14 +1215,14 @@ public abstract class Editor extends JFrame implements RunnerListener { 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(); @@ -1226,17 +1231,17 @@ 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 + + // 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. + // 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 (VerifyError ve) { System.err.println("\"" + tool.getMenuTitle() + "\" is not " + "compatible with this version of Processing"); - + } catch (NoSuchMethodError nsme) { System.err.println("\"" + tool.getMenuTitle() + "\" is not " + "compatible with this version of Processing"); @@ -1388,7 +1393,7 @@ public abstract class Editor extends JFrame implements RunnerListener { /** * Given the .html file, displays it in the default browser. - * + * * @param file */ public void showReferenceFile(File file) { @@ -1418,34 +1423,34 @@ public abstract class Editor extends JFrame implements RunnerListener { super(Language.text("menu.edit.cut")); this.setEnabled(false); } - + public void actionPerformed(ActionEvent e) { handleCut(); } - + public void updateCutState() { cutItems.setEnabled(canCut()); } - + public boolean canCut() { return textarea.isSelectionActive(); } } - + class CopyAction extends AbstractAction { public CopyAction() { super(Language.text("menu.edit.copy")); this.setEnabled(false); } - + public void actionPerformed(ActionEvent e) { textarea.copy(); } - + public void updateCopyState() { copyItems.setEnabled(canCopy()); } - + public boolean canCopy() { return textarea.isSelectionActive(); } @@ -2040,9 +2045,9 @@ 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() && + +// boolean wasVisible = +// textarea.getSelectionStopLine() >= textarea.getFirstLine() && // textarea.getSelectionStopLine() < textarea.getLastLine(); // make sure the caret would be past the end of the text @@ -2058,18 +2063,18 @@ 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, + // Since we're not doing a good job of maintaining position anyway, // a more complicated workaround here is fairly pointless. // http://code.google.com/p/processing/issues/detail?id=1533 if (scrollPos != textarea.getVerticalScrollPosition()) { -// boolean wouldBeVisible = -// scrollPos >= textarea.getFirstLine() && +// boolean wouldBeVisible = +// scrollPos >= textarea.getFirstLine() && // scrollPos < textarea.getLastLine(); // // // if it was visible, and now it's not, then allow the scroll -// if (!(wasVisible && !wouldBeVisible)) { +// if (!(wasVisible && !wouldBeVisible)) { textarea.setVerticalScrollPosition(scrollPos); // } } @@ -2122,9 +2127,9 @@ public abstract class Editor extends JFrame implements RunnerListener { // log("Commented: " + commented); // This is the line start offset of the first line, which is added to - // all other lines while adding a comment. Required when commenting - // lines which have uneven whitespaces in the beginning. Makes the - // commented lines look more uniform. + // all other lines while adding a comment. Required when commenting + // lines which have uneven whitespaces in the beginning. Makes the + // commented lines look more uniform. int lso = Math.abs(textarea.getLineStartNonWhiteSpaceOffset(startLine) - textarea.getLineStartOffset(startLine)); @@ -2248,14 +2253,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 */ @@ -2268,7 +2273,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])) { @@ -2290,8 +2295,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } return ref; } - - + + protected void handleFindReference() { String ref = referenceCheck(true); if (ref != null) { @@ -2305,8 +2310,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } } } - - + + /* protected void handleFindReference() { String text = textarea.getSelectedText().trim(); @@ -2330,8 +2335,8 @@ public abstract class Editor extends JFrame implements RunnerListener { } } } - - + + protected void handleFindReference() { String text = textarea.getSelectedText().trim(); @@ -2389,7 +2394,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // With Java 7u40 on OS X, need to bring the window forward. toFront(); - + String prompt = Language.text("close.unsaved_changes") + " " + sketch.getName() + "? "; @@ -2513,7 +2518,7 @@ public abstract class Editor extends JFrame implements RunnerListener { } else { final String properParent = file.getName().substring(0, file.getName().lastIndexOf('.')); - + Object[] options = { Language.text("prompt.ok"), Language.text("prompt.cancel") }; String prompt = "The file \"" + file.getName() + "\" needs to be inside\n" + @@ -2571,7 +2576,7 @@ public abstract class Editor extends JFrame implements RunnerListener { Base.showWarning("Error", "Could not create the sketch.", e); return false; } - + header.rebuild(); updateTitle(); // Disable untitled setting from previous document, if any @@ -2607,7 +2612,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // per other applications, don't set this until the file has been saved getRootPane().putClientProperty("Window.documentFile", null); } - + // toolbar.setText(sketch.getName()); } @@ -2623,7 +2628,7 @@ public abstract class Editor extends JFrame implements RunnerListener { */ public boolean handleSave(boolean immediately) { // handleStop(); // 0136 - + if (sketch.isUntitled()) { return handleSaveAs(); // need to get the name, user might also cancel here @@ -2669,7 +2674,7 @@ public abstract class Editor extends JFrame implements RunnerListener { if (sketch.saveAs()) { // statusNotice("Done Saving."); // status is now printed from Sketch so that "Done Saving." - // is only printed after Save As when progress bar is shown. + // is only printed after Save As when progress bar is shown. } else { statusNotice(Language.text("editor.status.saving.canceled")); return false; @@ -2855,22 +2860,22 @@ public abstract class Editor extends JFrame implements RunnerListener { } } - + /** * Returns the current notice message in the editor status bar. */ 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(){ return status.mode; } - + /** * Clear the status area. @@ -2989,7 +2994,7 @@ public abstract class Editor extends JFrame implements RunnerListener { } }); this.add(referenceItem); - + Toolkit.setMenuMnemonics(this); } @@ -2999,7 +3004,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // cutItem.setEnabled(true); // copyItem.setEnabled(true); // discourseItem.setEnabled(true); -// +// //// String sel = textarea.getSelectedText().trim(); //// String referenceFile = mode.lookupReference(sel); //// referenceItem.setEnabled(referenceFile != null); diff --git a/app/src/processing/app/Toolkit.java b/app/src/processing/app/Toolkit.java old mode 100644 new mode 100755 index 08cd0d181..296305767 --- a/app/src/processing/app/Toolkit.java +++ b/app/src/processing/app/Toolkit.java @@ -77,15 +77,15 @@ public class Toolkit { /** Command on Mac OS X, Ctrl on Windows and Linux */ static final int SHORTCUT_KEY_MASK = awtToolkit.getMenuShortcutKeyMask(); - + /** Command-W on Mac OS X, Ctrl-W on Windows and Linux */ public static final KeyStroke WINDOW_CLOSE_KEYSTROKE = - KeyStroke.getKeyStroke('W', SHORTCUT_KEY_MASK); + 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 = + static final int SHORTCUT_ALT_KEY_MASK = ActionEvent.ALT_MASK | SHORTCUT_KEY_MASK; /** Command-Shift on Mac OS X, Ctrl-Shift on Windows and Linux */ - static final int SHORTCUT_SHIFT_KEY_MASK = + static final int SHORTCUT_SHIFT_KEY_MASK = ActionEvent.SHIFT_MASK | SHORTCUT_KEY_MASK; @@ -117,8 +117,8 @@ public class Toolkit { /** * Same as newJMenuItem(), but adds the ALT (on Linux and Windows) - * or OPTION (on Mac OS X) key as a modifier. This function should almost - * never be used, because it's bad for non-US keyboards that use ALT in + * or OPTION (on Mac OS X) key as a modifier. This function should almost + * never be used, because it's bad for non-US keyboards that use ALT in * strange and wondrous ways. */ static public JMenuItem newJMenuItemAlt(String title, int what) { @@ -144,14 +144,14 @@ public class Toolkit { /** - * Removes all mnemonics, then sets a mnemonic for each menu and menu item + * Removes all mnemonics, then sets a mnemonic for each menu and menu item * recursively by these rules: *
    *
  1. It tries to assign one of * KDE's defaults.
  2. *
  3. Failing that, it loops through the first letter of each word, where a word - * is a block of Unicode "alphabetical" chars, looking for an upper-case ASCII mnemonic - * that is not taken. This is to try to be relevant, by using a letter well-associated + * is a block of Unicode "alphabetical" chars, looking for an upper-case ASCII mnemonic + * that is not taken. This is to try to be relevant, by using a letter well-associated * with the command. (MS guidelines)
  4. *
  5. Ditto, but with lowercase.
  6. *
  7. Next, it tries the second ASCII character, if its width >= half the width of @@ -162,7 +162,7 @@ public class Toolkit { * have 2/3 their actual width. (MS guidelines: avoid decenders). It also discriminates * against vowels, imagining they have 2/3 their actual width. (MS and Gnome guidelines: * avoid vowels.
  8. - *
  9. Failing that, it will loop left-to-right for an available digit. This is a last + *
  10. Failing that, it will loop left-to-right for an available digit. This is a last * resort because the normal setMnemonic dislikes them.
  11. *
  12. If that doesn't work, it doesn't assign a mnemonic.
  13. *
@@ -188,23 +188,23 @@ public class Toolkit { // for ampersands before mnemonics and ".+" for changable text. (They are regexs.) // Note that every ampersand MUST be followed by a lowercase ASCII letter. final String[] kdePreDefStrs = { "&file", "&new", "&open", "open&recent", "&save", - "save&as", "saveacop&y", "saveas&template", "savea&ll", "reloa&d", "&print", - "printpre&view", "&import", "e&xport", "&closefile", "clos&eallfiles", "&quit", - "&edit", "&undo", "re&do", "cu&t&", "©", "&paste", "&delete", "select&all", - "dese&lect", "&find", "find&next", "findpre&vious", "&replace", "&gotoline", - "&view", "&newview", "close&allviews", "&splitview", "&removeview", - "splitter&orientation", "&horizontal", "&vertical", "view&mode", "&fullscreenmode", - "&zoom", "zoom&in", "zoom&out", "zoomtopage&width", "zoomwhole&page", "zoom&factor", - "&insert", "&format", "&go", "&up", "&back", "&forward", "&home", "&go", "&previouspage", - "&nextpage", "&firstpage", "&lastpage", "read&updocument", "read&downdocument", "&back", - "&forward", "&gotopage", "&bookmarks", "&addbookmark", "bookmark&tabsasfolder", + "save&as", "saveacop&y", "saveas&template", "savea&ll", "reloa&d", "&print", + "printpre&view", "&import", "e&xport", "&closefile", "clos&eallfiles", "&quit", + "&edit", "&undo", "re&do", "cu&t&", "©", "&paste", "&delete", "select&all", + "dese&lect", "&find", "find&next", "findpre&vious", "&replace", "&gotoline", + "&view", "&newview", "close&allviews", "&splitview", "&removeview", + "splitter&orientation", "&horizontal", "&vertical", "view&mode", "&fullscreenmode", + "&zoom", "zoom&in", "zoom&out", "zoomtopage&width", "zoomwhole&page", "zoom&factor", + "&insert", "&format", "&go", "&up", "&back", "&forward", "&home", "&go", "&previouspage", + "&nextpage", "&firstpage", "&lastpage", "read&updocument", "read&downdocument", "&back", + "&forward", "&gotopage", "&bookmarks", "&addbookmark", "bookmark&tabsasfolder", "&editbookmarks", "&newbookmarksfolder", "&tools", "&settings", "&toolbars", - "configure&shortcuts", "configuretool&bars", "&configure*", "&help", ".+&handbook", + "configure&shortcuts", "configuretool&bars", "&configure*", "&help", ".+&handbook", "&whatsthis", "report&bug", "&aboutprocessing", "about&kde", "&beenden" }; Pattern[] kdePreDefPats = new Pattern[kdePreDefStrs.length]; for (int i = 0; i < kdePreDefStrs.length; i++) kdePreDefPats[i] = Pattern.compile(kdePreDefStrs[i].replace("&","")); - + final Pattern nonAAlpha = Pattern.compile("[^A-Za-z]"); FontMetrics fmTmp = null; for (JMenuItem m : menu) { @@ -214,15 +214,15 @@ public class Toolkit { final FontMetrics fm = fmTmp; // Hack for accessing variable in comparator. final Comparator charComparator = new Comparator() { - char[] baddies = "qypgjaeiouQYPGJAEIOU".toCharArray(); + char[] baddies = "qypgjaeiouQYPGJAEIOU".toCharArray(); public int compare(Character ch1, Character ch2) { // Descriminates against decenders for readability, per MS - // Human Interface Guide, and vowels per MS and Gnome. + // Human Interface Guide, and vowels per MS and Gnome. float w1 = fm.charWidth(ch1), w2 = fm.charWidth(ch2); for (char bad : baddies) { if (bad == ch1) w1 *= 0.66f; if (bad == ch2) w2 *= 0.66f; - } + } return (int)Math.signum(w2 - w1); } }; @@ -242,15 +242,15 @@ public class Toolkit { for (int i = 0; i < kdePreDefStrs.length; i++) { // To ASCII lowercase letters. String lASCIIName = nonAAlpha.matcher(jmi.getText()).replaceAll("").toLowerCase(); - if (kdePreDefPats[i].matcher(lASCIIName).matches()) { + if (kdePreDefPats[i].matcher(lASCIIName).matches()) { char mnem = kdePreDefStrs[i].charAt(1+kdePreDefStrs[i].indexOf("&")); jmi.setMnemonic(mnem); - taken.add(mnem); - break; - } + taken.add(mnem); + break; + } } } - + // Where KDE defaults fail, use an algorithm. algorithmicAssignment: for (JMenuItem jmi : menu) { @@ -263,7 +263,7 @@ public class Toolkit { String cleanString = jmi.getText(); if (cleanString.startsWith("sketchbook \u2192 ")) cleanString = cleanString.substring(13); - + if (cleanString.length() == 0) continue; // First, ban letters by underscores. @@ -271,10 +271,10 @@ public class Toolkit { for (int i = 0; i < cleanString.length(); i++) { if (cleanString.charAt(i) == '_') { if (i > 0) - banned.add(Character.toLowerCase(cleanString.charAt(i-1))); - if (i+1 < cleanString.length()) - banned.add(Character.toLowerCase(cleanString.charAt(i+1))); - } + banned.add(Character.toLowerCase(cleanString.charAt(i-1))); + if (i+1 < cleanString.length()) + banned.add(Character.toLowerCase(cleanString.charAt(i+1))); + } } // METHOD 2: Uppercase starts of words. @@ -284,7 +284,7 @@ public class Toolkit { if (wd.length() == 0) continue; firstChar = wd.charAt(0); if (taken.contains(Character.toLowerCase(firstChar))) continue; - if (banned.contains(Character.toLowerCase(firstChar))) continue; + if (banned.contains(Character.toLowerCase(firstChar))) continue; if ('A' <= firstChar && firstChar <= 'Z') { jmi.setMnemonic(firstChar); taken.add((char)(firstChar | 32)); // tolowercase @@ -297,7 +297,7 @@ public class Toolkit { if (wd.length() == 0) continue; firstChar = wd.charAt(0); if (taken.contains(Character.toLowerCase(firstChar))) continue; - if (banned.contains(Character.toLowerCase(firstChar))) continue; + if (banned.contains(Character.toLowerCase(firstChar))) continue; if ('a' <= firstChar && firstChar <= 'z') { jmi.setMnemonic(firstChar); taken.add(firstChar); // is lowercase @@ -306,16 +306,16 @@ public class Toolkit { } // METHOD 4: Second wide-enough ASCII letter. - cleanString = nonAAlpha.matcher(jmi.getText()).replaceAll(""); + cleanString = nonAAlpha.matcher(jmi.getText()).replaceAll(""); if (cleanString.length() >= 2) { char ascii2nd = cleanString.charAt(1); if (!taken.contains((char)(ascii2nd|32)) && - !banned.contains((char)(ascii2nd|32)) && - fm.charWidth('A') <= 2*fm.charWidth(ascii2nd)) { + !banned.contains((char)(ascii2nd|32)) && + fm.charWidth('A') <= 2*fm.charWidth(ascii2nd)) { jmi.setMnemonic(ascii2nd); taken.add((char)(ascii2nd|32)); continue algorithmicAssignment; - } + } } // METHOD 5: charComparator over all ASCII letters. @@ -327,7 +327,7 @@ public class Toolkit { Arrays.sort(cleanCharas, charComparator); // sorts in increasing order for (char mnem : cleanCharas) { if (taken.contains(Character.toLowerCase(mnem))) continue; - if (banned.contains(Character.toLowerCase(mnem))) continue; + if (banned.contains(Character.toLowerCase(mnem))) continue; // NB: setMnemonic(char) doesn't want [^A-Za-z] jmi.setMnemonic(mnem); taken.add(Character.toLowerCase(mnem)); @@ -339,8 +339,8 @@ public class Toolkit { if (taken.contains(digit)) continue; if (banned.contains(digit)) continue; jmi.setMnemonic(KeyEvent.VK_0 + digit - '0'); - taken.add(digit); - continue algorithmicAssignment; + taken.add(digit); + continue algorithmicAssignment; } } @@ -361,14 +361,14 @@ public class Toolkit { } setMenuMnemonics(items); } - - + + /** * As setMenuMnemonics(JMenuItem...). */ public static void setMenuMnemonics(JPopupMenu menu) { ArrayList items = new ArrayList(); - + for (Component c : menu.getComponents()) { if (c instanceof JMenuItem) items.add((JMenuItem)c); } @@ -402,13 +402,13 @@ public class Toolkit { */ static public Image getLibImage(String filename) { ImageIcon icon = getLibIcon(filename); - return (icon == null) ? null : icon.getImage(); + return (icon == null) ? null : icon.getImage(); } - - - /** - * Get an ImageIcon from the Processing 'lib' folder. - * @since 3.0a6 + + + /** + * Get an ImageIcon from the Processing 'lib' folder. + * @since 3.0a6 */ static public ImageIcon getLibIcon(String filename) { File file = Base.getContentFile("lib/" + filename); @@ -422,15 +422,15 @@ public class Toolkit { static List iconImages; - - // Deprecated version of the function, but can't get rid of it without - // breaking tools and modes (they'd only require a recompile, but they would - // no longer be backwards compatible. + + // Deprecated version of the function, but can't get rid of it without + // breaking tools and modes (they'd only require a recompile, but they would + // no longer be backwards compatible. static public void setIcon(Frame frame) { setIcon((Window) frame); } - + /** * Give this Frame the Processing icon set. Ignored on OS X, because they * thought different and made this function set the minified image of the @@ -498,13 +498,13 @@ public class Toolkit { return awtToolkit.getSystemClipboard(); } - + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - - - /** - * Handles scaling for high-res displays, also sets text anti-aliasing - * options to be far less ugly than the defaults. + + + /** + * Handles scaling for high-res displays, also sets text anti-aliasing + * options to be far less ugly than the defaults. * Moved to a utility function because it's used in several classes. * @return a Graphics2D object, as a bit o sugar */ @@ -514,7 +514,7 @@ public class Toolkit { if (Toolkit.highResDisplay()) { // scale everything 2x, will be scaled down when drawn to the screen g2.scale(2, 2); - } + } g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, @@ -526,10 +526,10 @@ public class Toolkit { } return g2; } - - + + // /** -// * Prepare and offscreen image that's sized for this Component, 1x or 2x +// * Prepare and offscreen image that's sized for this Component, 1x or 2x // * depending on whether this is a retina display or not. // * @param comp // * @param image @@ -538,8 +538,8 @@ public class Toolkit { // static public Image prepareOffscreen(Component comp, Image image) { // Dimension size = comp.getSize(); // Image offscreen = image; -// if (image == null || -// image.getWidth(null) != size.width || +// if (image == null || +// image.getWidth(null) != size.width || // image.getHeight(null) != size.height) { // if (Toolkit.highResDisplay()) { // offscreen = comp.createImage(size.width*2, size.height*2); @@ -549,19 +549,19 @@ public class Toolkit { // } // return offscreen; // } - - + + // static final Color CLEAR_COLOR = new Color(0, true); -// +// // static public void clearGraphics(Graphics g, int width, int height) { // g.setColor(CLEAR_COLOR); // g.fillRect(0, 0, width, height); // } - - + + // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - + static Boolean highResProp; @@ -571,8 +571,8 @@ public class Toolkit { } return highResProp; } - - + + // This should probably be reset each time there's a display change. // A 5-minute search didn't turn up any such event in the Java API. // Also, should we use the Toolkit associated with the editor window? @@ -591,7 +591,7 @@ public class Toolkit { return true; } } - } catch (Exception ignore) { } + } catch (Exception ignore) { } } return false; } @@ -641,6 +641,10 @@ public class Toolkit { // } + static final char GREEK_SMALL_LETTER_ALPHA = '\u03B1'; // α + static final char GREEK_CAPITAL_LETTER_OMEGA = '\u03A9'; // ω + + // Gets the plain (not bold, not italic) version of each static private List getMonoFontList() { GraphicsEnvironment ge = @@ -648,36 +652,36 @@ public class Toolkit { Font[] fonts = ge.getAllFonts(); ArrayList outgoing = new ArrayList(); // Using AffineTransform.getScaleInstance(100, 100) doesn't change sizes - FontRenderContext frc = + FontRenderContext frc = new FontRenderContext(new AffineTransform(), - Preferences.getBoolean("editor.antialias"), - true); // use fractional metrics + Preferences.getBoolean("editor.antialias"), + true); // use fractional metrics for (Font font : fonts) { if (font.getStyle() == Font.PLAIN && font.canDisplay('i') && font.canDisplay('M') && font.canDisplay(' ') && font.canDisplay('.')) { - - // The old method just returns 1 or 0, and using deriveFont(size) + + // The old method just returns 1 or 0, and using deriveFont(size) // is overkill. It also causes deprecation warnings // @SuppressWarnings("deprecation") // FontMetrics fm = awtToolkit.getFontMetrics(font); //FontMetrics fm = awtToolkit.getFontMetrics(font.deriveFont(24)); // System.out.println(fm.charWidth('i') + " " + fm.charWidth('M')); // if (fm.charWidth('i') == fm.charWidth('M') && -// fm.charWidth('M') == fm.charWidth(' ') && +// fm.charWidth('M') == fm.charWidth(' ') && // fm.charWidth(' ') == fm.charWidth('.')) { double w = font.getStringBounds(" ", frc).getWidth(); - if (w == font.getStringBounds("i", frc).getWidth() && + if (w == font.getStringBounds("i", frc).getWidth() && w == font.getStringBounds("M", frc).getWidth() && w == font.getStringBounds(".", frc).getWidth()) { - + // //PApplet.printArray(font.getAvailableAttributes()); // Map attr = font.getAttributes(); // System.out.println(font.getFamily() + " > " + font.getName()); // System.out.println(font.getAttributes()); // System.out.println(" " + attr.get(TextAttribute.WEIGHT)); // System.out.println(" " + attr.get(TextAttribute.POSTURE)); - + outgoing.add(font); // System.out.println(" good " + w); } @@ -685,8 +689,8 @@ public class Toolkit { } return outgoing; } - - + + static public String[] getMonoFontFamilies() { HashSet families = new HashSet(); for (Font font : getMonoFontList()) { @@ -710,15 +714,16 @@ public class Toolkit { } return monoFont.getName(); } - - + + static public Font getMonoFont(int size, int style) { if (monoFont == null) { try { monoFont = createFont("SourceCodePro-Regular.ttf", size); //monoBoldFont = createFont("SourceCodePro-Semibold.ttf", size); monoBoldFont = createFont("SourceCodePro-Bold.ttf", size); - if (!monoFont.canDisplay('α') || !monoFont.canDisplay('ω')) { + if (!monoFont.canDisplay(GREEK_SMALL_LETTER_ALPHA) || + !monoFont.canDisplay(GREEK_CAPITAL_LETTER_OMEGA)) { monoFont = createFont("Anonymous Pro.ttf", size); monoBoldFont = createFont("Anonymous Pro B.ttf", size); } @@ -749,7 +754,8 @@ public class Toolkit { try { sansFont = createFont("SourceSansPro-Regular.ttf", size); sansBoldFont = createFont("SourceSansPro-Semibold.ttf", size); - if (!sansFont.canDisplay('α') || !sansFont.canDisplay('ω')) { + if (!sansFont.canDisplay(GREEK_SMALL_LETTER_ALPHA) || + !sansFont.canDisplay(GREEK_CAPITAL_LETTER_OMEGA)) { sansFont = createFont("Carlito-Regular.ttf", size); sansBoldFont = createFont("Carlito-Bold.ttf", size); } @@ -776,11 +782,11 @@ public class Toolkit { } - /** - * Get a font from the JRE lib/fonts folder. Our default fonts are also + /** + * Get a font from the JRE lib/fonts folder. Our default fonts are also * installed there so that the monospace (and others) can be used by other - * font listing calls (i.e. it appears in the list of monospace fonts in - * the Preferences window). + * font listing calls (i.e. it appears in the list of monospace fonts in + * the Preferences window). */ static private Font createFont(String filename, int size) throws IOException, FontFormatException { //InputStream is = Base.getLibStream("fonts/" + filename); @@ -790,23 +796,23 @@ public class Toolkit { fontFile = new File(System.getProperty("user.dir"), "../build/shared/lib/fonts/" + filename); } if (!fontFile.exists()) { - // if we're debugging the new Java Mode from Eclipse, paths are different + // if we're debugging the new Java Mode from Eclipse, paths are different fontFile = new File(System.getProperty("user.dir"), "../../shared/lib/fonts/" + filename); } if (!fontFile.exists()) { Base.showError("Font Sadness", "Could not find required fonts", null); } - + BufferedInputStream input = new BufferedInputStream(new FileInputStream(fontFile)); Font font = Font.createFont(Font.TRUETYPE_FONT, input); input.close(); return font.deriveFont((float) size); } - - - /** - * Synthesized replacement for FontMetrics.getAscent(), which is dreadfully - * inaccurate and inconsistent across platforms. + + + /** + * Synthesized replacement for FontMetrics.getAscent(), which is dreadfully + * inaccurate and inconsistent across platforms. */ static double getAscent(Graphics g) { //, Font font) { Graphics2D g2 = (Graphics2D) g; @@ -814,9 +820,9 @@ public class Toolkit { //return new TextLayout("H", font, frc).getBounds().getHeight(); return new TextLayout("H", g.getFont(), frc).getBounds().getHeight(); } - - /** Do not use or rely upon presence of this method: not approved as final API. */ + + /** Do not use or rely upon presence of this method: not approved as final API. */ static public void debugOpacity(Component comp) { //Component parent = comp.getParent(); while (comp != null) { @@ -828,8 +834,8 @@ public class Toolkit { //EditorConsole.systemOut.println(); System.out.println(); } - - + + static public int getMenuItemIndex(JMenu menu, JMenuItem item) { int index = 0; for (Component comp : menu.getMenuComponents()) { diff --git a/app/src/processing/app/syntax/DefaultInputHandler.java b/app/src/processing/app/syntax/DefaultInputHandler.java old mode 100644 new mode 100755 diff --git a/app/src/processing/app/syntax/PdeInputHandler.java b/app/src/processing/app/syntax/PdeInputHandler.java old mode 100644 new mode 100755 index 198c33f89..d5950e320 --- a/app/src/processing/app/syntax/PdeInputHandler.java +++ b/app/src/processing/app/syntax/PdeInputHandler.java @@ -16,7 +16,7 @@ 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. + 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. @@ -25,6 +25,9 @@ package processing.app.syntax; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + import processing.app.Base; import processing.app.Preferences; @@ -35,7 +38,7 @@ import processing.app.Preferences; * use of Preferences and other PDE classes. */ public class PdeInputHandler extends DefaultInputHandler { - + public PdeInputHandler() { // Use option on mac for text edit controls that are ctrl on Windows/Linux. // (i.e. ctrl-left/right is option-left/right on OS X) @@ -183,4 +186,45 @@ public class PdeInputHandler extends DefaultInputHandler { addKeyBinding(mod + "+ENTER", InputHandler.REPEAT); } + + + public void keyPressed(KeyEvent event) { + // don't pass the ctrl-, through to the editor + // https://github.com/processing/processing/issues/3074 + if ((event.getModifiers() & InputEvent.CTRL_MASK) != 0 && + event.getKeyChar() == ',') { + return; + } + if (!handlePressed(event)) { + super.keyPressed(event); + } + } + + + public void keyTyped(KeyEvent event) { + if (!handleTyped(event)) { + super.keyTyped(event); + } + } + + + // we don't need keyReleased(), so that's passed through automatically + + + /** + * Override this function in your InputHandler to do any gymnastics. + * @return true if key has been handled (no further handling should be done) + */ + public boolean handlePressed(KeyEvent event) { + return false; + } + + + /** + * Override this instead of keyPressed/keyTyped + * @return true if key has been handled (no further handling should be done) + */ + public boolean handleTyped(KeyEvent event) { + return false; + } } \ No newline at end of file diff --git a/java/src/processing/mode/java/JavaEditor.java b/java/src/processing/mode/java/JavaEditor.java old mode 100644 new mode 100755 index f8d3f5daf..4967857a5 --- a/java/src/processing/mode/java/JavaEditor.java +++ b/java/src/processing/mode/java/JavaEditor.java @@ -152,7 +152,6 @@ public class JavaEditor extends Editor { protected JEditTextArea createTextArea() { - //return new JEditTextArea(new PdeTextAreaDefaults(mode), new JavaInputHandler(this)); return new JavaTextArea(new PdeTextAreaDefaults(mode), this); } @@ -204,7 +203,7 @@ public class JavaEditor extends Editor { } } }); - + JMenuItem presentItem = Toolkit.newJMenuItemShift(Language.text("toolbar.present"), 'R'); presentItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -1557,8 +1556,8 @@ public class JavaEditor extends Editor { return debugMenu; } - - + + protected boolean isDebuggerEnabled() { return enableDebug.isSelected(); } @@ -1898,7 +1897,7 @@ public class JavaEditor extends Editor { /** * Returns a list of AvailableContributions of those libraries that the user * wants imported, but that are not installed. - * + * * @param importHeaders */ private ArrayList getNotInstalledAvailableLibs(ArrayList importHeadersList) { @@ -2045,8 +2044,8 @@ public class JavaEditor extends Editor { // toolbar.activate(JavaToolbar.RUN); toolbar.activateRun(); } - - + + /** * Deactivate the Run button. This is called by Runner to notify that the * sketch has stopped running, usually in response to an error (or maybe @@ -2099,14 +2098,14 @@ public class JavaEditor extends Editor { enableDebug.setSelected(!enableDebug.isSelected()); updateDebugToggle(); } - - + + public void updateDebugToggle() { - final boolean enabled = enableDebug.isSelected(); + final boolean enabled = enableDebug.isSelected(); if (enabled) { tray.setFocusableWindowState(false); // to not get focus when set visible tray.setVisible(true); - tray.setFocusableWindowState(true); // allow to get focus again + tray.setFocusableWindowState(true); // allow to get focus again } else { tray.setVisible(false); } @@ -2116,8 +2115,8 @@ public class JavaEditor extends Editor { } } } - - + + // public void showVariableInspector() { // tray.setVisible(true); // } diff --git a/java/src/processing/mode/java/JavaInputHandler.java b/java/src/processing/mode/java/JavaInputHandler.java old mode 100644 new mode 100755 index 6506623c8..7d6c6df2f --- a/java/src/processing/mode/java/JavaInputHandler.java +++ b/java/src/processing/mode/java/JavaInputHandler.java @@ -48,25 +48,8 @@ public class JavaInputHandler extends PdeInputHandler { public JavaInputHandler(Editor editor) { - this.editor = editor; + this.editor = editor; } - - - public void keyPressed(KeyEvent event) { - if (!pressed(event)) { - super.keyPressed(event); - } - } - - - public void keyTyped(KeyEvent event) { - if (!typed(event)) { - super.keyTyped(event); - } - } - - - // we don't need keyReleased(), so that's passed through automatically /** @@ -77,7 +60,7 @@ public class JavaInputHandler extends PdeInputHandler { * keyTyped(). * @return true if the event has been handled (to remove it from the queue) */ - protected boolean pressed(KeyEvent event) { + public boolean handlePressed(KeyEvent event) { char c = event.getKeyChar(); int code = event.getKeyCode(); @@ -91,6 +74,7 @@ public class JavaInputHandler extends PdeInputHandler { if ((code == KeyEvent.VK_BACK_SPACE) || (code == KeyEvent.VK_TAB) || (code == KeyEvent.VK_ENTER) || ((c >= 32) && (c < 128))) { + System.out.println(event); sketch.setModified(true); } @@ -332,7 +316,7 @@ public class JavaInputHandler extends PdeInputHandler { } - protected boolean typed(KeyEvent event) { + public boolean handleTyped(KeyEvent event) { char c = event.getKeyChar(); if ((event.getModifiers() & InputEvent.CTRL_MASK) != 0) {