diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java index 2219db857c25..49c48af5c80e 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindPopupPanel.java @@ -35,6 +35,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileChooser.FileChooser; import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; @@ -45,7 +46,6 @@ import com.intellij.openapi.progress.util.ReadTask; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.*; -import com.intellij.openapi.ui.popup.Balloon; import com.intellij.openapi.ui.popup.ComponentPopupBuilder; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.JBPopupFactory; @@ -102,6 +102,15 @@ import static com.intellij.find.impl.FindDialog.createCheckbox; public class FindPopupPanel extends JBPanel { private static final Logger LOG = Logger.getInstance("#com.intellij.find.impl.FindPopupPanel"); private static final KeyStroke OK_KEYSTROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK); + + private static final KeyStroke MOVE_CARET_DOWN = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0); + private static final KeyStroke MOVE_CARET_UP = KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0); + private static final KeyStroke NEW_LINE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0); + + private static final KeyStroke MOVE_CARET_DOWN_ALTERNATIVE = KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK); + private static final KeyStroke MOVE_CARET_UP_ALTERNATIVE = KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK); + private static final KeyStroke NEW_LINE_ALTERNATIVE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.ALT_DOWN_MASK); + private JComponent myCodePreviewComponent; private SearchTextArea mySearchTextArea; private SearchTextArea myReplaceTextArea; @@ -489,27 +498,10 @@ public class FindPopupPanel extends JBPanel { new NavigateToSourceListener().installOn(myResultsPreviewTable); applyFont(JBUI.Fonts.smallFont(), myCbCaseSensitive, myCbPreserveCase, myCbWholeWordsOnly, myCbRegularExpressions, myResultsPreviewTable); - - registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - //if (IdeFocusManager.findInstance().getFocusOwner() == myResultsPreviewTable) return; - int row = myResultsPreviewTable.getSelectedRow(); - if (row >= myResultsPreviewTable.getRowCount() - 1) return; - myResultsPreviewTable.getSelectionModel().setSelectionInterval(row + 1, row + 1); - TableUtil.scrollSelectionToVisible(myResultsPreviewTable); - } - }, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.ALT_DOWN_MASK), WHEN_IN_FOCUSED_WINDOW); - registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - //if (IdeFocusManager.findInstance().getFocusOwner() == myResultsPreviewTable) return; - int row = myResultsPreviewTable.getSelectedRow(); - if (row < 1) return; - myResultsPreviewTable.getSelectionModel().setSelectionInterval(row - 1, row - 1); - TableUtil.scrollSelectionToVisible(myResultsPreviewTable); - } - }, KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.ALT_DOWN_MASK), WHEN_IN_FOCUSED_WINDOW); + KeymapUtil.reassignAction(mySearchComponent, MOVE_CARET_DOWN, MOVE_CARET_DOWN_ALTERNATIVE, WHEN_IN_FOCUSED_WINDOW); + KeymapUtil.reassignAction(mySearchComponent, MOVE_CARET_UP, MOVE_CARET_UP_ALTERNATIVE, WHEN_IN_FOCUSED_WINDOW); + KeymapUtil.reassignAction(mySearchComponent, NEW_LINE, NEW_LINE_ALTERNATIVE, WHEN_IN_FOCUSED_WINDOW); + UIUtil.redirectKeystrokes(myDisposable, mySearchComponent, myResultsPreviewTable, MOVE_CARET_UP, MOVE_CARET_DOWN, NEW_LINE); myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation()) { @@ -574,7 +566,7 @@ public class FindPopupPanel extends JBPanel { private static final int POPUP_MAX_WIDTH = 600; private void scheduleUpdateResultsPopupBounds() { - if (myUpdateResultsPopupBoundsAlarm == null) return; + if (myUpdateResultsPopupBoundsAlarm == null || myUpdateResultsPopupBoundsAlarm.isDisposed()) return; boolean later = myUpdateResultsPopupBoundsAlarm.getActiveRequestCount() > 0; myUpdateResultsPopupBoundsAlarm.cancelAllRequests(); @@ -785,7 +777,7 @@ public class FindPopupPanel extends JBPanel { private void scheduleResultsUpdate() { if (myFindBalloon == null || !myFindBalloon.isVisible()) return; - if (mySearchRescheduleOnCancellationsAlarm == null) return; + if (mySearchRescheduleOnCancellationsAlarm == null || mySearchRescheduleOnCancellationsAlarm.isDisposed()) return; mySearchRescheduleOnCancellationsAlarm.cancelAllRequests(); mySearchRescheduleOnCancellationsAlarm.addRequest(new Runnable() { @Override @@ -1208,8 +1200,7 @@ public class FindPopupPanel extends JBPanel { String key = "navigate.to.usage"; JComponent component = (JComponent)c; - component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), - key); + component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(NEW_LINE, key); component.getActionMap().put(key, new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { @@ -1236,8 +1227,7 @@ public class FindPopupPanel extends JBPanel { if (navigations != null) { applyTo(FindManager.getInstance(myProject).getFindInProjectModel(), false); - Balloon balloon = JBPopupFactory.getInstance().getParentBalloonFor(this); - if (balloon != null) balloon.hide(); + myFindBalloon.cancel(); navigations.get(0).navigate(true); for (int i = 1; i < navigations.size(); ++i) navigations.get(i).highlightInEditor(); diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapUtil.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapUtil.java index 57b95cb9d49d..b1d41bf55e22 100644 --- a/platform/platform-api/src/com/intellij/openapi/keymap/KeymapUtil.java +++ b/platform/platform-api/src/com/intellij/openapi/keymap/KeymapUtil.java @@ -32,6 +32,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; @@ -433,4 +434,30 @@ public class KeymapUtil { } return false; } + + /** + * @param component target component to reassign previously mapped action (if any) + * @param oldKeyStroke previously mapped keystroke (e.g. standard one that you want to use in some different way) + * @param newKeyStroke new keystroke to be assigned. null value means 'just unregister previously mapped action' + * @param condition one of + * + * @return true if the action is reassigned successfully + */ + public static boolean reassignAction(@NotNull JComponent component, + @NotNull KeyStroke oldKeyStroke, + @Nullable KeyStroke newKeyStroke, + int condition) { + ActionListener action = component.getActionForKeyStroke(oldKeyStroke); + if (action == null) return false; + if (newKeyStroke != null) { + component.registerKeyboardAction(action, newKeyStroke, condition); + } + component.unregisterKeyboardAction(oldKeyStroke); + return true; + } } diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index c6f5824086db..6a73cf1f8a31 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -3620,4 +3620,37 @@ public class UIUtil { } return ComponentStyle.REGULAR; } + + /** + * KeyEvents for specified keystrokes would be redispatched to target component + */ + public static void redirectKeystrokes(@NotNull Disposable disposable, + @NotNull final JComponent source, + @NotNull final JComponent target, + @NotNull final KeyStroke... keyStrokes) { + final KeyAdapter keyAdapter = new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + KeyStroke keyStrokeForEvent = KeyStroke.getKeyStrokeForEvent(e); + for (KeyStroke stroke : keyStrokes) { + if (!stroke.isOnKeyRelease() && stroke.equals(keyStrokeForEvent)) target.dispatchEvent(e); + } + } + + @Override + public void keyReleased(KeyEvent e) { + KeyStroke keyStrokeForEvent = KeyStroke.getKeyStrokeForEvent(e); + for (KeyStroke stroke : keyStrokes) { + if (stroke.isOnKeyRelease() && stroke.equals(keyStrokeForEvent)) target.dispatchEvent(e); + } + } + }; + source.addKeyListener(keyAdapter); + Disposer.register(disposable, new Disposable() { + @Override + public void dispose() { + source.removeKeyListener(keyAdapter); + } + }); + } }