From 0a07d042c4b720bc8e0c102668fad4a9bc5faff2 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Tue, 16 Apr 2019 13:32:45 +0300 Subject: [PATCH] IDEA-178054: update tree actions to move selection (page up/down + home/end) --- .../com/intellij/util/ui/tree/TreeUtil.java | 4 +- .../intellij/ui/tree/ui/DefaultTreeUI.java | 1 + .../com/intellij/ui/tree/ui/TreeAction.java | 71 ++++++++++++++++--- 3 files changed, 65 insertions(+), 11 deletions(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java index 5c514e63ce7a..d057cd944c32 100644 --- a/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java +++ b/platform/platform-api/src/com/intellij/util/ui/tree/TreeUtil.java @@ -721,6 +721,8 @@ public final class TreeUtil { @SuppressWarnings("HardCodedStringLiteral") public static void installActions(@NotNull final JTree tree) { + TreeUI ui = tree.getUI(); + if (ui != null && ui.getClass().getName().equals("com.intellij.ui.tree.ui.DefaultTreeUI")) return; tree.getActionMap().put("scrollUpChangeSelection", new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { @@ -733,8 +735,6 @@ public final class TreeUtil { movePageDown(tree); } }); - TreeUI ui = tree.getUI(); - if (ui != null && ui.getClass().getName().equals("com.intellij.ui.tree.ui.DefaultTreeUI")) return; tree.getActionMap().put("selectPrevious", new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java index 215e13f4d59b..97f4616d3f1c 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/DefaultTreeUI.java @@ -256,6 +256,7 @@ public final class DefaultTreeUI extends BasicTreeUI { protected void installKeyboardActions() { super.installKeyboardActions(); TreeAction.installTo(tree.getActionMap()); + TreeAction.installTo(tree.getInputMap(JComponent.WHEN_FOCUSED)); } @Override diff --git a/platform/platform-impl/src/com/intellij/ui/tree/ui/TreeAction.java b/platform/platform-impl/src/com/intellij/ui/tree/ui/TreeAction.java index dd30b15c6303..f1b87adf34ac 100644 --- a/platform/platform-impl/src/com/intellij/ui/tree/ui/TreeAction.java +++ b/platform/platform-impl/src/com/intellij/ui/tree/ui/TreeAction.java @@ -11,13 +11,29 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.plaf.UIResource; import javax.swing.tree.TreePath; +import java.awt.Rectangle; import java.awt.event.ActionEvent; -import java.util.Arrays; +import java.awt.event.KeyEvent; import java.util.List; +import static java.util.Arrays.asList; +import static javax.swing.KeyStroke.getKeyStroke; + abstract class TreeAction extends AbstractAction implements UIResource { - private static final List ACTIONS = Arrays.asList( - new TreeAction(TreeActions.Up.ID) { + private static final List ACTIONS = asList( + new TreeAction(TreeActions.Home.ID, getKeyStroke(KeyEvent.VK_HOME, 0)) { + @Override + void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { + scrollAndSetSelection(tree, 0); + } + }, + new TreeAction(TreeActions.End.ID, getKeyStroke(KeyEvent.VK_END, 0)) { + @Override + void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { + scrollAndSetSelection(tree, tree.getRowCount() - 1); + } + }, + new TreeAction(TreeActions.Up.ID, getKeyStroke(KeyEvent.VK_UP, 0), getKeyStroke(KeyEvent.VK_KP_UP, 0)) { @Override void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { int row = tree.getRowForPath(path); @@ -31,7 +47,7 @@ abstract class TreeAction extends AbstractAction implements UIResource { } } }, - new TreeAction(TreeActions.Down.ID) { + new TreeAction(TreeActions.Down.ID, getKeyStroke(KeyEvent.VK_DOWN, 0), getKeyStroke(KeyEvent.VK_KP_DOWN, 0)) { @Override void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { int row = tree.getRowForPath(path); @@ -45,7 +61,7 @@ abstract class TreeAction extends AbstractAction implements UIResource { } } }, - new TreeAction(TreeActions.Left.ID) { + new TreeAction(TreeActions.Left.ID, getKeyStroke(KeyEvent.VK_LEFT, 0), getKeyStroke(KeyEvent.VK_KP_LEFT, 0)) { @Override void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { int row = tree.getRowForPath(path); @@ -68,7 +84,7 @@ abstract class TreeAction extends AbstractAction implements UIResource { } } }, - new TreeAction(TreeActions.Right.ID) { + new TreeAction(TreeActions.Right.ID, getKeyStroke(KeyEvent.VK_RIGHT, 0), getKeyStroke(KeyEvent.VK_KP_RIGHT, 0)) { @Override void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { int row = tree.getRowForPath(path); @@ -82,11 +98,42 @@ abstract class TreeAction extends AbstractAction implements UIResource { tree.expandPath(path); } } + }, + new TreeAction(TreeActions.PageUp.ID, getKeyStroke(KeyEvent.VK_PAGE_UP, 0)) { + @Override + void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { + Rectangle bounds = tree.getPathBounds(path); + if (path == null || bounds == null) { + scrollAndSetSelection(tree, 0); + } + else { + int height = Math.max(tree.getVisibleRect().height - bounds.height, 1); + TreePath next = tree.getClosestPathForLocation(bounds.x, bounds.y - height); + if (next != null && !next.equals(path)) scrollAndSetSelection(tree, next); + } + } + }, + new TreeAction(TreeActions.PageDown.ID, getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0)) { + @Override + void actionPerformed(@NotNull JTree tree, @Nullable TreePath path) { + Rectangle bounds = tree.getPathBounds(path); + if (path == null || bounds == null) { + scrollAndSetSelection(tree, tree.getRowCount() - 1); + } + else { + int height = Math.max(tree.getVisibleRect().height - bounds.height, 1); + TreePath next = tree.getClosestPathForLocation(bounds.x, bounds.y + bounds.height + height); + if (next != null && !next.equals(path)) scrollAndSetSelection(tree, next); + } + } } ); + private final String name; + private final List keys; - TreeAction(@NotNull String name) { - super(name); + TreeAction(@NotNull String name, @NotNull KeyStroke... keys) { + this.name = name; + this.keys = asList(keys); } abstract void actionPerformed(@NotNull JTree tree, @Nullable TreePath path); @@ -103,7 +150,13 @@ abstract class TreeAction extends AbstractAction implements UIResource { static void installTo(@NotNull ActionMap map) { Object[] keys = map.keys(); if (keys != null && keys.length != 0) return; // actions are already installed - for (TreeAction action : ACTIONS) map.put(action.getValue(NAME), action); + for (TreeAction action : ACTIONS) map.put(action.name, action); + } + + static void installTo(@NotNull InputMap map) { + Object[] keys = map.keys(); + if (keys != null && keys.length != 0) return; // keys for actions are already installed + for (TreeAction action : ACTIONS) for (KeyStroke key : action.keys) map.put(key, action.name); } static void scrollAndSetSelection(@NotNull JTree tree, int row) {