diff --git a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java index a3e47b104f91..051890149bfd 100644 --- a/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java +++ b/platform/o.n.swing.laf.flatlaf/src/org/netbeans/swing/laf/flatlaf/FlatLFCustoms.java @@ -91,6 +91,8 @@ public Object[] createApplicationSpecificKeysAndValues() { EDITOR_TOOLBAR_BORDER, new CompoundBorder(DPISafeBorder.matte(0, 0, 1, 0, editorContentBorderColor), BorderFactory.createEmptyBorder(1, 0, 1, 0)), "NbExplorerView.quicksearch.border.instance", new CompoundBorder(DPISafeBorder.matte(1, 0, 0, 0, editorContentBorderColor), BorderFactory.createEmptyBorder(2, 6, 2, 2)), + "NbExplorerView.quicksearch.listview.border.instance", + new CompoundBorder(DPISafeBorder.matte(1, 1, 1, 1, editorContentBorderColor), BorderFactory.createEmptyBorder(2, 6, 2, 2)), EDITOR_TAB_CONTENT_BORDER, DPISafeBorder.matte(0, 1, 1, 1, editorContentBorderColor), VIEW_TAB_CONTENT_BORDER, DPISafeBorder.matte(0, 1, 1, 1, UIManager.getColor("TabbedContainer.view.contentBorderColor")), // NOI18N diff --git a/platform/openide.awt/src/org/openide/awt/QuickSearch.java b/platform/openide.awt/src/org/openide/awt/QuickSearch.java index 045490240576..68df579848ff 100644 --- a/platform/openide.awt/src/org/openide/awt/QuickSearch.java +++ b/platform/openide.awt/src/org/openide/awt/QuickSearch.java @@ -36,6 +36,7 @@ import org.netbeans.api.annotations.common.StaticResource; import org.openide.util.ImageUtilities; import org.openide.util.RequestProcessor; +import org.openide.util.Utilities; /** * Quick search infrastructure for an arbitrary component. @@ -52,7 +53,9 @@ public class QuickSearch { @StaticResource private static final String ICON_FIND_WITH_MENU = "org/openide/awt/resources/quicksearch/findMenu.png"; // NOI18N private static final Object CLIENT_PROPERTY_KEY = new Object(); - + private static final KeyStroke NEXT_ALTERNATIVE_KEY_STROKE = Utilities.stringToKey("D-G"); + private static final KeyStroke PREVIOUS_ALTERNATIVE_KEY_STROKE = Utilities.stringToKey("DS-G"); + private final JComponent component; private final Object constraints; private final Callback callback; @@ -288,10 +291,12 @@ private void fireQuickSearchUpdate(String searchText) { } private void fireShowNextSelection(boolean forward) { - if (asynchronous) { - rp.post(new LazyFire(QS_FIRE.NEXT, forward)); - } else { - callback.showNextSelection(forward); + if (hasSearchText) { + if (asynchronous) { + rp.post(new LazyFire(QS_FIRE.NEXT, forward)); + } else { + callback.showNextSelection(forward); + } } } @@ -354,6 +359,23 @@ public void keyTyped(KeyEvent e) { if(isAlwaysShown()) { displaySearchField(); } + component.getActionMap().put("openQuickSearch", new AbstractAction() { + @Override + public void actionPerformed(ActionEvent evt) { + if (searchPanel != null && isEnabled()) { + searchTextField.selectAll(); + return; + } + if (searchPanel != null || !isEnabled()) { + return; + } + searchTextField.setText(""); + displaySearchField(); + } + }); + InputMap im = component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + im.put(Utilities.stringToKey("D-F"), "openQuickSearch"); + im.put(Utilities.stringToKey("F3"), "openQuickSearch"); } private void displaySearchField() { @@ -678,7 +700,7 @@ public void run() { } ); } - + @Override public boolean isManagingFocus() { return true; @@ -707,9 +729,14 @@ public void processKeyEvent(KeyEvent ke) { } else { if (!hasSearchText) { int keyCode = ke.getKeyCode(); + KeyStroke ks = KeyStroke.getKeyStrokeForEvent(ke); if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT || - keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_F3) { + keyCode == KeyEvent.VK_TAB || keyCode == KeyEvent.VK_F3 || + keyCode == KeyEvent.VK_ENTER && ke.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || + NEXT_ALTERNATIVE_KEY_STROKE.equals(ks) || + PREVIOUS_ALTERNATIVE_KEY_STROKE.equals(ks)) + { // Ignore movement events when search text was not set return ; } @@ -748,6 +775,7 @@ public void removeUpdate(DocumentEvent e) { @Override public void keyPressed(KeyEvent e) { int keyCode = e.getKeyCode(); + KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e); if (keyCode == KeyEvent.VK_ESCAPE) { removeSearchField(); @@ -763,12 +791,22 @@ public void keyPressed(KeyEvent e) { callback.quickSearchCanceled(); hasSearchText = false; e.consume(); - } else if (keyCode == KeyEvent.VK_UP || (keyCode == KeyEvent.VK_F3 && e.isShiftDown())) { + } else if (keyCode == KeyEvent.VK_UP || + keyCode == KeyEvent.VK_F3 && e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || + keyCode == KeyEvent.VK_ENTER && e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || + PREVIOUS_ALTERNATIVE_KEY_STROKE.equals(ks)) + { fireShowNextSelection(false); // Stop processing the event here. Otherwise it's dispatched // to the tree too (which scrolls) e.consume(); - } else if (keyCode == KeyEvent.VK_DOWN || keyCode == KeyEvent.VK_F3) { + } else if (keyCode == KeyEvent.VK_DOWN || + keyCode == KeyEvent.VK_F3 && e.getModifiersEx() == 0 || + /* We can't use ENTER to go to the next match, as this keystroke is used to + invoke the row's default action. */ + /* keyCode == KeyEvent.VK_ENTER && e.getModifiersEx() == 0 || */ + NEXT_ALTERNATIVE_KEY_STROKE.equals(ks)) + { fireShowNextSelection(true); // Stop processing the event here. Otherwise it's dispatched // to the tree too (which scrolls) diff --git a/platform/openide.explorer/nbproject/project.xml b/platform/openide.explorer/nbproject/project.xml index 0da4747fd437..74e90390a5e6 100644 --- a/platform/openide.explorer/nbproject/project.xml +++ b/platform/openide.explorer/nbproject/project.xml @@ -25,6 +25,15 @@ org.openide.explorer + + org.netbeans.api.annotations.common + + + + 1 + 1.13 + + org.netbeans.swing.outline diff --git a/platform/openide.explorer/src/org/openide/explorer/view/ListView.java b/platform/openide.explorer/src/org/openide/explorer/view/ListView.java index dd99297921e8..744a1ae61a88 100644 --- a/platform/openide.explorer/src/org/openide/explorer/view/ListView.java +++ b/platform/openide.explorer/src/org/openide/explorer/view/ListView.java @@ -45,7 +45,6 @@ import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.BorderFactory; -import javax.swing.BoxLayout; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JList; @@ -58,6 +57,8 @@ import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; +import javax.swing.UIManager; +import javax.swing.border.Border; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListDataEvent; @@ -73,10 +74,11 @@ import org.openide.nodes.Node.Property; import org.openide.nodes.NodeOp; import org.openide.util.Mutex; -import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.util.WeakListeners; import org.openide.util.actions.CallbackSystemAction; +import org.netbeans.api.annotations.common.StaticResource; +import org.openide.util.ImageUtilities; /** Explorer view to display items in a list. *

@@ -112,6 +114,13 @@ * @author Ian Formanek, Jan Jancura, Jaroslav Tulach */ public class ListView extends JScrollPane implements Externalizable { + @StaticResource + private static final String ICON_FIND = "org/openide/explorer/view/find.png"; // NOI18N + private static final KeyStroke NEXT_ALTERNATIVE_KEY_STROKE = Utilities.stringToKey("D-G"); + private static final KeyStroke PREVIOUS_ALTERNATIVE_KEY_STROKE = Utilities.stringToKey("DS-G"); + private static final KeyStroke OPEN_SEARCH_KEY_STROKE = Utilities.stringToKey("D-F"); + private static final KeyStroke OPEN_SEARCH_ALTERNATIVE_KEY_STROKE = Utilities.stringToKey("F3"); + /** generated Serialized Version UID */ static final long serialVersionUID = -7540940974042262975L; @@ -1035,6 +1044,13 @@ private void setupSearch() { public void keyPressed(KeyEvent e) { int modifiers = e.getModifiers(); int keyCode = e.getKeyCode(); + KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e); + + if (OPEN_SEARCH_KEY_STROKE.equals(ks) || OPEN_SEARCH_ALTERNATIVE_KEY_STROKE.equals(ks)) { + searchTextField.setText(""); + displaySearchField(); + return; + } if (((modifiers > 0) && (modifiers != KeyEvent.SHIFT_MASK)) || e.isActionKey()) { return; @@ -1108,12 +1124,17 @@ private void prepareSearchPanel() { if (searchpanel == null) { searchpanel = new JPanel(); - JLabel lbl = new JLabel(NbBundle.getMessage(TreeView.class, "LBL_QUICKSEARCH")); //NOI18N + JLabel lbl = new JLabel(ImageUtilities.loadImageIcon(ICON_FIND, false)); //NOI18N searchpanel.setLayout(new BorderLayout(5, 0)); searchpanel.add(lbl, BorderLayout.WEST); searchpanel.add(searchTextField, BorderLayout.CENTER); lbl.setLabelFor(searchTextField); - searchpanel.setBorder(BorderFactory.createRaisedBevelBorder()); + Border customBorder = UIManager.getBorder("NbExplorerView.quicksearch.listview.border.instance"); + if (customBorder != null) { + searchpanel.setBorder(customBorder); + } else { + searchpanel.setBorder(BorderFactory.createRaisedBevelBorder()); + } } } @@ -1216,19 +1237,30 @@ public void removeUpdate(DocumentEvent e) { @Override public void keyPressed(KeyEvent e) { + // Recognize the same keystrokes as in org.openide.awt.QuickSearch. int keyCode = e.getKeyCode(); + KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e); if (keyCode == KeyEvent.VK_ESCAPE) { removeSearchField(); NbList.this.requestFocus(); - } else if (keyCode == KeyEvent.VK_UP) { + } else if (OPEN_SEARCH_KEY_STROKE.equals(ks) || OPEN_SEARCH_ALTERNATIVE_KEY_STROKE.equals(ks)) { + searchTextField.selectAll(); + } else if (keyCode == KeyEvent.VK_UP || + keyCode == KeyEvent.VK_F3 && e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || + keyCode == KeyEvent.VK_ENTER && e.getModifiersEx() == KeyEvent.SHIFT_DOWN_MASK || + PREVIOUS_ALTERNATIVE_KEY_STROKE.equals(ks)) + { currentSelectionIndex--; displaySearchResult(); // Stop processing the event here. Otherwise it's dispatched // to the tree too (which scrolls) e.consume(); - } else if (keyCode == KeyEvent.VK_DOWN) { + } else if (keyCode == KeyEvent.VK_DOWN || + keyCode == KeyEvent.VK_F3 && e.getModifiersEx() == 0 || + NEXT_ALTERNATIVE_KEY_STROKE.equals(ks)) + { currentSelectionIndex++; displaySearchResult(); diff --git a/platform/openide.explorer/src/org/openide/explorer/view/TableQuickSearchSupport.java b/platform/openide.explorer/src/org/openide/explorer/view/TableQuickSearchSupport.java index 2a0232374ea8..f93f8eea8d36 100644 --- a/platform/openide.explorer/src/org/openide/explorer/view/TableQuickSearchSupport.java +++ b/platform/openide.explorer/src/org/openide/explorer/view/TableQuickSearchSupport.java @@ -87,8 +87,10 @@ public void quickSearchUpdate(String searchText) { quickSearchInitialColumn = 0; } } - quickSearchLastRow = quickSearchInitialRow; - quickSearchLastColumn = quickSearchInitialColumn; + if (quickSearchLastRow < 0 || quickSearchLastColumn < 0) { + quickSearchLastRow = quickSearchInitialRow; + quickSearchLastColumn = quickSearchInitialColumn; + } doSearch(searchText, true); } @@ -152,14 +154,18 @@ public void quickSearchConfirmed() { quickSearchInitialColumn = -1; } + private static final boolean RESTORE_PRIOR_SELECTION_AFTER_QUICK_SEARCH = false; + @Override public void quickSearchCanceled() { // Check whether the cancel was explicit or implicit. // Implicit cancel has undefined focus owner // TODO: After switch to JDK 8, we can e.g. add a static method to Callback providing the info. - Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); - if (focusOwner != null) { - displaySearchResult(quickSearchInitialRow, quickSearchInitialColumn); + if (RESTORE_PRIOR_SELECTION_AFTER_QUICK_SEARCH) { + Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + if (focusOwner != null) { + displaySearchResult(quickSearchInitialRow, quickSearchInitialColumn); + } } quickSearchInitialRow = -1; quickSearchInitialColumn = -1; diff --git a/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java b/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java index 79527ac175d5..32b89ef1c0f6 100644 --- a/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java +++ b/platform/openide.explorer/src/org/openide/explorer/view/TreeView.java @@ -1957,12 +1957,14 @@ public void quickSearchUpdate(String searchText) { @Override public void showNextSelection(boolean forward) { - if (forward) { - currentSelectionIndex++; - } else { - currentSelectionIndex--; + if (lastSearchText != null) { + if (forward) { + currentSelectionIndex++; + } else { + currentSelectionIndex--; + } + displaySearchResult(); } - displaySearchResult(); } @Override @@ -2096,7 +2098,7 @@ private void displaySearchResult() { setSelectionPath(path); scrollPathToVisible(path); } else { - if (lastSearchText.isEmpty() && origSelectionPaths != null) { + if ((lastSearchText == null || lastSearchText.isEmpty()) && origSelectionPaths != null) { setSelectionPaths(origSelectionPaths); scrollPathToVisible(origSelectionPaths[0]); } else {