diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java index 2a668c4cb46c..072aea54019c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ChooseActionsDialog.java @@ -19,41 +19,85 @@ */ package com.intellij.openapi.keymap.impl.ui; +import com.intellij.ide.CommonActionsManager; +import com.intellij.ide.TreeExpander; +import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.QuickList; +import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.popup.JBPopup; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.IconLoader; +import com.intellij.packageDependencies.ui.TreeExpansionMonitor; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.FilterComponent; +import com.intellij.util.Alarm; import com.intellij.util.ArrayUtil; +import com.intellij.util.IJSwingUtilities; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.tree.TreeUtil; import javax.swing.*; +import javax.swing.border.EmptyBorder; +import javax.swing.event.DocumentEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.util.ArrayList; public class ChooseActionsDialog extends DialogWrapper { private final ActionsTree myActionsTree; + private FilterComponent myFilterComponent; + private TreeExpansionMonitor myTreeExpansionMonitor; + private Keymap myKeymap; + private QuickList[] myQuicklists; + private JBPopup myPopup; public ChooseActionsDialog(Component parent, Keymap keymap, QuickList[] quicklists) { super(parent, true); + myKeymap = keymap; + myQuicklists = quicklists; myActionsTree = new ActionsTree(); myActionsTree.reset(keymap, quicklists); myActionsTree.getTree().getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + myActionsTree.getTree().addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + doOKAction(); + } + } + }); + + myTreeExpansionMonitor = TreeExpansionMonitor.install(myActionsTree.getTree()); + setTitle("Add Actions to Quick List"); init(); } + @Override + protected JComponent createNorthPanel() { + return createToolbarPanel(); + } + @Override protected JComponent createCenterPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.add(myActionsTree.getComponent()); panel.setPreferredSize(new Dimension(400, 500)); - + return panel; } - + public String[] getTreeSelectedActionIds() { TreePath[] paths = myActionsTree.getTree().getSelectionPaths(); if (paths == null) return ArrayUtil.EMPTY_STRING_ARRAY; @@ -74,4 +118,160 @@ public class ChooseActionsDialog extends DialogWrapper { } return ArrayUtil.toStringArray(actions); } + + private JPanel createToolbarPanel() { + final JPanel panel = new JPanel(new BorderLayout()); + DefaultActionGroup group = new DefaultActionGroup(); + final JComponent toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); + final CommonActionsManager commonActionsManager = CommonActionsManager.getInstance(); + final TreeExpander treeExpander = new TreeExpander() { + public void expandAll() { + TreeUtil.expandAll(myActionsTree.getTree()); + } + + public boolean canExpand() { + return true; + } + + public void collapseAll() { + TreeUtil.collapseAll(myActionsTree.getTree(), 0); + } + + public boolean canCollapse() { + return true; + } + }; + group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree())); + group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree())); + + panel.add(toolbar, BorderLayout.WEST); + group = new DefaultActionGroup(); + final JComponent searchToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent(); + final Alarm alarm = new Alarm(); + myFilterComponent = new FilterComponent("KEYMAP_IN_QUICK_LISTS", 5) { + public void filter() { + alarm.cancelAllRequests(); + alarm.addRequest(new Runnable() { + public void run() { + if (!myFilterComponent.isShowing()) return; + if (!myTreeExpansionMonitor.isFreeze()) myTreeExpansionMonitor.freeze(); + final String filter = getFilter(); + myActionsTree.filter(filter, myQuicklists); + final JTree tree = myActionsTree.getTree(); + TreeUtil.expandAll(tree); + if (filter == null || filter.length() == 0) { + TreeUtil.collapseAll(tree, 0); + myTreeExpansionMonitor.restore(); + } + } + }, 300); + } + }; + myFilterComponent.reset(); + + panel.add(myFilterComponent, BorderLayout.CENTER); + + group.add(new AnAction(KeyMapBundle.message("filter.shortcut.action.text"), + KeyMapBundle.message("filter.shortcut.action.text"), + IconLoader.getIcon("/ant/shortcutFilter.png")) { + public void actionPerformed(AnActionEvent e) { + myFilterComponent.reset(); + if (myPopup == null || myPopup.getContent() == null) { + myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(createFilteringPanel(), null) + .setRequestFocus(true) + .setTitle(KeyMapBundle.message("filter.settings.popup.title")) + .setMovable(true) + .createPopup(); + } + myPopup.showUnderneathOf(searchToolbar); + } + }); + group.add(new AnAction(KeyMapBundle.message("filter.clear.action.text"), + KeyMapBundle.message("filter.clear.action.text"), IconLoader.getIcon("/actions/gc.png")) { + public void actionPerformed(AnActionEvent e) { + myActionsTree.filter(null, myQuicklists); //clear filtering + TreeUtil.collapseAll(myActionsTree.getTree(), 0); + myTreeExpansionMonitor.restore(); + } + }); + + panel.add(searchToolbar, BorderLayout.EAST); + return panel; + } + + private void filterTreeByShortcut(final ShortcutTextField firstShortcut, + final JCheckBox enable2Shortcut, + final ShortcutTextField secondShortcut) { + final KeyStroke keyStroke = firstShortcut.getKeyStroke(); + if (keyStroke != null) { + if (!myTreeExpansionMonitor.isFreeze()) myTreeExpansionMonitor.freeze(); + myActionsTree.filterTree(new KeyboardShortcut(keyStroke, enable2Shortcut.isSelected() ? secondShortcut.getKeyStroke() : null), + myQuicklists); + final JTree tree = myActionsTree.getTree(); + TreeUtil.expandAll(tree); + } + } + + private JPanel createFilteringPanel() { + myActionsTree.reset(myKeymap, myQuicklists); + + final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); + final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.second.stroke.input")); + final ShortcutTextField firstShortcut = new ShortcutTextField(); + firstShortcut.setColumns(10); + final ShortcutTextField secondShortcut = new ShortcutTextField(); + secondShortcut.setColumns(10); + + enable2Shortcut.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + secondShortcut.setEnabled(enable2Shortcut.isSelected()); + if (enable2Shortcut.isSelected()) { + secondShortcut.requestFocusInWindow(); + } + } + }); + + firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + IJSwingUtilities.adjustComponentsOnMac(firstLabel, firstShortcut); + JPanel filterComponent = FormBuilder.createFormBuilder() + .addLabeledComponent(firstLabel, firstShortcut, true) + .addComponent(enable2Shortcut) + .setVerticalGap(0) + .setIndent(5) + .addComponent(secondShortcut) + .getPanel(); + + filterComponent.setBorder(new EmptyBorder(UIUtil.PANEL_SMALL_INSETS)); + + enable2Shortcut.setSelected(false); + secondShortcut.setEnabled(false); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + firstShortcut.requestFocus(); + } + }); + return filterComponent; + } + + + public void dispose() { + super.dispose(); + if (myPopup != null && myPopup.isVisible()) { + myPopup.cancel(); + } + if (myFilterComponent != null) { + myFilterComponent.dispose(); + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index a53ec8bed25b..6d223a185ef1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -50,12 +50,16 @@ import com.intellij.ui.DocumentAdapter; import com.intellij.ui.FilterComponent; import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Alarm; +import com.intellij.util.IJSwingUtilities; import com.intellij.util.containers.HashMap; +import com.intellij.util.ui.FormBuilder; +import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import javax.swing.border.EmptyBorder; import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.*; @@ -119,7 +123,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi if (shortcuts != null) { for (Shortcut shortcut : shortcuts) { - impl.removeShortcut(actionId, shortcut); + impl.removeShortcut(actionId, shortcut); impl.addShortcut(newActionId, shortcut); } } @@ -270,7 +274,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi importButton.setMargin(insets); panel.add(importButton,gc); - + } @@ -376,7 +380,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi }; group.add(commonActionsManager.createExpandAllAction(treeExpander, myActionsTree.getTree())); group.add(commonActionsManager.createCollapseAllAction(treeExpander, myActionsTree.getTree())); - + group.add(new AnAction("Edit Shortcut", "Edit Shortcut", IconLoader.getIcon("/actions/properties.png")) { { registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), myActionsTree.getTree()); @@ -459,40 +463,45 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi private JPanel createFilteringPanel() { myActionsTree.reset(getSelectedKeymap(), getCurrentQuickListIds()); - JPanel filterComponent = new JPanel(new GridBagLayout()); - filterComponent.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2)); + final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); + final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.second.stroke.input")); final ShortcutTextField firstShortcut = new ShortcutTextField(); final ShortcutTextField secondShortcut = new ShortcutTextField(); - final JCheckBox enable2Shortcut = new JCheckBox(KeyMapBundle.message("filter.enable.second.stroke.checkbox")); - firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { - filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); - } - }); - secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { - protected void textChanged(DocumentEvent e) { - filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); - } - }); - final JLabel firstLabel = new JLabel(KeyMapBundle.message("filter.first.stroke.input")); - final JLabel secondLabel = new JLabel(KeyMapBundle.message("filter.second.stroke.input")); - filterComponent.add(firstLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(5,2,0,0),0,0)); - filterComponent.add(firstShortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); + enable2Shortcut.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { secondShortcut.setEnabled(enable2Shortcut.isSelected()); - secondLabel.setEnabled(enable2Shortcut.isSelected()); if (enable2Shortcut.isSelected()){ secondShortcut.requestFocusInWindow(); } } }); - filterComponent.add(enable2Shortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,0,0,0),0,0)); - filterComponent.add(secondLabel, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); - filterComponent.add(secondShortcut, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 2, 1, 1, 0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0,2,0,0),0,0)); + + firstShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + secondShortcut.getDocument().addDocumentListener(new DocumentAdapter() { + protected void textChanged(DocumentEvent e) { + filterTreeByShortcut(firstShortcut, enable2Shortcut, secondShortcut); + } + }); + + IJSwingUtilities.adjustComponentsOnMac(firstLabel, firstShortcut); + JPanel filterComponent = FormBuilder.createFormBuilder() + .addLabeledComponent(firstLabel, firstShortcut, true) + .addComponent(enable2Shortcut) + .setVerticalGap(0) + .setIndent(5) + .addComponent(secondShortcut) + .getPanel(); + + filterComponent.setBorder(new EmptyBorder(UIUtil.PANEL_SMALL_INSETS)); + enable2Shortcut.setSelected(false); - secondLabel.setEnabled(false); secondShortcut.setEnabled(false); SwingUtilities.invokeLater(new Runnable() { public void run() { @@ -938,7 +947,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi DefaultActionGroup group = new DefaultActionGroup(); final Shortcut[] shortcuts = mySelectedKeymap.getShortcuts(actionId); - + group.add(new AnAction("Add Keyboard Shortcut") { @Override public void actionPerformed(AnActionEvent e) { @@ -953,7 +962,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi addKeyboardShortcut(firstKeyboard); } }); - + group.add(new AnAction("Add Mouse Shortcut") { @Override public void actionPerformed(AnActionEvent e) { @@ -991,7 +1000,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, true); - + if (e instanceof MouseEvent) { popup.show(new RelativePoint((MouseEvent)e)); }