diff -r 1617c82406aa api.search/src/org/netbeans/modules/search/BasicSearchForm.java --- a/api.search/src/org/netbeans/modules/search/BasicSearchForm.java Fri Jan 10 00:14:07 2014 +0000 +++ b/api.search/src/org/netbeans/modules/search/BasicSearchForm.java Fri Jan 10 18:10:22 2014 +0100 @@ -276,6 +276,9 @@ replacementPatternEditor = (JTextComponent) cboxEditorComp; } this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); + UiUtils.fixComboBoxes(cboxTextToFind.getComponent(), cboxReplacement, + cboxScope.getComponent(), cboxFileNamePattern.getComponent(), + textToFindType); } /** diff -r 1617c82406aa api.search/src/org/netbeans/modules/search/ui/UiUtils.java --- a/api.search/src/org/netbeans/modules/search/ui/UiUtils.java Fri Jan 10 00:14:07 2014 +0000 +++ b/api.search/src/org/netbeans/modules/search/ui/UiUtils.java Fri Jan 10 18:10:22 2014 +0100 @@ -42,19 +42,34 @@ package org.netbeans.modules.search.ui; import java.awt.Color; +import java.awt.Component; import java.awt.EventQueue; +import java.awt.Window; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; import java.io.CharConversionException; import java.io.File; import java.io.IOException; import javax.swing.AbstractButton; +import javax.swing.Action; +import javax.swing.ComboBoxEditor; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; import javax.swing.JLabel; +import javax.swing.JRootPane; +import javax.swing.KeyStroke; import javax.swing.UIManager; import org.netbeans.modules.search.BasicSearchProvider; import org.openide.awt.Mnemonics; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.openide.xml.XMLUtil; /** @@ -158,4 +173,123 @@ "BasicSearchForm.cboxFileNamePattern.example"); //NOI18N } } + + /** + * Workaround bugs in checkboxes - they consume some key events on Mac with + * JDK8. See bug 239241. + * + * @param comboBoxes + */ + public static void fixComboBoxes(JComboBox... comboBoxes) { + + int javaVersion = -1; + String javaVersionStr = System.getProperty("java.version"); //NOI18N + if (javaVersionStr != null) { + String[] parts = javaVersionStr.split("\\."); //NOI18N + if (parts != null && parts.length > 1) { + try { + javaVersion = Integer.parseInt(parts[1]); + } catch (NumberFormatException e) { + } + } + } + + if (Utilities.isMac() && (javaVersion < 0 || javaVersion > 7) + && comboBoxes.length > 0) { + + KeyListener kl = new JComboBoxEscapeAndEnterListener(); + + for (JComboBox comboBox : comboBoxes) { + if (comboBox != null) { + comboBox.addKeyListener(kl); + ComboBoxEditor editor = comboBox.getEditor(); + if (editor != null) { + Component editorComponent = editor.getEditorComponent(); + if (editorComponent != null) { + editorComponent.addKeyListener(kl); + } + } + } + } + } + } + + /** + * Listener for Enter and Escape pressing in JComboBoxes. See + * {@link #fixComboBoxes(JComboBox...)}. + * + */ + private static class JComboBoxEscapeAndEnterListener extends KeyAdapter { + + /** + * Key pressed in a JComboBox or in its editor. + * + * @param e + */ + @Override + public void keyPressed(KeyEvent e) { + Object source = e.getSource(); + if (source instanceof Component) { + for (Component a = ((Component) source); a != null; + a = a.getParent()) { + if (a instanceof JComboBox) { + process((JComboBox) a, e); + return; + } + } + } + } + + /** + * Check whether the event should handled, find the containing dialog + * and invoke proper action in its root pane. + * + * @param comboBox + * @param e + */ + private void process(JComboBox comboBox, KeyEvent e) { + if (!comboBox.isPopupVisible() + && comboBox.getParent() != null + && (e.getKeyCode() == KeyEvent.VK_ESCAPE + || e.getKeyCode() == KeyEvent.VK_ENTER)) { + Component parent = comboBox; + while (parent != null && !(parent instanceof Window)) { + parent = parent.getParent(); + } + if (parent instanceof JDialog) { + JDialog dial = (JDialog) parent; + JRootPane rootPane = dial.getRootPane(); + invokeProperAction(e, rootPane); + } + } + } + + /** + * Invoke proper action for the event - click the default button or + * invoke the action associated with Escape key. + * + * @param e + * @param rootPane + */ + private void invokeProperAction(KeyEvent e, JRootPane rootPane) { + if (e.getKeyCode() == KeyEvent.VK_ENTER) { + JButton button = rootPane.getDefaultButton(); + if (button != null) { + button.doClick(); + } + } else { + Object key = rootPane.getInputMap( + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + .get(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)); + if (key != null) { + Action action = rootPane.getActionMap().get(key); + if (action != null) { + action.actionPerformed( + new ActionEvent(e.getSource(), + e.getID(), "Escape")); //NOI18N + } + } + } + } + } }