7194184: JColorChooser swatch cannot accessed from keyboard
Reviewed-by: rupashka, alexsch
--- a/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java Tue Sep 18 17:38:40 2012 +0400
+++ b/jdk/src/share/classes/javax/swing/colorchooser/DefaultSwatchChooserPanel.java Thu Sep 20 17:39:47 2012 +0400
@@ -57,6 +57,8 @@
RecentSwatchPanel recentSwatchPanel;
MouseListener mainSwatchListener;
MouseListener recentSwatchListener;
+ private KeyListener mainSwatchKeyListener;
+ private KeyListener recentSwatchKeyListener;
public DefaultSwatchChooserPanel() {
super();
@@ -151,10 +153,14 @@
recentSwatchPanel.putClientProperty(AccessibleContext.ACCESSIBLE_NAME_PROPERTY,
recentStr);
+ mainSwatchKeyListener = new MainSwatchKeyListener();
mainSwatchListener = new MainSwatchListener();
swatchPanel.addMouseListener(mainSwatchListener);
+ swatchPanel.addKeyListener(mainSwatchKeyListener);
recentSwatchListener = new RecentSwatchListener();
+ recentSwatchKeyListener = new RecentSwatchKeyListener();
recentSwatchPanel.addMouseListener(recentSwatchListener);
+ recentSwatchPanel.addKeyListener(recentSwatchKeyListener);
JPanel mainHolder = new JPanel(new BorderLayout());
Border border = new CompoundBorder( new LineBorder(Color.black),
@@ -196,11 +202,17 @@
public void uninstallChooserPanel(JColorChooser enclosingChooser) {
super.uninstallChooserPanel(enclosingChooser);
swatchPanel.removeMouseListener(mainSwatchListener);
+ swatchPanel.removeKeyListener(mainSwatchKeyListener);
recentSwatchPanel.removeMouseListener(recentSwatchListener);
+ recentSwatchPanel.removeKeyListener(recentSwatchKeyListener);
+
swatchPanel = null;
recentSwatchPanel = null;
mainSwatchListener = null;
+ mainSwatchKeyListener = null;
recentSwatchListener = null;
+ recentSwatchKeyListener = null;
+
removeAll(); // strip out all the sub-components
}
@@ -209,11 +221,32 @@
}
+ private class RecentSwatchKeyListener extends KeyAdapter {
+ public void keyPressed(KeyEvent e) {
+ if (KeyEvent.VK_SPACE == e.getKeyCode()) {
+ Color color = recentSwatchPanel.getSelectedColor();
+ setSelectedColor(color);
+ }
+ }
+ }
+
+ private class MainSwatchKeyListener extends KeyAdapter {
+ public void keyPressed(KeyEvent e) {
+ if (KeyEvent.VK_SPACE == e.getKeyCode()) {
+ Color color = swatchPanel.getSelectedColor();
+ setSelectedColor(color);
+ recentSwatchPanel.setMostRecentColor(color);
+ }
+ }
+ }
+
class RecentSwatchListener extends MouseAdapter implements Serializable {
public void mousePressed(MouseEvent e) {
if (isEnabled()) {
Color color = recentSwatchPanel.getColorForLocation(e.getX(), e.getY());
+ recentSwatchPanel.setSelectedColorFromLocation(e.getX(), e.getY());
setSelectedColor(color);
+ recentSwatchPanel.requestFocusInWindow();
}
}
}
@@ -223,7 +256,9 @@
if (isEnabled()) {
Color color = swatchPanel.getColorForLocation(e.getX(), e.getY());
setSelectedColor(color);
+ swatchPanel.setSelectedColorFromLocation(e.getX(), e.getY());
recentSwatchPanel.setMostRecentColor(color);
+ swatchPanel.requestFocusInWindow();
}
}
}
@@ -239,18 +274,81 @@
protected Dimension numSwatches;
protected Dimension gap;
+ private int selRow;
+ private int selCol;
+
public SwatchPanel() {
initValues();
initColors();
setToolTipText(""); // register for events
setOpaque(true);
setBackground(Color.white);
- setRequestFocusEnabled(false);
+ setFocusable(true);
setInheritsPopupMenu(true);
+
+ addFocusListener(new FocusAdapter() {
+ public void focusGained(FocusEvent e) {
+ repaint();
+ }
+
+ public void focusLost(FocusEvent e) {
+ repaint();
+ }
+ });
+
+ addKeyListener(new KeyAdapter() {
+ public void keyPressed(KeyEvent e) {
+ int typed = e.getKeyCode();
+ switch (typed) {
+ case KeyEvent.VK_UP:
+ if (selRow > 0) {
+ selRow--;
+ repaint();
+ }
+ break;
+ case KeyEvent.VK_DOWN:
+ if (selRow < numSwatches.height - 1) {
+ selRow++;
+ repaint();
+ }
+ break;
+ case KeyEvent.VK_LEFT:
+ if (selCol > 0 && SwatchPanel.this.getComponentOrientation().isLeftToRight()) {
+ selCol--;
+ repaint();
+ } else if (selCol < numSwatches.width - 1
+ && !SwatchPanel.this.getComponentOrientation().isLeftToRight()) {
+ selCol++;
+ repaint();
+ }
+ break;
+ case KeyEvent.VK_RIGHT:
+ if (selCol < numSwatches.width - 1
+ && SwatchPanel.this.getComponentOrientation().isLeftToRight()) {
+ selCol++;
+ repaint();
+ } else if (selCol > 0 && !SwatchPanel.this.getComponentOrientation().isLeftToRight()) {
+ selCol--;
+ repaint();
+ }
+ break;
+ case KeyEvent.VK_HOME:
+ selCol = 0;
+ selRow = 0;
+ repaint();
+ break;
+ case KeyEvent.VK_END:
+ selCol = numSwatches.width - 1;
+ selRow = numSwatches.height - 1;
+ repaint();
+ break;
+ }
+ }
+ });
}
- public boolean isFocusTraversable() {
- return false;
+ public Color getSelectedColor() {
+ return getColorForCell(selCol, selRow);
}
protected void initValues() {
@@ -263,11 +361,10 @@
for (int row = 0; row < numSwatches.height; row++) {
int y = row * (swatchSize.height + gap.height);
for (int column = 0; column < numSwatches.width; column++) {
-
- g.setColor( getColorForCell(column, row) );
+ Color c = getColorForCell(column, row);
+ g.setColor(c);
int x;
- if ((!this.getComponentOrientation().isLeftToRight()) &&
- (this instanceof RecentSwatchPanel)) {
+ if (!this.getComponentOrientation().isLeftToRight()) {
x = (numSwatches.width - column - 1) * (swatchSize.width + gap.width);
} else {
x = column * (swatchSize.width + gap.width);
@@ -276,6 +373,20 @@
g.setColor(Color.black);
g.drawLine( x+swatchSize.width-1, y, x+swatchSize.width-1, y+swatchSize.height-1);
g.drawLine( x, y+swatchSize.height-1, x+swatchSize.width-1, y+swatchSize.height-1);
+
+ if (selRow == row && selCol == column && this.isFocusOwner()) {
+ Color c2 = new Color(c.getRed() < 125 ? 255 : 0,
+ c.getGreen() < 125 ? 255 : 0,
+ c.getBlue() < 125 ? 255 : 0);
+ g.setColor(c2);
+
+ g.drawLine(x, y, x + swatchSize.width - 1, y);
+ g.drawLine(x, y, x, y + swatchSize.height - 1);
+ g.drawLine(x + swatchSize.width - 1, y, x + swatchSize.width - 1, y + swatchSize.height - 1);
+ g.drawLine(x, y + swatchSize.height - 1, x + swatchSize.width - 1, y + swatchSize.height - 1);
+ g.drawLine(x, y, x + swatchSize.width - 1, y + swatchSize.height - 1);
+ g.drawLine(x, y + swatchSize.height - 1, x + swatchSize.width - 1, y);
+ }
}
}
}
@@ -296,10 +407,19 @@
return color.getRed()+", "+ color.getGreen() + ", " + color.getBlue();
}
+ public void setSelectedColorFromLocation(int x, int y) {
+ if (!this.getComponentOrientation().isLeftToRight()) {
+ selCol = numSwatches.width - x / (swatchSize.width + gap.width) - 1;
+ } else {
+ selCol = x / (swatchSize.width + gap.width);
+ }
+ selRow = y / (swatchSize.height + gap.height);
+ repaint();
+ }
+
public Color getColorForLocation( int x, int y ) {
int column;
- if ((!this.getComponentOrientation().isLeftToRight()) &&
- (this instanceof RecentSwatchPanel)) {
+ if (!this.getComponentOrientation().isLeftToRight()) {
column = numSwatches.width - x / (swatchSize.width + gap.width) - 1;
} else {
column = x / (swatchSize.width + gap.width);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JColorChooser/Test7194184.java Thu Sep 20 17:39:47 2012 +0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+/*
+ * @test
+ * @bug 7194184
+ * @summary Tests JColorChooser Swatch keyboard accessibility.
+ * @author Sean Chou
+ * @library ../regtesthelpers
+ * @build Util
+ * @run main Test7194184
+ */
+
+import java.awt.Component;
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.KeyEvent;
+
+import javax.swing.JColorChooser;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+import java.util.concurrent.Callable;
+import sun.awt.SunToolkit;
+
+public class Test7194184 implements Runnable {
+ private static JFrame frame;
+ private static JColorChooser colorChooser;
+ private static Color selectedColor;
+
+ public static void main(String[] args) throws Exception {
+ testKeyBoardAccess();
+ }
+
+ private static void testKeyBoardAccess() throws Exception {
+ Robot robot = new Robot();
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+
+ SwingUtilities.invokeLater(new Test7194184());
+ toolkit.realSync();
+
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ selectedColor = colorChooser.getColor();
+
+ Component recentSwatchPanel = Util.findSubComponent(colorChooser, "RecentSwatchPanel");
+ if (recentSwatchPanel == null) {
+ throw new RuntimeException("RecentSwatchPanel not found");
+ }
+ recentSwatchPanel.requestFocusInWindow();
+ }
+ });
+
+ toolkit.realSync();
+
+ // Tab to move the focus to MainSwatch
+ Util.hitKeys(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_TAB);
+
+ // Select the color on right
+ Util.hitKeys(robot, KeyEvent.VK_RIGHT);
+ Util.hitKeys(robot, KeyEvent.VK_RIGHT);
+ Util.hitKeys(robot, KeyEvent.VK_SPACE);
+ toolkit.realSync();
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ if (selectedColor == colorChooser.getColor()) {
+ throw new RuntimeException("JColorChooser misses keyboard accessibility");
+ }
+ }
+ });
+ }
+
+ public void run() {
+ String title = getClass().getName();
+ frame = new JFrame(title);
+ colorChooser = new JColorChooser();
+
+ frame.add(colorChooser);
+ frame.pack();
+ frame.setVisible(true);
+ }
+
+}