/Users/joshy/projects/current/swingx/src/java/org/jdesktop/swingx/JXColorSelectionButton.java
  1 /*
  2  * $Id: JXColorSelectionButton.html 1460 2006-10-09 20:51:39Z joshy $
  3  *
  4  * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
  5  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6  *
  7  * This library is free software; you can redistribute it and/or
  8  * modify it under the terms of the GNU Lesser General Public
  9  * License as published by the Free Software Foundation; either
 10  * version 2.1 of the License, or (at your option) any later version.
 11  *
 12  * This library is distributed in the hope that it will be useful,
 13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 15  * Lesser General Public License for more details.
 16  *
 17  * You should have received a copy of the GNU Lesser General Public
 18  * License along with this library; if not, write to the Free Software
 19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 20  */
 21 
 22 package org.jdesktop.swingx;
 23 
 24 import java.awt.Color;
 25 import java.awt.Graphics;
 26 import java.awt.Insets;
 27 import java.awt.event.ActionEvent;
 28 import java.awt.event.ActionListener;
 29 import java.awt.image.BufferedImage;
 30 import javax.imageio.ImageIO;
 31 import javax.swing.JButton;
 32 import javax.swing.JColorChooser;
 33 import javax.swing.JComponent;
 34 import javax.swing.JDialog;
 35 import javax.swing.JFrame;
 36 import javax.swing.JLabel;
 37 import javax.swing.JPanel;
 38 import javax.swing.event.ChangeEvent;
 39 import javax.swing.event.ChangeListener;
 40 import org.jdesktop.swingx.color.*;
 41 
 42 /**
 43  * A button which allows the user to select a single color. The button has a platform
 44  * specific look. Ex: on Mac OS X it will mimic an NSColorWell. When the user
 45  * clicks the button it will open a color chooser set to the current background
 46  * color of the button. The new selected color will be stored in the background
 47  * property and can be retrieved using the getBackground() method. As the user is
 48  * choosing colors within the color chooser the background property will be updated.
 49  * By listening to this property developers can make other parts of their programs
 50  * update.
 51  *
 52  * @author joshua@marinacci.org
 53  */
 54 public class JXColorSelectionButton extends JButton {
 55     private BufferedImage colorwell;
 56     private JDialog dialog = null;
 57     private JColorChooser chooser = null;
 58     
 59     /**
 60      * Creates a new instance of JXColorSelectionButton
 61      */
 62     public JXColorSelectionButton() {
 63         this(Color.red);
 64     }
 65     
 66     /**
 67      * Creates a new instance of JXColorSelectionButton set to the specified color.
 68      * @param col The default color
 69      */
 70     public JXColorSelectionButton(Color col) {
 71         setBackground(col);
 72         this.addActionListener(new ActionHandler());
 73         this.setContentAreaFilled(false);
 74         this.setOpaque(false);
 75         
 76         try {
 77             colorwell = ImageIO.read(this.getClass().getResourceAsStream("/org/jdesktop/swingx/color/colorwell.png"));
 78         } catch (Exception ex) {
 79             ex.printStackTrace();
 80         }
 81     }
 82     
 83     
 84     /**
 85      * A listener class to update the button's background when the selected
 86      * color changes.
 87      */
 88     private class ColorChangeListener implements ChangeListener {
 89         public JXColorSelectionButton button;
 90         public ColorChangeListener(JXColorSelectionButton button) {
 91             this.button = button;
 92         }
 93         public void stateChanged(ChangeEvent changeEvent) {
 94             button.setBackground(button.getChooser().getColor());
 95         }
 96     }
 97     
 98     /**
 99      * {@inheritDoc}
100      */
101     protected void paintComponent(Graphics g) {
102         // draw the colorwell image (should only be on OSX)
103         Insets ins = new Insets(5,5,5,5);
104         if(colorwell != null) {
105             ColorUtil.tileStretchPaint(g, this, colorwell, ins);
106         }
107         
108         // fill in the color area
109         g.setColor(ColorUtil.removeAlpha(getBackground()));
110         g.fillRect(ins.left, ins.top,
111                 getWidth()  - ins.left - ins.right,
112                 getHeight() - ins.top - ins.bottom);
113         // draw the borders
114         g.setColor(ColorUtil.setBrightness(getBackground(),0.85f));
115         g.drawRect(ins.left, ins.top,
116                 getWidth() - ins.left - ins.right - 1,
117                 getHeight() - ins.top - ins.bottom - 1);
118         g.drawRect(ins.left + 1, ins.top + 1,
119                 getWidth() - ins.left - ins.right - 3,
120                 getHeight() - ins.top - ins.bottom - 3);
121     }
122     
123     
124     /**
125      * Sample usage of JXColorSelectionButton
126      * @param args not used
127      */
128     public static void main(String[] args) {
129         JFrame frame = new JFrame("Color Button Test");
130         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
131         JPanel panel = new JPanel();
132         panel.add(new JXColorSelectionButton());
133         panel.add(new JLabel("ColorSelectionButton test"));
134         
135         frame.add(panel);
136         frame.pack();
137         frame.setVisible(true);
138     }
139     
140     /**
141      * Conditionally create and show the color chooser dialog.
142      */
143     private void showDialog() {
144         if (dialog == null) {
145             dialog = JColorChooser.createDialog(JXColorSelectionButton.this,
146                     "Choose a color", true, getChooser(),
147                     new ActionListener() {
148                         public void actionPerformed(ActionEvent actionEvent) {
149                         }
150                     },
151                     new ActionListener() {
152                         public void actionPerformed(ActionEvent actionEvent) {
153                     }
154                 });
155             dialog.getContentPane().add(getChooser());
156             getChooser().getSelectionModel().addChangeListener(
157                     new ColorChangeListener(JXColorSelectionButton.this));
158         }
159         dialog.setVisible(true);
160         Color color = getChooser().getColor();
161         if (color != null) {
162             setBackground(color);
163         }
164     }
165     
166     /**
167      * Get the JColorChooser that is used by this JXColorSelectionButton. This
168      * chooser instance is shared between all invocations of the chooser, but is unique to
169      * this instance of JXColorSelectionButton.
170      * @return the JColorChooser used by this JXColorSelectionButton
171      */
172     public JColorChooser getChooser() {
173         if(chooser == null) {
174             chooser = new JColorChooser();
175             // add the eyedropper color chooser panel
176             chooser.addChooserPanel(new EyeDropperColorChooserPanel());
177         }
178         return chooser;
179     }
180     
181     /**
182      * Set the JColorChooser that is used by this JXColorSelectionButton.
183      * chooser instance is shared between all invocations of the chooser,
184      * but is unique to
185      * this instance of JXColorSelectionButton.
186      * @param chooser The new JColorChooser to use.
187      */
188     public void setChooser(JColorChooser chooser) {
189         JColorChooser oldChooser = getChooser();
190         this.chooser = chooser;
191         firePropertyChange("chooser",oldChooser,chooser);
192     }
193     
194     /**
195      * A private class to conditionally create and show the color chooser
196      * dialog.
197      */
198     private class ActionHandler implements ActionListener {
199         
200         public void actionPerformed(ActionEvent actionEvent) {
201             showDialog();
202         }
203     }
204     
205     
206 }
207