/* * Copyright 2000-2017 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.ui; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonShortcuts; import com.intellij.openapi.actionSystem.CustomShortcutSet; import com.intellij.openapi.actionSystem.ShortcutSet; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.util.Couple; import com.intellij.ui.speedSearch.SpeedSearchSupply; import com.intellij.util.ui.UIUtil; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.text.JTextComponent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; /** * A helper class for registering Keymap aware navigation actions for lists and trees * * @author Konstantin Bulenkov * @since 15.0 */ public class ScrollingUtil { private static final Logger LOG = Logger.getInstance("#com.intellij.ui.ScrollingUtil"); @NonNls protected static final String SCROLLUP_ACTION_ID = "scrollUp"; @NonNls protected static final String SCROLLDOWN_ACTION_ID = "scrollDown"; @NonNls protected static final String SELECT_PREVIOUS_ROW_ACTION_ID = "selectPreviousRow"; @NonNls protected static final String SELECT_NEXT_ROW_ACTION_ID = "selectNextRow"; @NonNls protected static final String SELECT_LAST_ROW_ACTION_ID = "selectLastRow"; @NonNls protected static final String SELECT_FIRST_ROW_ACTION_ID = "selectFirstRow"; @NonNls protected static final String MOVE_HOME_ID = "MOVE_HOME"; @NonNls protected static final String MOVE_END_ID = "MOVE_END"; public static final int ROW_PADDING = 2; public static void selectItem(JList list, int index) { LOG.assertTrue(index >= 0); LOG.assertTrue(index < list.getModel().getSize()); ensureIndexIsVisible(list, index, 0); list.setSelectedIndex(index); } public static void ensureSelectionExists(JList list) { int size = list.getModel().getSize(); if (size == 0) { list.clearSelection(); return; } int selectedIndex = list.getSelectedIndex(); if (selectedIndex < 0 || selectedIndex >= size) { // fit index to [0, size-1] range selectedIndex = 0; } selectItem(list, selectedIndex); } public static boolean selectItem(JList list, @NotNull Object item) { ListModel model = list.getModel(); for (int i = 0; i < model.getSize(); i++) { Object anItem = model.getElementAt(i); if (item.equals(anItem)) { selectItem(list, i); return true; } } return false; } public static void movePageUp(JList list) { int visible = getVisibleRowCount(list); ListSelectionModel selectionModel = list.getSelectionModel(); if (visible <= 0) { moveHome(list); return; } int size = list.getModel().getSize(); int decrement = visible - 1; int index = Math.max(list.getSelectedIndex() - decrement, 0); int top = list.getFirstVisibleIndex() - decrement; if (top < 0) { top = 0; } int bottom = top + visible - 1; if (bottom >= size) { bottom = size - 1; } //list.clearSelection(); Rectangle cellBounds = list.getCellBounds(top, bottom); if (cellBounds == null) { moveHome(list); return; } list.scrollRectToVisible(cellBounds); selectionModel.setSelectionInterval(index,index); list.ensureIndexIsVisible(index); } public static void movePageDown(JList list) { int visible = getVisibleRowCount(list); if (visible <= 0) { moveEnd(list); return; } int size = list.getModel().getSize(); int increment = visible - 1; int index = Math.min(list.getSelectedIndex() + increment, size - 1); int top = list.getFirstVisibleIndex() + increment; int bottom = top + visible - 1; if (bottom >= size) { bottom = size - 1; } //list.clearSelection(); Rectangle cellBounds = list.getCellBounds(top, bottom); if (cellBounds == null) { moveEnd(list); return; } list.scrollRectToVisible(cellBounds); list.setSelectedIndex(index); list.ensureIndexIsVisible(index); } public static void moveHome(JList list) { list.setSelectedIndex(0); list.ensureIndexIsVisible(0); } public static void moveEnd(JList list) { int index = list.getModel().getSize() - 1; list.setSelectedIndex(index); list.ensureIndexIsVisible(index); } public static void ensureIndexIsVisible(JList list, int index, int moveDirection) { _ensureIndexIsVisible(list, index, moveDirection, list.getModel().getSize()); } public static void ensureIndexIsVisible(JTable table, int index, int moveDirection) { _ensureIndexIsVisible(table, index, moveDirection, table.getRowCount()); } private static void _ensureIndexIsVisible(JComponent c, int index, int moveDirection, int size) { int visible = visibleRowCount(c); int top; int bottom; if (moveDirection == 0) { top = index - (visible - 1) / ROW_PADDING; bottom = top + visible - 1; } else if (moveDirection < 0) { top = index - ROW_PADDING; bottom = index; } else { top = index; bottom = index + ROW_PADDING; } if (top < 0) { top = 0; } if (bottom >= size) { bottom = size - 1; } _ensureRangeIsVisible(c, top, bottom); } public static void ensureRangeIsVisible(JList list, int top, int bottom) { int size = list.getModel().getSize(); if (top < 0) { top = 0; } if (bottom >= size) { bottom = size - 1; } Rectangle cellBounds = list.getCellBounds(top, bottom); if (cellBounds != null) { cellBounds.x = 0; list.scrollRectToVisible(cellBounds); } } private static void _ensureRangeIsVisible(JComponent c, int top, int bottom) { if (c instanceof JList) { JList list = ((JList)c); int size = list.getModel().getSize(); if (top < 0) { top = 0; } if (bottom >= size) { bottom = size - 1; } Rectangle cellBounds = list.getCellBounds(top, bottom); if (cellBounds != null) { cellBounds.x = 0; c.scrollRectToVisible(cellBounds); } } else if (c instanceof JTable) { JTable table = (JTable)c; Rectangle cellBounds = getCellBounds(table, top, bottom); cellBounds.x = 0; table.scrollRectToVisible(cellBounds); } } public static boolean isIndexFullyVisible(JList list, int index) { int first = list.getFirstVisibleIndex(); int last = list.getLastVisibleIndex(); if (index < 0 || first < 0 || last < 0 || index < first || index > last) { return false; } if (index > first && index < last) { return true; } return list.getVisibleRect().contains(list.getCellBounds(index, index)); } private static int getVisibleRowCount(JList list) { return list.getLastVisibleIndex() - list.getFirstVisibleIndex() + 1; } public static void moveDown(JList list, @JdkConstants.InputEventMask final int modifiers) { _moveDown(list, list.getSelectionModel(), modifiers, list.getModel().getSize(), UISettings.getInstance().getCycleScrolling()); } private static void selectOrAddSelection(ListSelectionModel selectionModel, int indexToSelect, @JdkConstants.InputEventMask int modifiers) { if (selectionModel.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) { selectionModel.setSelectionInterval(indexToSelect,indexToSelect); } else { if ((modifiers & InputEvent.SHIFT_DOWN_MASK) == 0) { selectionModel.removeSelectionInterval(selectionModel.getMinSelectionIndex(), selectionModel.getMaxSelectionIndex()); } selectionModel.addSelectionInterval(indexToSelect, indexToSelect); } } public static void installActions(final JList list) { installActions(list, null); } public static void installActions(final JList list, @Nullable JComponent focusParent) { ActionMap actionMap = list.getActionMap(); actionMap.put(SCROLLUP_ACTION_ID, new MoveAction(SCROLLUP_ACTION_ID, list)); actionMap.put(SCROLLDOWN_ACTION_ID, new MoveAction(SCROLLDOWN_ACTION_ID, list)); actionMap.put(SELECT_PREVIOUS_ROW_ACTION_ID, new MoveAction(SELECT_PREVIOUS_ROW_ACTION_ID, list)); actionMap.put(SELECT_NEXT_ROW_ACTION_ID, new MoveAction(SELECT_NEXT_ROW_ACTION_ID, list)); actionMap.put(SELECT_LAST_ROW_ACTION_ID, new MoveAction(SELECT_LAST_ROW_ACTION_ID, list)); actionMap.put(SELECT_FIRST_ROW_ACTION_ID, new MoveAction(SELECT_FIRST_ROW_ACTION_ID, list)); actionMap.put(MOVE_HOME_ID, new MoveAction(MOVE_HOME_ID, list)); actionMap.put(MOVE_END_ID, new MoveAction(MOVE_END_ID, list)); maybeInstallDefaultShortcuts(list); installMoveUpAction(list, focusParent); installMoveDownAction(list, focusParent); installMovePageUpAction(list, focusParent); installMovePageDownAction(list, focusParent); if (!(focusParent instanceof JTextComponent)) { installMoveHomeAction(list, focusParent); installMoveEndAction(list, focusParent); } } public static void installMoveEndAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMoveEnd(), focusParent == null ? list : focusParent){ @Override public void actionPerformed(AnActionEvent e) { moveEnd(list); } }; } public static void installMoveHomeAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMoveHome(), focusParent == null ? list : focusParent){ @Override public void actionPerformed(AnActionEvent e) { moveHome(list); } }; } public static void installMovePageDownAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMovePageDown(), focusParent == null ? list : focusParent){ @Override public void actionPerformed(AnActionEvent e) { movePageDown(list); } }; } public static void installMovePageUpAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMovePageUp(), focusParent == null ? list : focusParent){ @Override public void actionPerformed(AnActionEvent e) { movePageUp(list); } }; } public static void installMoveDownAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMoveDown(), focusParent == null ? list : focusParent){ @Override public void actionPerformed(AnActionEvent e) { moveDown(list, 0); } }; } public static void installMoveUpAction(final JList list, @Nullable JComponent focusParent) { new ListScrollAction(CommonShortcuts.getMoveUp(), focusParent == null ? list : focusParent) { @Override public void actionPerformed(AnActionEvent e) { moveUp(list, 0); } }; } static void maybeInstallDefaultShortcuts(JComponent component) { InputMap map = component.getInputMap(JComponent.WHEN_FOCUSED); UIUtil.maybeInstall(map, SCROLLUP_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, 0)); UIUtil.maybeInstall(map, SCROLLDOWN_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, 0)); UIUtil.maybeInstall(map, SELECT_PREVIOUS_ROW_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)); UIUtil.maybeInstall(map, SELECT_NEXT_ROW_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)); UIUtil.maybeInstall(map, SELECT_FIRST_ROW_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_HOME, 0)); UIUtil.maybeInstall(map, SELECT_LAST_ROW_ACTION_ID, KeyStroke.getKeyStroke(KeyEvent.VK_END, 0)); UIUtil.maybeInstall(map, MOVE_HOME_ID, KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)); UIUtil.maybeInstall(map, MOVE_END_ID, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)); } public interface ScrollingAction extends DumbAware { } public static abstract class ListScrollAction extends MyScrollingAction { protected ListScrollAction(final ShortcutSet shortcutSet, final JComponent component) { super(component); registerCustomShortcutSet(shortcutSet, component); } } public static void ensureSelectionExists(@NotNull JTable table) { int size = table.getModel().getRowCount(); if (size == 0) { table.clearSelection(); return; } int selectedIndex = table.getSelectedRow(); boolean reselect = false; if (selectedIndex < 0 || selectedIndex >= size) { // fit index to [0, size-1] range selectedIndex = 0; reselect = true; } ensureIndexIsVisible(table, selectedIndex, 0); if (reselect) { table.getSelectionModel().setSelectionInterval(selectedIndex, selectedIndex); } } @NotNull private static Rectangle getCellBounds(JTable table, int top, int bottom) { return table.getCellRect(top, 0, true).union(table.getCellRect(bottom,0,true)); } private static int visibleRowCount(JComponent c) { if (c instanceof JList) return getVisibleRowCount((JList)c); if (c instanceof JTable) return getVisibleRowCount((JTable)c); return -1; } private static int getVisibleRowCount(JTable table) { Rectangle visibleRect = table.getVisibleRect(); return getTrailingRow(table, visibleRect) - getLeadingRow(table, visibleRect) + 1; } public static Couple<Integer> getVisibleRows(JTable table) { Rectangle visibleRect = table.getVisibleRect(); return Couple.of(getLeadingRow(table, visibleRect) + 1, getTrailingRow(table, visibleRect)); } private static int getLeadingRow(JTable table, Rectangle visibleRect) { return table.rowAtPoint(getLeadingPoint(table, visibleRect)); } private static Point getLeadingPoint(JTable table, Rectangle visibleRect) { if (table.getComponentOrientation().isLeftToRight()) { return new Point(visibleRect.x, visibleRect.y); } else { return new Point(visibleRect.x + visibleRect.width, visibleRect.y); } } public static int getReadableRow(JTable table, int maximumHiddenPart) { Rectangle visibleRect = table.getVisibleRect(); Point leadingPoint = getLeadingPoint(table, visibleRect); int row = table.rowAtPoint(leadingPoint); int column = table.columnAtPoint(leadingPoint); if (leadingPoint.y - table.getCellRect(row, column, true).getY() <= maximumHiddenPart) { return row; } else { return Math.min(row + 1, table.getRowCount() - 1); // just in case } } public static boolean isVisible(JTable table, int row) { Rectangle visibleRect = table.getVisibleRect(); int start = getLeadingRow(table, visibleRect); int end = getTrailingRow(table, visibleRect); return row >= start && row <= end; } private static int getTrailingRow(JTable table, Rectangle visibleRect) { Point trailingPoint; if (table.getComponentOrientation().isLeftToRight()) { trailingPoint = new Point(visibleRect.x, visibleRect.y + visibleRect.height - 1); } else { trailingPoint = new Point(visibleRect.x + visibleRect.width, visibleRect.y + visibleRect.height - 1); } return table.rowAtPoint(trailingPoint); } public static void moveDown(JTable table, @JdkConstants.InputEventMask int modifiers, boolean cycleScrolling) { _moveDown(table, table.getSelectionModel(), modifiers, table.getRowCount(), cycleScrolling); } public static void moveUp(JList list, @JdkConstants.InputEventMask int modifiers) { _moveUp(list, list.getSelectionModel(), list.getModel().getSize(), modifiers, UISettings.getInstance().getCycleScrolling()); } public static void moveUp(JTable table, @JdkConstants.InputEventMask int modifiers, boolean cycleScrolling) { _moveUp(table, table.getSelectionModel(), table.getModel().getRowCount(), modifiers, cycleScrolling); } private static void _moveDown(JComponent c, ListSelectionModel selectionModel, @JdkConstants.InputEventMask final int modifiers, int size, boolean cycleScrolling) { _move(c, selectionModel, modifiers, size, cycleScrolling, +1); } private static void _move(JComponent c, ListSelectionModel selectionModel, @JdkConstants.InputEventMask final int modifiers, int size, boolean cycleScrolling, int direction) { if (size == 0) return; int index = selectionModel.getLeadSelectionIndex(); int indexToSelect = index + direction; if (indexToSelect < 0 || indexToSelect == size) { if (cycleScrolling) { indexToSelect = indexToSelect < 0 ? size - 1 : 0; } else { return; } } _ensureIndexIsVisible(c, indexToSelect, -1, size); selectOrAddSelection(selectionModel, indexToSelect, modifiers); } private static void _moveUp(JComponent c, ListSelectionModel selectionModel, int size, @JdkConstants.InputEventMask int modifiers, boolean cycleScrolling) { _move(c, selectionModel, modifiers, size, cycleScrolling, -1); } public static void moveHome(JTable table) { table.getSelectionModel().setSelectionInterval(0,0); ensureIndexIsVisible(table, 0,0); } public static void moveEnd(JTable table) { int index = table.getModel().getRowCount() - 1; table.getSelectionModel().setSelectionInterval(index, index); ensureIndexIsVisible(table, index, 0); } public static void movePageUp(JTable table) { int visible = getVisibleRowCount(table); if (visible <= 0) { moveHome(table); return; } int size = table.getModel().getRowCount(); int decrement = visible - 1; ListSelectionModel selectionModel = table.getSelectionModel(); int index = Math.max(selectionModel.getMinSelectionIndex() - decrement, 0); int visibleIndex = getLeadingRow(table, table.getVisibleRect()); int top = visibleIndex - decrement; if (top < 0) { top = 0; } int bottom = top + visible - 1; if (bottom >= size) { bottom = size - 1; } Rectangle cellBounds = getCellBounds(table, top, bottom); table.scrollRectToVisible(cellBounds); table.getSelectionModel().setSelectionInterval(index, index); ensureIndexIsVisible(table, index, 0); } public static void movePageDown(JTable table) { int visible = getVisibleRowCount(table); if (visible <= 0) { moveEnd(table); return; } ListSelectionModel selectionModel = table.getSelectionModel(); int size = table.getModel().getRowCount(); int increment = visible - 1; int index = Math.min(selectionModel.getMinSelectionIndex() + increment, size - 1); int firstVisibleRow = getLeadingRow(table, table.getVisibleRect()); int top = firstVisibleRow + increment; int bottom = top + visible - 1; if (bottom >= size) { bottom = size - 1; } Rectangle cellBounds = getCellBounds(table, top, bottom); table.scrollRectToVisible(cellBounds); table.getSelectionModel().setSelectionInterval(index, index); ensureIndexIsVisible(table, index, 0); } public static void installActions(final JTable table) { installActions(table, UISettings.getInstance().getCycleScrolling()); } private abstract static class MyScrollingAction extends DumbAwareAction implements ScrollingAction { private final JComponent myComponent; MyScrollingAction(JComponent component) { myComponent = component; } @Override public void update(AnActionEvent e) { e.getPresentation().setEnabled(SpeedSearchSupply.getSupply(myComponent) == null && !isEmpty(myComponent)); } } public static boolean isEmpty(JComponent component) { if (component instanceof JTable) return ((JTable)component).getRowCount() < 1; if (component instanceof JList) return ((JList)component).getModel().getSize() <1; return false; } public static void installActions(final JTable table, final boolean cycleScrolling) { installActions(table, cycleScrolling, null); } public static void installActions(final JTable table, final boolean cycleScrolling, JComponent focusParent) { ActionMap actionMap = table.getActionMap(); actionMap.put(SCROLLUP_ACTION_ID, new MoveAction(SCROLLUP_ACTION_ID, table, cycleScrolling)); actionMap.put(SCROLLDOWN_ACTION_ID, new MoveAction(SCROLLDOWN_ACTION_ID, table, cycleScrolling)); actionMap.put(SELECT_PREVIOUS_ROW_ACTION_ID, new MoveAction(SELECT_PREVIOUS_ROW_ACTION_ID, table, cycleScrolling)); actionMap.put(SELECT_NEXT_ROW_ACTION_ID, new MoveAction(SELECT_NEXT_ROW_ACTION_ID, table, cycleScrolling)); actionMap.put(SELECT_LAST_ROW_ACTION_ID, new MoveAction(SELECT_LAST_ROW_ACTION_ID, table, cycleScrolling)); actionMap.put(SELECT_FIRST_ROW_ACTION_ID, new MoveAction(SELECT_FIRST_ROW_ACTION_ID, table, cycleScrolling)); maybeInstallDefaultShortcuts(table); JComponent target = focusParent == null ? table : focusParent; new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveHome(table); } }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)), table); new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveEnd(table); } }.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0)), table); if (!(focusParent instanceof JTextComponent)) { new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveHome(table); } }.registerCustomShortcutSet(CommonShortcuts.getMoveHome(), target); new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveEnd(table); } }.registerCustomShortcutSet(CommonShortcuts.getMoveEnd(), target); } new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveDown(table, e.getModifiers(), cycleScrolling); } }.registerCustomShortcutSet(CommonShortcuts.getMoveDown(), target); new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { moveUp(table, e.getModifiers(), cycleScrolling); } }.registerCustomShortcutSet(CommonShortcuts.getMoveUp(), target); new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { movePageUp(table); } }.registerCustomShortcutSet(CommonShortcuts.getMovePageUp(), target); new MyScrollingAction(table) { @Override public void actionPerformed(AnActionEvent e) { movePageDown(table); } }.registerCustomShortcutSet(CommonShortcuts.getMovePageDown(), target); } static class MoveAction extends AbstractAction { private final String myId; private final JComponent myComponent; private Boolean myCycleScrolling; public MoveAction(String id, JComponent component, Boolean cycleScrolling) { myId = id; myComponent = component; myCycleScrolling = cycleScrolling; } public MoveAction(String id, JComponent component) { this(id, component, null); } @Override public void actionPerformed(ActionEvent e) { final int modifiers = e.getModifiers(); if (SCROLLUP_ACTION_ID.equals(myId)) doPageUp(); else if (SCROLLDOWN_ACTION_ID.equals(myId)) doPageDown(); else if (SELECT_PREVIOUS_ROW_ACTION_ID.equals(myId)) doMoveUp(modifiers); else if (SELECT_NEXT_ROW_ACTION_ID.equals(myId)) doMoveDown(modifiers); else if (SELECT_LAST_ROW_ACTION_ID.equals(myId)) doMoveEnd(); else if (SELECT_FIRST_ROW_ACTION_ID.equals(myId)) doMoveHome(); else if (MOVE_END_ID.equals(myId)) doMoveEnd(); else if (MOVE_HOME_ID.equals(myId)) doMoveHome(); } private void doMoveEnd() { if (myComponent instanceof JList) moveEnd((JList)myComponent); else if (myComponent instanceof JTable) moveEnd((JTable)myComponent); else throw new IllegalArgumentException("MoveEnd is not implemented for " + myComponent.getClass()); } private void doMoveHome() { if (myComponent instanceof JList) moveHome((JList)myComponent); else if (myComponent instanceof JTable) moveHome((JTable)myComponent); else throw new IllegalArgumentException("MoveHome is not implemented for " + myComponent.getClass()); } private void doMoveUp(@JdkConstants.InputEventMask int modifiers) { if (myComponent instanceof JList) moveUp((JList)myComponent, modifiers); else if (myComponent instanceof JTable) moveUp((JTable)myComponent, modifiers, isCycleScrolling()); else throw new IllegalArgumentException("MoveUp is not implemented for " + myComponent.getClass()); } private void doMoveDown(@JdkConstants.InputEventMask int modifiers) { if (myComponent instanceof JList) moveDown((JList)myComponent, modifiers); else if (myComponent instanceof JTable) moveDown((JTable)myComponent, modifiers, isCycleScrolling()); else throw new IllegalArgumentException("MoveDown is not implemented for " + myComponent.getClass()); } private void doPageUp() { if (myComponent instanceof JList) movePageUp((JList)myComponent); else if (myComponent instanceof JTable) movePageUp((JTable)myComponent); else throw new IllegalArgumentException("PageUp is not implemented for " + myComponent.getClass()); } private void doPageDown() { if (myComponent instanceof JList) movePageDown((JList)myComponent); else if (myComponent instanceof JTable) movePageDown((JTable)myComponent); else throw new IllegalArgumentException("PageDown is not implemented for " + myComponent.getClass()); } private boolean isCycleScrolling() { return myCycleScrolling == null ? UISettings.getInstance().getCycleScrolling() : myCycleScrolling.booleanValue(); } } }