1 /* JColorChooser.java --
2    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package javax.swing;
40 
41 import java.awt.AWTError;
42 import java.awt.BorderLayout;
43 import java.awt.Color;
44 import java.awt.Component;
45 import java.awt.Dialog;
46 import java.awt.FlowLayout;
47 import java.awt.Frame;
48 import java.awt.event.ActionEvent;
49 import java.awt.event.ActionListener;
50 
51 import javax.accessibility.Accessible;
52 import javax.accessibility.AccessibleContext;
53 import javax.accessibility.AccessibleRole;
54 import javax.swing.colorchooser.AbstractColorChooserPanel;
55 import javax.swing.colorchooser.ColorSelectionModel;
56 import javax.swing.colorchooser.DefaultColorSelectionModel;
57 import javax.swing.plaf.ColorChooserUI;
58 
59 
60 /**
61  * A Swing widget that offers users different ways to
62  * select a color. By default, three different panels are presented to the
63  * user that are capable of changing the selected color. There are three ways
64  * to utilize JColorChooser. The first is to build a JColorChooser and add it
65  * to the content pane. The second is to use the createDialog method to
66  * create a JDialog that holds a JColorChooser. The third is to show a
67  * JColorChooser in a JDialog directly using the showDialog method.
68  *
69  * @author original author unknown
70  */
71 public class JColorChooser extends JComponent implements Accessible
72 {
73   /** DOCUMENT ME! */
74   private static final long serialVersionUID = 9168066781620640889L;
75 
76   /**
77    * Accessibility support for <code>JColorChooser</code>.
78    */
79   protected class AccessibleJColorChooser
80     extends JComponent.AccessibleJComponent
81   {
82     /** DOCUMENT ME! */
83     private static final long serialVersionUID = -2038297864782299082L;
84 
85     /**
86      * Constructor AccessibleJColorChooser
87      */
AccessibleJColorChooser()88     protected AccessibleJColorChooser()
89     {
90       // Nothing to do here.
91     }
92 
93     /**
94      * getAccessibleRole
95      *
96      * @return AccessibleRole
97      */
getAccessibleRole()98     public AccessibleRole getAccessibleRole()
99     {
100       return AccessibleRole.COLOR_CHOOSER;
101     } // getAccessibleRole()
102   } // AccessibleJColorChooser
103 
104   /** The model used with the JColorChooser. */
105   private ColorSelectionModel selectionModel;
106 
107   /** The preview panel associated with the JColorChooser. */
108   private JComponent previewPanel;
109 
110   /**
111    * The set of AbstractColorChooserPanels associated with the JColorChooser.
112    */
113   private AbstractColorChooserPanel[] chooserPanels;
114 
115   /** A Drag and Drop property. */
116   private boolean dragEnabled;
117 
118   /**
119    * The property fired by the JColorChooser when the selectionModel property
120    * changes.
121    */
122   public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
123 
124   /**
125    * The property fired by the JColorChooser when the previewPanel property
126    * changes.
127    */
128   public static final String PREVIEW_PANEL_PROPERTY = "previewPanel";
129 
130   /**
131    * The property fired by the JColorChooser when the chooserPanels property
132    * changes.
133    */
134   public static final String CHOOSER_PANELS_PROPERTY = "chooserPanels";
135 
136   /** accessibleContext */
137   protected AccessibleContext accessibleContext;
138 
139   /**
140    * This method creates a new JColorChooser with the default initial color.
141    */
JColorChooser()142   public JColorChooser()
143   {
144     this(new DefaultColorSelectionModel());
145   } // JColorChooser()
146 
147   /**
148    * This method creates a new JColorChooser with the given initial color.
149    *
150    * @param initial The initial color.
151    */
JColorChooser(Color initial)152   public JColorChooser(Color initial)
153   {
154     this(new DefaultColorSelectionModel(initial));
155   } // JColorChooser()
156 
157   /**
158    * This method creates a new JColorChooser with the given model. The model
159    * will dictate what the initial color for the JColorChooser is.
160    *
161    * @param model The Model to use with the JColorChooser.
162    */
JColorChooser(ColorSelectionModel model)163   public JColorChooser(ColorSelectionModel model)
164   {
165     if (model == null)
166       model = new DefaultColorSelectionModel();
167     selectionModel = model;
168     updateUI();
169   } // JColorChooser()
170 
171   /**
172    * This method sets the current color for the JColorChooser.
173    *
174    * @param color The new color for the JColorChooser.
175    */
setColor(Color color)176   public void setColor(Color color)
177   {
178     if (color != null)
179       selectionModel.setSelectedColor(color);
180   } // setColor()
181 
182   /**
183    * This method sets the current color for the JColorChooser using RGB
184    * values.
185    *
186    * @param r The red value.
187    * @param g The green value.
188    * @param b The blue value.
189    */
setColor(int r, int g, int b)190   public void setColor(int r, int g, int b)
191   {
192     selectionModel.setSelectedColor(new Color(r, g, b));
193   } // setColor()
194 
195   /**
196    * This method sets the current color for the JColorChooser using the
197    * integer value. Bits 0-7 represent the blue value. Bits 8-15 represent
198    * the green value. Bits 16-23 represent the red value.
199    *
200    * @param color The new current color of the JColorChooser.
201    */
setColor(int color)202   public void setColor(int color)
203   {
204     setColor(new Color(color, false));
205   } // setColor()
206 
207   /**
208    * This method shows a JColorChooser inside a JDialog. The JDialog will
209    * block until it is hidden. The JDialog comes with three buttons: OK,
210    * Cancel, and Reset. Pressing OK or Cancel hide the JDialog. Pressing
211    * Reset will reset the JColorChooser to its initial value.
212    *
213    * @param component The Component that parents the JDialog.
214    * @param title The title displayed in the JDialog.
215    * @param initial The initial color.
216    *
217    * @return The selected color.
218    */
showDialog(Component component, String title, Color initial)219   public static Color showDialog(Component component, String title,
220                                  Color initial)
221   {
222     JColorChooser choose = new JColorChooser(initial);
223 
224     JDialog dialog = createDialog(component, title, true, choose, null, null);
225 
226     dialog.getContentPane().add(choose);
227     dialog.pack();
228     dialog.show();
229 
230     return choose.getColor();
231   } // showDialog()
232 
233   /**
234    * This is a helper method to make the given JDialog block until it is
235    * hidden.  This is package-private to avoid an accessor method.
236    *
237    * @param dialog The JDialog to block.
238    */
makeModal(JDialog dialog)239   static void makeModal(JDialog dialog)
240   {
241     try
242       {
243         synchronized (dialog)
244           {
245             while (dialog.isVisible())
246               dialog.wait();
247           }
248       }
249     catch (InterruptedException e)
250       {
251         // TODO: Should this be handled?
252       }
253   }
254 
255   /**
256    * This is a helper method to find the first Frame or Dialog ancestor of the
257    * given Component.
258    *
259    * @param c The Component to find ancestors for.
260    *
261    * @return A Frame or Dialog ancestor. Null if none are found.
262    */
findParent(Component c)263   private static Component findParent(Component c)
264   {
265     Component parent = SwingUtilities.getAncestorOfClass(Frame.class, c);
266     if (parent != null)
267       return parent;
268     parent = SwingUtilities.getAncestorOfClass(Dialog.class, c);
269     return parent;
270   }
271 
272   /**
273    * This method will take the given JColorChooser and place it in a JDialog
274    * with the given modal property. Three buttons are displayed in the
275    * JDialog: OK, Cancel and Reset. If OK or Cancel are pressed, the JDialog
276    * is hidden. If Reset is pressed, then the JColorChooser will take on its
277    * default color value. The given okListener will be registered to the OK
278    * button and the cancelListener will be registered to the Cancel button.
279    * If the modal property is set, then the JDialog will block until it is
280    * hidden.
281    *
282    * @param component The Component that will parent the JDialog.
283    * @param title The title displayed in the JDialog.
284    * @param modal The modal property.
285    * @param chooserPane The JColorChooser to place in the JDialog.
286    * @param okListener The ActionListener to register to the OK button.
287    * @param cancelListener The ActionListener to register to the Cancel
288    *        button.
289    *
290    * @return A JDialog with the JColorChooser inside of it.
291    *
292    * @throws AWTError If the component is not a suitable parent.
293    */
createDialog(Component component, String title, boolean modal, JColorChooser chooserPane, ActionListener okListener, ActionListener cancelListener)294   public static JDialog createDialog(Component component, String title,
295                                      boolean modal, JColorChooser chooserPane,
296                                      ActionListener okListener,
297                                      ActionListener cancelListener)
298   {
299     Component parent = findParent(component);
300     if (parent == null)
301       throw new AWTError("No suitable parent found for Component.");
302     JDialog dialog;
303     if (parent instanceof Frame)
304       dialog = new JDialog((Frame) parent, title, true);
305     else
306       dialog = new JDialog((Dialog) parent, title, true);
307 
308     dialog.getContentPane().setLayout(new BorderLayout());
309 
310     JPanel panel = new JPanel();
311     panel.setLayout(new FlowLayout());
312 
313     ActionListener al = new DefaultOKCancelListener(dialog);
314 
315     JButton ok = new JButton("OK");
316     ok.addActionListener(okListener);
317     ok.addActionListener(al);
318 
319     JButton cancel = new JButton("Cancel");
320     cancel.addActionListener(cancelListener);
321     cancel.addActionListener(al);
322 
323     JButton reset = new JButton("Reset");
324     reset.addActionListener(new DefaultResetListener(chooserPane));
325 
326     dialog.getContentPane().add(chooserPane, BorderLayout.NORTH);
327 
328     panel.add(ok);
329     panel.add(cancel);
330     panel.add(reset);
331 
332     dialog.getContentPane().add(panel, BorderLayout.SOUTH);
333 
334     return dialog;
335   } // createDialog()
336 
337   /**
338    * This method returns the UI Component used for this JColorChooser.
339    *
340    * @return The UI Component for this JColorChooser.
341    */
getUI()342   public ColorChooserUI getUI()
343   {
344     return (ColorChooserUI) ui;
345   } // getUI()
346 
347   /**
348    * This method sets the UI Component used for this JColorChooser.
349    *
350    * @param ui The UI Component to use with this JColorChooser.
351    */
setUI(ColorChooserUI ui)352   public void setUI(ColorChooserUI ui)
353   {
354     super.setUI(ui);
355   } // setUI()
356 
357   /**
358    * This method resets the UI Component property to the Look and Feel
359    * default.
360    */
updateUI()361   public void updateUI()
362   {
363     setUI((ColorChooserUI) UIManager.getUI(this));
364   }
365 
366   /**
367    * This method returns a String identifier for the UI Class to be used with
368    * the JColorChooser.
369    *
370    * @return The String identifier for the UI Class.
371    */
getUIClassID()372   public String getUIClassID()
373   {
374     return "ColorChooserUI";
375   } // getUIClassID()
376 
377   /**
378    * This method returns the current color for the JColorChooser.
379    *
380    * @return The current color for the JColorChooser.
381    */
getColor()382   public Color getColor()
383   {
384     return selectionModel.getSelectedColor(); // TODO
385   } // getColor()
386 
387   /**
388    * This method changes the previewPanel property for the JTabbedPane. The
389    * previewPanel is responsible for indicating the current color of the
390    * JColorChooser.
391    *
392    * @param component The Component that will act as the previewPanel.
393    */
setPreviewPanel(JComponent component)394   public void setPreviewPanel(JComponent component)
395   {
396     if (component != previewPanel)
397       {
398         JComponent old = previewPanel;
399         previewPanel = component;
400         firePropertyChange(PREVIEW_PANEL_PROPERTY, old, previewPanel);
401       }
402   } // setPreviewPanel()
403 
404   /**
405    * This method returns the current previewPanel used with this
406    * JColorChooser.
407    *
408    * @return The current previewPanel.
409    */
getPreviewPanel()410   public JComponent getPreviewPanel()
411   {
412     return previewPanel; // TODO
413   } // getPreviewPanel()
414 
415   /**
416    * This method adds the given AbstractColorChooserPanel to the list of the
417    * JColorChooser's chooserPanels.
418    *
419    * @param panel The AbstractColorChooserPanel to add.
420    */
addChooserPanel(AbstractColorChooserPanel panel)421   public void addChooserPanel(AbstractColorChooserPanel panel)
422   {
423     if (panel == null)
424       return;
425     AbstractColorChooserPanel[] old = chooserPanels;
426     AbstractColorChooserPanel[] newPanels =
427       new AbstractColorChooserPanel[(old == null) ? 1 : old.length + 1];
428     if (old != null)
429       System.arraycopy(old, 0, newPanels, 0, old.length);
430     newPanels[newPanels.length - 1] = panel;
431     chooserPanels = newPanels;
432     panel.installChooserPanel(this);
433     firePropertyChange(CHOOSER_PANELS_PROPERTY, old, newPanels);
434   } // addChooserPanel()
435 
436   /**
437    * This method removes the given AbstractColorChooserPanel from the
438    * JColorChooser's list of chooserPanels.
439    *
440    * @param panel The AbstractColorChooserPanel to remove.
441    *
442    * @return The AbstractColorChooserPanel that was removed.
443    */
removeChooserPanel(AbstractColorChooserPanel panel)444   public AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel panel)
445   {
446     int index = -1;
447     for (int i = 0; i < chooserPanels.length; i++)
448       if (panel == chooserPanels[i])
449         {
450           index = i;
451           break;
452         }
453 
454     if (index == -1)
455       return null;
456 
457     AbstractColorChooserPanel[] old = chooserPanels;
458     if (chooserPanels.length == 1)
459       chooserPanels = null;
460     else
461       {
462         AbstractColorChooserPanel[] newPanels =
463           new AbstractColorChooserPanel[chooserPanels.length - 1];
464         System.arraycopy(chooserPanels, 0, newPanels, 0, index);
465         System.arraycopy(chooserPanels, index, newPanels, index - 1,
466                          chooserPanels.length - index);
467         chooserPanels = newPanels;
468       }
469     panel.uninstallChooserPanel(this);
470     firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels);
471     return panel;
472   }
473 
474   /**
475    * This method sets the chooserPanels property for this JColorChooser.
476    *
477    * @param panels The new set of AbstractColorChooserPanels to use.
478    */
setChooserPanels(AbstractColorChooserPanel[] panels)479   public void setChooserPanels(AbstractColorChooserPanel[] panels)
480   {
481     if (panels != chooserPanels)
482       {
483         if (chooserPanels != null)
484           for (int i = 0; i < chooserPanels.length; i++)
485             if (chooserPanels[i] != null)
486               chooserPanels[i].uninstallChooserPanel(this);
487 
488         AbstractColorChooserPanel[] old = chooserPanels;
489         chooserPanels = panels;
490 
491         if (panels != null)
492           for (int i = 0; i < panels.length; i++)
493             if (panels[i] != null)
494               panels[i].installChooserPanel(this);
495 
496         firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels);
497       }
498   } // setChooserPanels()
499 
500   /**
501    * This method returns the AbstractColorChooserPanels used with this
502    * JColorChooser.
503    *
504    * @return The AbstractColorChooserPanels used with this JColorChooser.
505    */
getChooserPanels()506   public AbstractColorChooserPanel[] getChooserPanels()
507   {
508     return chooserPanels;
509   } // getChooserPanels()
510 
511   /**
512    * This method returns the ColorSelectionModel used with this JColorChooser.
513    *
514    * @return The ColorSelectionModel.
515    */
getSelectionModel()516   public ColorSelectionModel getSelectionModel()
517   {
518     return selectionModel;
519   } // getSelectionModel()
520 
521   /**
522    * This method sets the ColorSelectionModel to be used with this
523    * JColorChooser.
524    *
525    * @param model The ColorSelectionModel to be used with this JColorChooser.
526    *
527    * @throws AWTError If the given model is null.
528    */
setSelectionModel(ColorSelectionModel model)529   public void setSelectionModel(ColorSelectionModel model)
530   {
531     if (model == null)
532       throw new AWTError("ColorSelectionModel is not allowed to be null.");
533     selectionModel = model;
534   } // setSelectionModel()
535 
536   /**
537    * DOCUMENT ME!
538    *
539    * @return DOCUMENT ME!
540    */
getDragEnabled()541   public boolean getDragEnabled()
542   {
543     return dragEnabled;
544   }
545 
546   /**
547    * DOCUMENT ME!
548    *
549    * @param b DOCUMENT ME!
550    */
setDragEnabled(boolean b)551   public void setDragEnabled(boolean b)
552   {
553     dragEnabled = b;
554   }
555 
556   /**
557    * This method returns a String describing the JColorChooser.
558    *
559    * @return A String describing the JColorChooser.
560    */
paramString()561   protected String paramString()
562   {
563     return "JColorChooser";
564   } // paramString()
565 
566   /**
567    * getAccessibleContext
568    *
569    * @return AccessibleContext
570    */
getAccessibleContext()571   public AccessibleContext getAccessibleContext()
572   {
573     if (accessibleContext == null)
574       accessibleContext = new AccessibleJColorChooser();
575 
576     return accessibleContext;
577   }
578 
579   /**
580    * A helper class that hides a JDialog when the action is performed.
581    */
582   static class DefaultOKCancelListener implements ActionListener
583   {
584     /** The JDialog to hide. */
585     private JDialog dialog;
586 
587     /**
588      * Creates a new DefaultOKCancelListener with the given JDialog to hide.
589      *
590      * @param dialog The JDialog to hide.
591      */
DefaultOKCancelListener(JDialog dialog)592     public DefaultOKCancelListener(JDialog dialog)
593     {
594       super();
595       this.dialog = dialog;
596     }
597 
598     /**
599      * This method hides the JDialog when called.
600      *
601      * @param e The ActionEvent.
602      */
actionPerformed(ActionEvent e)603     public void actionPerformed(ActionEvent e)
604     {
605       dialog.hide();
606     }
607   }
608 
609   /**
610    * This method resets the JColorChooser color to the initial color when the
611    * action is performed.
612    */
613   static class DefaultResetListener implements ActionListener
614   {
615     /** The JColorChooser to reset. */
616     private JColorChooser chooser;
617 
618     /** The initial color. */
619     private Color init;
620 
621     /**
622      * Creates a new DefaultResetListener with the given JColorChooser.
623      *
624      * @param chooser The JColorChooser to reset.
625      */
DefaultResetListener(JColorChooser chooser)626     public DefaultResetListener(JColorChooser chooser)
627     {
628       super();
629       this.chooser = chooser;
630       init = chooser.getColor();
631     }
632 
633     /**
634      * This method resets the JColorChooser to its initial color.
635      *
636      * @param e The ActionEvent.
637      */
actionPerformed(ActionEvent e)638     public void actionPerformed(ActionEvent e)
639     {
640       chooser.setColor(init);
641     }
642   }
643 
644 }
645