This patch (committed) adds keyboard bindings for the JSlider component. I followed
the description given here:
http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html
I also modified the scrollByBlock() and scrollByUnit() methods to behave more like
the reference implementation - positive values for the direction argument indicate
an increment, while zero or negative values indicate a decrement.
2006-04-17 David Gilbert <[EMAIL PROTECTED]>
* javax/swing/plaf/basic/BasicSliderUI.java
(installKeyboardActions): Implemented,
(uninstallKeyboardActions): Implemented,
(scrollByBlock): Accept any value for direction,
(scrollByUnit): Likewise,
(getInputMap): New method,
(getActionMap): New method,
(createActionMap): New method.
Regards,
Dave
Index: javax/swing/plaf/basic/BasicSliderUI.java
===================================================================
RCS file:
/sources/classpath/classpath/javax/swing/plaf/basic/BasicSliderUI.java,v
retrieving revision 1.27
diff -u -r1.27 BasicSliderUI.java
--- javax/swing/plaf/basic/BasicSliderUI.java 29 Mar 2006 21:26:11 -0000
1.27
+++ javax/swing/plaf/basic/BasicSliderUI.java 17 Apr 2006 06:31:04 -0000
@@ -63,7 +63,9 @@
import java.util.Enumeration;
import javax.swing.AbstractAction;
+import javax.swing.ActionMap;
import javax.swing.BoundedRangeModel;
+import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JSlider;
@@ -74,6 +76,7 @@
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MouseInputAdapter;
+import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.SliderUI;
@@ -871,9 +874,11 @@
* installed.
*/
protected void installKeyboardActions(JSlider slider)
- throws NotImplementedException
{
- // FIXME: implement.
+ InputMap keyMap = getInputMap(JComponent.WHEN_FOCUSED);
+ SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, keyMap);
+ ActionMap map = getActionMap();
+ SwingUtilities.replaceUIActionMap(slider, map);
}
/**
@@ -884,9 +889,9 @@
* uninstalled.
*/
protected void uninstallKeyboardActions(JSlider slider)
- throws NotImplementedException
{
- // FIXME: implement.
+ SwingUtilities.replaceUIActionMap(slider, null);
+ SwingUtilities.replaceUIInputMap(slider, JComponent.WHEN_FOCUSED, null);
}
/* XXX: This is all after experimentation with SUN's implementation.
@@ -2073,18 +2078,22 @@
}
/**
- * This method is used to move the thumb one block in the direction
- * specified. If the slider snaps to ticks, this method is responsible for
- * snapping it to a tick after the thumb has been moved.
- *
- * @param direction The direction to move in.
+ * Moves the thumb one block in the direction specified (a block is 1/10th
+ * of the slider range). If the slider snaps to ticks, this method is
+ * responsible for snapping it to a tick after the thumb has been moved.
+ *
+ * @param direction the direction (positive values increment the thumb
+ * position by one block, zero/negative values decrement the thumb position
+ * by one block).
*/
public void scrollByBlock(int direction)
{
- // The direction is -1 for backwards and 1 for forwards.
- int unit = direction * (slider.getMaximum() - slider.getMinimum()) / 10;
-
- int moveTo = slider.getValue() + unit;
+ int unit = (slider.getMaximum() - slider.getMinimum()) / 10;
+ int moveTo = slider.getValue();
+ if (direction > 0)
+ moveTo += unit;
+ else
+ moveTo -= unit;
if (slider.getSnapToTicks())
moveTo = findClosestTick(moveTo);
@@ -2093,16 +2102,21 @@
}
/**
- * This method is used to move the thumb one unit in the direction
- * specified. If the slider snaps to ticks, this method is responsible for
- * snapping it to a tick after the thumb has been moved.
- *
- * @param direction The direction to move in.
+ * Moves the thumb one unit in the specified direction. If the slider snaps
+ * to ticks, this method is responsible for snapping it to a tick after the
+ * thumb has been moved.
+ *
+ * @param direction the direction (positive values increment the thumb
+ * position by one, zero/negative values decrement the thumb position by
+ * one).
*/
public void scrollByUnit(int direction)
{
- // The direction is -1 for backwards and 1 for forwards.
- int moveTo = slider.getValue() + direction;
+ int moveTo = slider.getValue();
+ if (direction > 0)
+ moveTo++;
+ else
+ moveTo--;
if (slider.getSnapToTicks())
moveTo = findClosestTick(moveTo);
@@ -2316,4 +2330,113 @@
else
return value + minor;
}
+
+ InputMap getInputMap(int condition)
+ {
+ if (condition == JComponent.WHEN_FOCUSED)
+ return (InputMap) UIManager.get("Slider.focusInputMap");
+ return null;
+ }
+
+ /**
+ * Returns the action map for the [EMAIL PROTECTED] JSlider}. All sliders
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("JSlider.actionMap");
+
+ if (map == null) // first time here
+ {
+ map = createActionMap();
+ if (map != null)
+ UIManager.put("Slider.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)
+ {
+ if (slider.getInverted())
+ scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL);
+ else
+ scrollByUnit(BasicSliderUI.POSITIVE_SCROLL);
+ }
+ }
+ );
+ map.put("negativeUnitIncrement",
+ new AbstractAction("negativeUnitIncrement") {
+ public void actionPerformed(ActionEvent event)
+ {
+ if (slider.getInverted())
+ scrollByUnit(BasicSliderUI.POSITIVE_SCROLL);
+ else
+ scrollByUnit(BasicSliderUI.NEGATIVE_SCROLL);
+ }
+ }
+ );
+ map.put("positiveBlockIncrement",
+ new AbstractAction("positiveBlockIncrement") {
+ public void actionPerformed(ActionEvent event)
+ {
+ if (slider.getInverted())
+ scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL);
+ else
+ scrollByBlock(BasicSliderUI.POSITIVE_SCROLL);
+ }
+ }
+ );
+ map.put("negativeBlockIncrement",
+ new AbstractAction("negativeBlockIncrement") {
+ public void actionPerformed(ActionEvent event)
+ {
+ if (slider.getInverted())
+ scrollByBlock(BasicSliderUI.POSITIVE_SCROLL);
+ else
+ scrollByBlock(BasicSliderUI.NEGATIVE_SCROLL);
+ }
+ }
+ );
+ map.put("minScroll",
+ new AbstractAction("minScroll") {
+ public void actionPerformed(ActionEvent event)
+ {
+ if (slider.getInverted())
+ slider.setValue(slider.getMaximum());
+ else
+ slider.setValue(slider.getMinimum());
+ }
+ }
+ );
+ map.put("maxScroll",
+ new AbstractAction("maxScroll") {
+ public void actionPerformed(ActionEvent event)
+ {
+ if (slider.getInverted())
+ slider.setValue(slider.getMinimum());
+ else
+ slider.setValue(slider.getMaximum());
+ }
+ }
+ );
+ return map;
+ }
}