[cp-patches] FYI: JScrollBar keyboard bindings

David Gilbert david.gilbert at object-refinery.com
Fri Jun 9 11:33:51 UTC 2006


This patch (committed) adds keyboard bindings for the JScrollBar component:

2006-06-09  David Gilbert  <david.gilbert at object-refinery.com>

	* 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
-------------- next part --------------
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 {@link 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
+   * {@link #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 {@link 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 {@link JSlider} instances.
+   * This method is called once by {@link #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 {@link #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();


More information about the Classpath-patches mailing list