8051548: JColorChooser should have a way to disable transparency controls

Reviewed-by: prr, serb
This commit is contained in:
Alexander Scherbatiy 2015-08-26 17:21:01 +04:00
parent 66ae036b1f
commit c177fba43e
6 changed files with 332 additions and 4 deletions

View File

@ -133,13 +133,42 @@ public class JColorChooser extends JComponent implements Accessible {
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
@SuppressWarnings("deprecation")
public static Color showDialog(Component component,
String title, Color initialColor) throws HeadlessException {
String title, Color initialColor) throws HeadlessException {
return showDialog(component, title, initialColor, true);
}
/**
* Shows a modal color-chooser dialog and blocks until the
* dialog is hidden. If the user presses the "OK" button, then
* this method hides/disposes the dialog and returns the selected color.
* If the user presses the "Cancel" button or closes the dialog without
* pressing "OK", then this method hides/disposes the dialog and returns
* <code>null</code>.
*
* @param component the parent <code>Component</code> for the dialog
* @param title the String containing the dialog's title
* @param initialColor the initial Color set when the color-chooser is shown
* @param colorTransparencySelectionEnabled true if the transparency of
* a color can be selected
* @return the selected color or <code>null</code> if the user opted out
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
*/
@SuppressWarnings("deprecation")
public static Color showDialog(Component component, String title,
Color initialColor, boolean colorTransparencySelectionEnabled)
throws HeadlessException {
final JColorChooser pane = new JColorChooser(initialColor != null?
initialColor : Color.white);
for (AbstractColorChooserPanel ccPanel : pane.getChooserPanels()) {
ccPanel.setColorTransparencySelectionEnabled(
colorTransparencySelectionEnabled);
}
ColorTracker ok = new ColorTracker(pane);
JDialog dialog = createDialog(component, title, true, pane, ok, null);
@ -150,7 +179,6 @@ public class JColorChooser extends JComponent implements Accessible {
return ok.getColor();
}
/**
* Creates and returns a new dialog containing the specified
* <code>ColorChooser</code> pane along with "OK", "Cancel", and "Reset"

View File

@ -50,6 +50,14 @@ import javax.swing.*;
@SuppressWarnings("serial") // Same-version serialization only
public abstract class AbstractColorChooserPanel extends JPanel {
/**
* Identifies that the transparency of the color (alpha value) can be
* selected
*/
public static final String TRANSPARENCY_ENABLED_PROPERTY
= "TransparencyEnabled";
private final PropertyChangeListener enabledListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
Object value = event.getNewValue();
@ -201,6 +209,40 @@ public abstract class AbstractColorChooserPanel extends JPanel {
}
}
/**
* Sets whether color chooser panel allows to select the transparency
* (alpha value) of a color.
* This method fires a property-changed event, using the string value of
* {@code TRANSPARENCY_ENABLED_PROPERTY} as the name
* of the property.
*
* <p>The value is a hint and may not be applicable to all types of chooser
* panel.
*
* <p>The default value is {@code true}.
*
* @param b true if the transparency of a color can be selected
*
* @beaninfo
* bound: true
* description: Sets the transparency of a color selection on or off.
*
* @see #isColorTransparencySelectionEnabled()
*/
public void setColorTransparencySelectionEnabled(boolean b){
}
/**
* Gets whether color chooser panel allows to select the transparency
* (alpha value) of a color.
*
* @return true if the transparency of a color can be selected
* @see #setColorTransparencySelectionEnabled(boolean)
*/
public boolean isColorTransparencySelectionEnabled(){
return true;
}
/**
* Draws the panel.
* @param g the <code>Graphics</code> object

View File

@ -176,6 +176,21 @@ final class ColorChooserPanel extends AbstractColorChooserPanel implements Prope
return null;
}
@Override
public void setColorTransparencySelectionEnabled(boolean b){
boolean oldValue = isColorTransparencySelectionEnabled();
if (b != oldValue) {
panel.setColorTransparencySelectionEnabled(b);
firePropertyChange(TRANSPARENCY_ENABLED_PROPERTY,
oldValue, b);
}
}
@Override
public boolean isColorTransparencySelectionEnabled(){
return panel.isColorTransparencySelectionEnabled();
}
public void propertyChange(PropertyChangeEvent event) {
ColorSelectionModel model = getColorSelectionModel();
if (model != null) {

View File

@ -145,7 +145,7 @@ final class ColorPanel extends JPanel implements ActionListener {
}
void colorChanged() {
this.color = new Color(getColor(0), true);
this.color = new Color(getColor(0), isColorTransparencySelectionEnabled());
Object parent = getParent();
if (parent instanceof ColorChooserPanel) {
ColorChooserPanel chooser = (ColorChooserPanel) parent;
@ -208,6 +208,17 @@ final class ColorPanel extends JPanel implements ActionListener {
return this.model.getColor(this.values);
}
void setColorTransparencySelectionEnabled(boolean b) {
if (spinners[model.getCount() - 1].isVisible() != b) {
spinners[model.getCount() - 1].setVisible(b);
colorChanged();
}
}
boolean isColorTransparencySelectionEnabled() {
return spinners[model.getCount() - 1].isVisible();
}
private void setValue(int index) {
this.values[index] = this.spinners[index].getValue();
}

View File

@ -95,6 +95,10 @@ final class SlidingSpinner implements ChangeListener {
this.spinner.setVisible(visible);
}
boolean isVisible() {
return this.slider.isVisible();
}
public void stateChanged(ChangeEvent event) {
if (!this.internal) {
if (this.spinner == event.getSource()) {

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2014, 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.
*/
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Frame;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.util.function.Predicate;
import javax.swing.JColorChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import javax.swing.colorchooser.AbstractColorChooserPanel;
/*
* @test
* @bug 8051548
* @summary JColorChooser should have a way to disable transparency controls
* @author Alexandr Scherbatiy
* @run main Test8051548
*/
public class Test8051548 {
private static final String[][] TABS = {
{"HSV", "0"},
{"HSL", "0"},
{"RGB", "255"},
{"CMYK", "255"}
};
private static JColorChooser colorChooser;
private static boolean propertyChangeListenerInvoked;
private static volatile Color color;
public static void main(String[] args) throws Exception {
testColorPanels();
testShowDialog(true);
testShowDialog(false);
}
private static void testColorPanels() throws Exception {
SwingUtilities.invokeAndWait(() -> createAndShowGUI());
Robot robot = new Robot();
robot.setAutoDelay(50);
robot.waitForIdle();
for (String[] tabs : TABS) {
final String tab = tabs[0];
final String initialValue = tabs[1];
SwingUtilities.invokeAndWait(() -> {
colorChooser.setColor(new Color(50, 100, 85));
JTabbedPane tabbedPane =
(JTabbedPane) findComponent(colorChooser, "JTabbedPane");
int index = tabbedPane.indexOfTab(tab);
tabbedPane.setSelectedIndex(index);
AbstractColorChooserPanel colorChooserPanel
= (AbstractColorChooserPanel) findComponent(
tabbedPane.getComponent(index), "ColorChooserPanel");
propertyChangeListenerInvoked = false;
colorChooserPanel.addPropertyChangeListener((e) -> {
if (AbstractColorChooserPanel.TRANSPARENCY_ENABLED_PROPERTY.
equals(e.getPropertyName())) {
propertyChangeListenerInvoked = true;
if(!(Boolean)e.getOldValue()){
throw new RuntimeException("Old color transparency"
+ " selection property should be true!");
}
if((Boolean)e.getNewValue()){
throw new RuntimeException("New color transparency"
+ " selection property should be false!");
}
}
});
if (!colorChooserPanel.isColorTransparencySelectionEnabled()) {
throw new RuntimeException("Color transparency selection"
+ " should be enabled by default");
}
JFormattedTextField transparencyTextField = (JFormattedTextField)
findTextField(colorChooserPanel, initialValue);
if (!transparencyTextField.isEnabled()) {
throw new RuntimeException("Transparency controls are"
+ " disabled by default!");
}
transparencyTextField.setValue(50);
if(!colorHasAlpha()){
throw new RuntimeException("Transparency selection should"
+ " be enabled!");
}
colorChooserPanel.setColorTransparencySelectionEnabled(false);
if (colorChooserPanel.isColorTransparencySelectionEnabled()) {
throw new RuntimeException("Color transparency selection"
+ " should be disabled!");
}
if(!propertyChangeListenerInvoked){
throw new RuntimeException("Property change listener is not"
+ " invoked!");
}
if(colorHasAlpha()){
throw new RuntimeException("Transparency selection should"
+ " be disabled!");
}
});
robot.waitForIdle();
}
}
static void testShowDialog(boolean colorTransparencySelectionEnabled) throws Exception {
int alphaValue = 123;
Robot robot = new Robot();
robot.setAutoDelay(50);
SwingUtilities.invokeLater(() -> {
color = JColorChooser.showDialog(null, "Change Color",
new Color(10, 20, 30, alphaValue),
colorTransparencySelectionEnabled);
});
SwingUtilities.invokeAndWait(() -> {
// wait for dialog is shown
});
robot.waitForIdle();
robot.keyPress(KeyEvent.VK_ENTER);
robot.keyRelease(KeyEvent.VK_ENTER);
robot.waitForIdle();
if (colorTransparencySelectionEnabled) {
if (color.getAlpha() != alphaValue) {
throw new RuntimeException("Color alpha has not bee reseted!");
}
} else {
if (color.getAlpha() != 255) {
throw new RuntimeException("Color alpha has not bee reseted!");
}
}
}
private static boolean colorHasAlpha(){
return colorChooser.getColor().getAlpha() != 255;
}
private static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setSize(700, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
colorChooser = new JColorChooser();
frame.getContentPane().add(colorChooser);
frame.setVisible(true);
}
private static Component findComponent(Component component, String name) {
return findComponent(component,
(comp) -> comp.getClass().getName().contains(name));
}
private static Component findTextField(Component component, String value) {
return findComponent(component, (comp) -> {
if (comp instanceof JFormattedTextField) {
JFormattedTextField textField = (JFormattedTextField) comp;
return value.equals(textField.getText());
}
return false;
});
}
private static Component findComponent(Component component,
Predicate<Component> predicate) {
if (predicate.test(component)) {
return component;
}
if (component instanceof Container) {
Container container = (Container) component;
for (int i = 0; i < container.getComponentCount(); i++) {
Component child = findComponent(container.getComponent(i),
predicate);
if (child != null) {
return child;
}
}
}
return null;
}
}