This patch (committed) adds keyboard bindings for the JScrollBar component:
2006-06-09 David Gilbert <[EMAIL PROTECTED]> * javax/swing/plaf/basic/BasicLookAndFeel.java (initComponentDefaults): Corrected 'ScrollBar.focusInputMap' entry, * javax/swing/plaf/basic/BasicScrollBarUI.java (installKeyboardActions): Implemented, (uninstallKeyboardActions): Implemented, (getInputMap): New method, (getActionMap): New method, (createActionMap): New method, (installUI): Call installKeyboardActions(), (uninstallUI): Call uninstallKeyboardActions(). Note that these only get used when a scrollbar has the focus, which is not common. Regards, Dave
Index: javax/swing/plaf/basic/BasicLookAndFeel.java =================================================================== RCS file: /sources/classpath/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java,v retrieving revision 1.91 diff -u -r1.91 BasicLookAndFeel.java --- javax/swing/plaf/basic/BasicLookAndFeel.java 6 Jun 2006 15:12:10 -0000 1.91 +++ javax/swing/plaf/basic/BasicLookAndFeel.java 9 Jun 2006 11:09:41 -0000 @@ -1069,14 +1069,14 @@ "PAGE_DOWN", "positiveBlockIncrement", "END", "maxScroll", "HOME", "minScroll", - "LEFT", "positiveUnitIncrement", + "LEFT", "negativeUnitIncrement", "KP_UP", "negativeUnitIncrement", "KP_DOWN", "positiveUnitIncrement", "UP", "negativeUnitIncrement", - "RIGHT", "negativeUnitIncrement", - "KP_LEFT", "positiveUnitIncrement", + "RIGHT", "positiveUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", "DOWN", "positiveUnitIncrement", - "KP_RIGHT", "negativeUnitIncrement" + "KP_RIGHT", "positiveUnitIncrement" }), "ScrollBar.foreground", new ColorUIResource(light), "ScrollBar.maximumThumbSize", new DimensionUIResource(4096, 4096), Index: javax/swing/plaf/basic/BasicScrollBarUI.java =================================================================== RCS file: /sources/classpath/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java,v retrieving revision 1.33 diff -u -r1.33 BasicScrollBarUI.java --- javax/swing/plaf/basic/BasicScrollBarUI.java 17 Apr 2006 07:41:05 -0000 1.33 +++ javax/swing/plaf/basic/BasicScrollBarUI.java 9 Jun 2006 11:09:42 -0000 @@ -1,5 +1,5 @@ /* BasicScrollBarUI.java -- - Copyright (C) 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 2004, 2005, 2006, Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,8 +38,6 @@ package javax.swing.plaf.basic; -import gnu.classpath.NotImplementedException; - import java.awt.Color; import java.awt.Component; import java.awt.Container; @@ -56,10 +54,14 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import javax.swing.AbstractAction; +import javax.swing.ActionMap; import javax.swing.BoundedRangeModel; +import javax.swing.InputMap; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollBar; +import javax.swing.JSlider; import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; @@ -67,6 +69,7 @@ import javax.swing.UIManager; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ScrollBarUI; @@ -762,15 +765,151 @@ } /** - * This method installs the keyboard actions for the scrollbar. + * Installs the input map from the look and feel defaults, and a + * corresponding action map. Note the the keyboard bindings will only + * work when the [EMAIL PROTECTED] JScrollBar} component has the focus, which is rare. */ protected void installKeyboardActions() - throws NotImplementedException { - // FIXME: implement. + InputMap keyMap = getInputMap( + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); + SwingUtilities.replaceUIInputMap(scrollbar, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keyMap); + ActionMap map = getActionMap(); + SwingUtilities.replaceUIActionMap(scrollbar, map); } /** + * Uninstalls the input map and action map installed by + * [EMAIL PROTECTED] #installKeyboardActions()}. + */ + protected void uninstallKeyboardActions() + { + SwingUtilities.replaceUIActionMap(scrollbar, null); + SwingUtilities.replaceUIInputMap(scrollbar, + JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); + } + + InputMap getInputMap(int condition) + { + if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) + return (InputMap) UIManager.get("ScrollBar.focusInputMap"); + return null; + } + + /** + * Returns the action map for the [EMAIL PROTECTED] JScrollBar}. All scroll bars + * share a single action map which is created the first time this method is + * called, then stored in the UIDefaults table for subsequent access. + * + * @return The shared action map. + */ + ActionMap getActionMap() + { + ActionMap map = (ActionMap) UIManager.get("ScrollBar.actionMap"); + + if (map == null) // first time here + { + map = createActionMap(); + if (map != null) + UIManager.put("ScrollBar.actionMap", map); + } + return map; + } + + /** + * Creates the action map shared by all [EMAIL PROTECTED] JSlider} instances. + * This method is called once by [EMAIL PROTECTED] #getActionMap()} when it + * finds no action map in the UIDefaults table...after the map is + * created, it gets added to the defaults table so that subsequent + * calls to [EMAIL PROTECTED] #getActionMap()} will return the same shared + * instance. + * + * @return The action map. + */ + ActionMap createActionMap() + { + ActionMap map = new ActionMapUIResource(); + map.put("positiveUnitIncrement", + new AbstractAction("positiveUnitIncrement") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + int delta = sb.getUnitIncrement(1); + sb.setValue(sb.getValue() + delta); + } + } + } + ); + map.put("positiveBlockIncrement", + new AbstractAction("positiveBlockIncrement") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + int delta = sb.getBlockIncrement(1); + sb.setValue(sb.getValue() + delta); + } + } + } + ); + map.put("negativeUnitIncrement", + new AbstractAction("negativeUnitIncrement") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + int delta = sb.getUnitIncrement(-1); + sb.setValue(sb.getValue() + delta); + } + } + } + ); + map.put("negativeBlockIncrement", + new AbstractAction("negativeBlockIncrement") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + int delta = sb.getBlockIncrement(-1); + sb.setValue(sb.getValue() + delta); + } + } + } + ); + map.put("minScroll", + new AbstractAction("minScroll") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + sb.setValue(sb.getMinimum()); + } + } + } + ); + map.put("maxScroll", + new AbstractAction("maxScroll") { + public void actionPerformed(ActionEvent event) + { + JScrollBar sb = (JScrollBar) event.getSource(); + if (sb.isVisible()) + { + sb.setValue(sb.getMaximum()); + } + } + } + ); + return map; + } + + /** * This method installs any listeners for the scrollbar. This method also * installs listeners for things such as the JButtons and the timer. */ @@ -806,19 +945,20 @@ super.installUI(c); if (c instanceof JScrollBar) { - scrollbar = (JScrollBar) c; + scrollbar = (JScrollBar) c; - trackRect = new Rectangle(); - thumbRect = new Rectangle(); + trackRect = new Rectangle(); + thumbRect = new Rectangle(); - scrollTimer = new Timer(300, null); + scrollTimer = new Timer(300, null); installDefaults(); - installComponents(); - configureScrollBarColors(); - installListeners(); + installComponents(); + configureScrollBarColors(); + installListeners(); + installKeyboardActions(); - calculatePreferredSize(); + calculatePreferredSize(); } } @@ -1140,16 +1280,6 @@ } /** - * This method uninstalls any keyboard actions this scrollbar acquired - * during install. - */ - protected void uninstallKeyboardActions() - throws NotImplementedException - { - // FIXME: implement. - } - - /** * This method uninstalls any listeners that were registered during install. */ protected void uninstallListeners() @@ -1186,6 +1316,7 @@ */ public void uninstallUI(JComponent c) { + uninstallKeyboardActions(); uninstallListeners(); uninstallDefaults(); uninstallComponents();