/*
* $Id: JXColorSelectionButton.java 4082 2011-11-15 18:39:43Z kschaefe $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.swingx;
import static java.awt.RenderingHints.KEY_ANTIALIASING;
import static java.awt.RenderingHints.VALUE_ANTIALIAS_ON;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jdesktop.swingx.color.EyeDropperColorChooserPanel;
import org.jdesktop.swingx.plaf.UIManagerExt;
import org.jdesktop.swingx.util.GraphicsUtilities;
import org.jdesktop.swingx.util.OS;
import org.jdesktop.swingx.util.PaintUtils;
/**
* A button which allows the user to select a single color. The button has a platform
* specific look. Ex: on Mac OS X it will mimic an NSColorWell. When the user
* clicks the button it will open a color chooser set to the current background
* color of the button. The new selected color will be stored in the background
* property and can be retrieved using the getBackground() method. As the user is
* choosing colors within the color chooser the background property will be updated.
* By listening to this property developers can make other parts of their programs
* update.
*
* @author joshua@marinacci.org
*/
public class JXColorSelectionButton extends JButton {
private BufferedImage colorwell;
private JDialog dialog = null;
private JColorChooser chooser = null;
private Color initialColor = null;
/**
* Creates a new instance of JXColorSelectionButton
*/
public JXColorSelectionButton() {
this(Color.red);
}
/**
* Creates a new instance of JXColorSelectionButton set to the specified color.
* @param col The default color
*/
public JXColorSelectionButton(Color col) {
setBackground(col);
this.addActionListener(new ActionHandler());
this.setContentAreaFilled(false);
this.setOpaque(false);
try {
colorwell = ImageIO.read(JXColorSelectionButton.class.getResourceAsStream("color/colorwell.png"));
} catch (Exception ex) {
ex.printStackTrace();
}
this.addPropertyChangeListener("background",new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent propertyChangeEvent) {
getChooser().setColor(getBackground());
}
});
}
/**
* A listener class to update the button's background when the selected
* color changes.
*/
private class ColorChangeListener implements ChangeListener {
public JXColorSelectionButton button;
public ColorChangeListener(JXColorSelectionButton button) {
this.button = button;
}
public void stateChanged(ChangeEvent changeEvent) {
button.setBackground(button.getChooser().getColor());
}
}
/**
* {@inheritDoc}
*/
@Override
protected void paintComponent(Graphics g) {
// want disabledForeground when disabled, current colour otherwise
final Color FILL_COLOR = isEnabled() ? PaintUtils.removeAlpha(getBackground())
: UIManagerExt.getSafeColor("Button.disabledForeground", Color.LIGHT_GRAY);
// draw the colorwell image (should only be on OSX)
if(OS.isMacOSX() && colorwell != null) {
Insets ins = new Insets(5,5,5,5);
GraphicsUtilities.tileStretchPaint(g, this, colorwell, ins);
// fill in the color area
g.setColor(FILL_COLOR);
g.fillRect(ins.left, ins.top,
getWidth() - ins.left - ins.right,
getHeight() - ins.top - ins.bottom);
// draw the borders
g.setColor(PaintUtils.setBrightness(FILL_COLOR,0.85f));
g.drawRect(ins.left, ins.top,
getWidth() - ins.left - ins.right - 1,
getHeight() - ins.top - ins.bottom - 1);
g.drawRect(ins.left + 1, ins.top + 1,
getWidth() - ins.left - ins.right - 3,
getHeight() - ins.top - ins.bottom - 3);
}else{
Graphics2D g2 = (Graphics2D) g.create();
try {
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
g2.setColor(Color.LIGHT_GRAY);
final int DIAM = Math.min(getWidth(), getHeight());
final int inset = 3;
g2.fill(new Ellipse2D.Float(inset, inset, DIAM-2*inset, DIAM-2*inset));
g2.setColor(FILL_COLOR);
final int border = 1;
g2.fill(new Ellipse2D.Float(inset+border, inset+border, DIAM-2*inset-2*border, DIAM-2*inset-2*border));
} finally {
g2.dispose();
}
}
}
// /**
// * Sample usage of JXColorSelectionButton
// * @param args not used
// */
// public static void main(String[] args) {
// javax.swing.JFrame frame = new javax.swing.JFrame("Color Button Test");
// frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
// javax.swing.JPanel panel = new javax.swing.JPanel();
// javax.swing.JComponent btn = new JXColorSelectionButton();
// btn.setEnabled(true);
// panel.add(btn);
// panel.add(new javax.swing.JLabel("ColorSelectionButton test"));
//
// frame.add(panel);
// frame.pack();
// frame.setVisible(true);
// }
/**
* Conditionally create and show the color chooser dialog.
*/
private void showDialog() {
if (dialog == null) {
dialog = JColorChooser.createDialog(JXColorSelectionButton.this,
"Choose a color", true, getChooser(),
new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
Color color = getChooser().getColor();
if (color != null) {
setBackground(color);
}
}
},
new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
setBackground(initialColor);
}
});
dialog.getContentPane().add(getChooser());
getChooser().getSelectionModel().addChangeListener(
new ColorChangeListener(JXColorSelectionButton.this));
}
initialColor = getBackground();
dialog.setVisible(true);
}
/**
* Get the JColorChooser that is used by this JXColorSelectionButton. This
* chooser instance is shared between all invocations of the chooser, but is unique to
* this instance of JXColorSelectionButton.
* @return the JColorChooser used by this JXColorSelectionButton
*/
public JColorChooser getChooser() {
if(chooser == null) {
chooser = new JColorChooser();
// add the eyedropper color chooser panel
chooser.addChooserPanel(new EyeDropperColorChooserPanel());
}
return chooser;
}
/**
* Set the JColorChooser that is used by this JXColorSelectionButton.
* chooser instance is shared between all invocations of the chooser,
* but is unique to
* this instance of JXColorSelectionButton.
* @param chooser The new JColorChooser to use.
*/
public void setChooser(JColorChooser chooser) {
JColorChooser oldChooser = getChooser();
this.chooser = chooser;
firePropertyChange("chooser",oldChooser,chooser);
}
/**
* {@inheritDoc}
*/
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || colorwell == null) {
return super.getPreferredSize();
}
return new Dimension(colorwell.getWidth(), colorwell.getHeight());
}
/**
* A private class to conditionally create and show the color chooser
* dialog.
*/
private class ActionHandler implements ActionListener {
public void actionPerformed(ActionEvent actionEvent) {
showDialog();
}
}
}