1 /* DefaultHSBChooserPanel.java --
2 Copyright (C) 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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., 59 Temple Place, Suite 330, Boston, MA
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
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. */
39 package javax
.swing
.colorchooser
;
41 import java
.awt
.BorderLayout
;
42 import java
.awt
.Color
;
43 import java
.awt
.Container
;
44 import java
.awt
.Dimension
;
45 import java
.awt
.Graphics
;
46 import java
.awt
.GridLayout
;
47 import java
.awt
.Image
;
48 import java
.awt
.Point
;
49 import java
.awt
.event
.MouseAdapter
;
50 import java
.awt
.event
.MouseEvent
;
51 import java
.awt
.event
.MouseMotionListener
;
52 import java
.awt
.image
.MemoryImageSource
;
54 import javax
.swing
.AbstractButton
;
55 import javax
.swing
.ButtonGroup
;
56 import javax
.swing
.Icon
;
57 import javax
.swing
.JColorChooser
;
58 import javax
.swing
.JLabel
;
59 import javax
.swing
.JPanel
;
60 import javax
.swing
.JRadioButton
;
61 import javax
.swing
.JSlider
;
62 import javax
.swing
.JSpinner
;
63 import javax
.swing
.SpinnerNumberModel
;
64 import javax
.swing
.SwingConstants
;
65 import javax
.swing
.event
.ChangeEvent
;
66 import javax
.swing
.event
.ChangeListener
;
69 * This is the Default HSB Panel displayed in the JColorChooser.
71 class DefaultHSBChooserPanel
extends AbstractColorChooserPanel
73 /** The gradient image displayed. */
74 private transient Image gradientImage
;
76 /** The Panel that holds the gradient image. */
77 private transient JPanel gradientPanel
;
79 /** The track gradient image. */
80 private transient Image trackImage
;
82 /** The panel that holds the track. */
83 private transient JPanel trackPanel
;
85 /** The slider for the locked HSB value. */
86 private transient JSlider slider
;
88 /** The RadioButton that controls the Hue. */
89 private transient JRadioButton hRadio
;
91 /** The RadioButton that controls the Saturation. */
92 private transient JRadioButton sRadio
;
94 /** The RadioButton that controls the Brightness. */
95 private transient JRadioButton bRadio
;
97 /** The JSpinner that controls the Hue. */
98 private transient JSpinner hSpinner
;
100 /** The JSpinner that controls the Saturation. */
101 private transient JSpinner sSpinner
;
103 /** The JSpinner that controls the Brightness. */
104 private transient JSpinner bSpinner
;
106 /** The default width of the gradient image. */
107 private static final int imgWidth
= 200;
109 /** The default height of the gradient image. */
110 private static final int imgHeight
= 200;
112 /** The default width of the track gradient. */
113 private static final int trackWidth
= 30;
115 /** The JLabel for Red. */
116 private static final JLabel R
= new JLabel("R");
118 /** The JLabel for Green. */
119 private static final JLabel G
= new JLabel("G");
121 /** The JLabel for Blue. */
122 private static final JLabel B
= new JLabel("B");
124 // FIXME: Should be textfields.
126 /** The JLabel that displays the value of Red. */
127 private transient JLabel rFull
;
129 /** The JLabel that displays the value of Green. */
130 private transient JLabel gFull
;
132 /** The JLabel that displays the value of Blue. */
133 private transient JLabel bFull
;
135 /** The point that is displayed in the gradient image. */
136 private transient Point gradientPoint
= new Point();
139 * This indicates that the change to the slider or point is triggered
142 private transient boolean internalChange
= false;
144 /** This indicates that the change to the spinner is triggered internally. */
145 private transient boolean spinnerTrigger
= false;
147 /** This int identifies which spinner is currently locked. */
148 private transient int locked
= -1;
150 /** This value indicates that the Hue spinner is locked. */
151 static final int HLOCKED
= 0;
153 /** This value indicates that the Saturation spinner is locked. */
154 static final int SLOCKED
= 1;
156 /** This value indicates that the Brightness spinner is locked. */
157 static final int BLOCKED
= 2;
160 * This method indicates that the mouse event is in the process of being
163 private transient boolean handlingMouse
;
166 * This helper class handles mouse events on the gradient image.
168 class MainGradientMouseListener
extends MouseAdapter
169 implements MouseMotionListener
172 * This method is called when the mouse is pressed over the gradient
173 * image. The JColorChooser is then updated with new HSB values.
175 * @param e The MouseEvent.
177 public void mousePressed(MouseEvent e
)
179 gradientPoint
= e
.getPoint();
180 update(e
.getPoint());
184 * This method is called when the mouse is dragged over the gradient
185 * image. The JColorChooser is then updated with the new HSB values.
187 * @param e The MouseEvent.
189 public void mouseDragged(MouseEvent e
)
191 Point p
= e
.getPoint();
192 if (p
.x
< 0 || p
.y
< 0 || p
.y
> imgHeight
|| p
.x
> imgWidth
)
200 * This method is called when the mouse is moved over the gradient image.
202 * @param e The MouseEvent.
204 public void mouseMoved(MouseEvent e
)
210 * This method updates the JColorChooser with the new values.
212 * @param p The Point where the MouseEvent occurred.
214 private void update(Point p
)
216 handlingMouse
= true;
217 if (hSpinner
.isEnabled())
219 else if (sSpinner
.isEnabled())
223 handlingMouse
= false;
227 * This method updates the SB values if Hue is locked.
229 * @param p The point where the MouseEvent occurred.
231 private void updateH(Point p
)
233 float s
= (imgWidth
- p
.x
* 1f
) / imgWidth
;
234 float b
= (imgHeight
- p
.y
* 1f
) / imgHeight
;
236 // Avoid two changes to the model by changing internalChange to true.
237 internalChange
= true;
238 sSpinner
.setValue(new Integer((int) (s
* 100)));
239 internalChange
= false;
240 bSpinner
.setValue(new Integer((int) (b
* 100)));
246 * This method updates the HB values if Saturation is locked.
248 * @param p The point where the MouseEvent occurred.
250 private void updateS(Point p
)
252 float h
= p
.x
* 1f
/ imgWidth
;
253 float b
= (imgHeight
- p
.y
* 1f
) / imgHeight
;
255 internalChange
= true;
256 hSpinner
.setValue(new Integer((int) (h
* 365)));
257 internalChange
= false;
258 bSpinner
.setValue(new Integer((int) (b
* 100)));
264 * This method updates the HS values if Brightness is locked.
266 * @param p The point where the MouseEvent occurred.
268 private void updateB(Point p
)
270 float h
= p
.x
* 1f
/ imgWidth
;
271 float s
= (imgHeight
- p
.y
* 1f
) / imgHeight
;
273 internalChange
= true;
274 hSpinner
.setValue(new Integer((int) (h
* 365)));
275 internalChange
= false;
276 sSpinner
.setValue(new Integer((int) (s
* 100)));
283 * This method listens for slider value changes.
285 class SliderChangeListener
implements ChangeListener
288 * This method is called when the slider value changes. It should change
289 * the color of the JColorChooser.
291 * @param e The ChangeEvent.
293 public void stateChanged(ChangeEvent e
)
298 Integer value
= new Integer(slider
.getValue());
303 hSpinner
.setValue(value
);
306 sSpinner
.setValue(value
);
309 bSpinner
.setValue(value
);
316 * This helper class determines the active JSpinner.
318 class RadioStateListener
implements ChangeListener
321 * This method is called when there is a new JRadioButton that was
322 * selected. As a result, it should activate the associated JSpinner.
324 * @param e The ChangeEvent.
326 public void stateChanged(ChangeEvent e
)
329 if (e
.getSource() == hRadio
)
334 else if (e
.getSource() == sRadio
)
345 change
.setEnabled(((AbstractButton
) e
.getSource()).isSelected());
354 * This class listens to the JSpinners for changes.
356 class ImageScrollListener
implements ChangeListener
359 * This method is called whenever one of the JSpinner values change. The
360 * JColorChooser should be updated with the new HSB values.
362 * @param e The ChangeEvent.
364 public void stateChanged(ChangeEvent e
)
369 float h
= ((Number
) hSpinner
.getValue()).intValue() / 360f
;
370 float s
= ((Number
) sSpinner
.getValue()).intValue() / 100f
;
371 float b
= ((Number
) bSpinner
.getValue()).intValue() / 100f
;
373 spinnerTrigger
= true;
374 getColorSelectionModel().setSelectedColor(new Color(Color
.HSBtoRGB(h
, s
,
376 spinnerTrigger
= false;
378 if (! handlingMouse
&& slider
!= null && ! slider
.getValueIsAdjusting())
388 * Creates a new DefaultHSBChooserPanel object.
390 DefaultHSBChooserPanel()
396 * This method returns the name displayed by the JColorChooser tab that
399 * @return The name displayed in the JColorChooser tab.
401 public String
getDisplayName()
407 * This method updates the various components inside the HSBPanel (the
408 * JSpinners, the JSlider, and the gradient image point) with updated
409 * values when the JColorChooser color value changes.
411 public void updateChooser()
413 Color c
= getColorSelectionModel().getSelectedColor();
415 float[] hsbVals
= Color
.RGBtoHSB(c
.getRed(), c
.getGreen(), c
.getBlue(),
418 internalChange
= true;
420 if (! spinnerTrigger
)
422 hSpinner
.setValue(new Integer((int) (hsbVals
[0] * 360)));
423 sSpinner
.setValue(new Integer((int) (hsbVals
[1] * 100)));
424 bSpinner
.setValue(new Integer((int) (hsbVals
[2] * 100)));
431 slider
.setValue(((Number
) hSpinner
.getValue()).intValue());
434 gradientPoint
.x
= (int) ((1
435 - ((Number
) sSpinner
.getValue()).intValue() / 100f
) * imgWidth
);
436 gradientPoint
.y
= (int) ((1
437 - ((Number
) bSpinner
.getValue()).intValue() / 100f
) * imgHeight
);
442 slider
.setValue(((Number
) sSpinner
.getValue()).intValue());
445 gradientPoint
.x
= (int) (((Number
) hSpinner
.getValue()).intValue() / 360f
* imgWidth
);
446 gradientPoint
.y
= (int) ((1
447 - ((Number
) bSpinner
.getValue()).intValue() / 100f
) * imgHeight
);
452 slider
.setValue(((Number
) bSpinner
.getValue()).intValue());
455 gradientPoint
.x
= (int) (((Number
) hSpinner
.getValue()).intValue() / 360f
* imgWidth
);
456 gradientPoint
.y
= (int) ((1
457 - ((Number
) sSpinner
.getValue()).intValue() / 100f
) * imgHeight
);
461 internalChange
= false;
463 if (! handlingMouse
&& slider
!= null && ! slider
.getValueIsAdjusting())
466 if (! handlingMouse
|| locked
!= HLOCKED
)
472 * This method builds the DefaultHSBChooserPanel.
474 protected void buildChooser()
476 setLayout(new BorderLayout());
478 add(buildRightPanel(), BorderLayout
.EAST
);
480 JPanel container
= new JPanel();
481 container
.setLayout(new BorderLayout());
483 gradientPanel
= new JPanel()
485 public Dimension
getPreferredSize()
487 return new Dimension(imgWidth
, imgHeight
);
490 public void paint(Graphics g
)
492 if (gradientImage
!= null)
493 g
.drawImage(gradientImage
, 0, 0, this);
495 Color saved
= g
.getColor();
496 g
.setColor(Color
.WHITE
);
497 g
.drawOval(gradientPoint
.x
- 3, gradientPoint
.y
- 3, 6, 6);
502 MouseAdapter ml
= new MainGradientMouseListener();
503 gradientPanel
.addMouseListener(ml
);
504 gradientPanel
.addMouseMotionListener((MouseMotionListener
) ml
);
506 trackPanel
= new JPanel()
508 public Dimension
getPreferredSize()
510 return new Dimension(trackWidth
, imgHeight
);
513 public void paint(Graphics g
)
515 if (trackImage
!= null)
516 g
.drawImage(trackImage
, 0, 0, this);
520 slider
= new JSlider();
521 slider
.setPaintTrack(false);
522 slider
.setPaintTicks(false);
524 slider
.setOrientation(SwingConstants
.VERTICAL
);
528 container
.add(gradientPanel
, BorderLayout
.WEST
);
529 container
.add(slider
, BorderLayout
.CENTER
);
530 container
.add(trackPanel
, BorderLayout
.EAST
);
532 add(container
, BorderLayout
.WEST
);
533 slider
.addChangeListener(new SliderChangeListener());
538 * This method uninstalls the DefaultHSBPanel.
540 * @param chooser The JColorChooser to remove this panel from.
542 public void uninstallChooserPanel(JColorChooser chooser
)
545 gradientImage
= null;
546 gradientPanel
= null;
558 super.uninstallChooserPanel(chooser
);
562 * This helper method creates the right side panel (the panel with the
563 * Spinners and TextFields).
565 * @return The right side panel.
567 private Container
buildRightPanel()
569 JPanel container
= new JPanel();
570 container
.setLayout(new GridLayout(6, 2));
572 hRadio
= new JRadioButton("H");
573 sRadio
= new JRadioButton("S");
574 bRadio
= new JRadioButton("B");
576 ButtonGroup group
= new ButtonGroup();
581 hSpinner
= new JSpinner(new SpinnerNumberModel(0, 0, 359, 1));
582 sSpinner
= new JSpinner(new SpinnerNumberModel(0, 0, 100, 1));
583 bSpinner
= new JSpinner(new SpinnerNumberModel(100, 0, 100, 1));
585 hSpinner
.setEnabled(false);
586 sSpinner
.setEnabled(false);
587 bSpinner
.setEnabled(false);
589 ChangeListener cl
= new RadioStateListener();
590 ChangeListener scroll
= new ImageScrollListener();
592 hRadio
.addChangeListener(cl
);
593 sRadio
.addChangeListener(cl
);
594 bRadio
.addChangeListener(cl
);
596 hSpinner
.addChangeListener(scroll
);
597 sSpinner
.addChangeListener(scroll
);
598 bSpinner
.addChangeListener(scroll
);
600 hRadio
.setSelected(true);
602 container
.add(hRadio
);
603 container
.add(hSpinner
);
605 container
.add(sRadio
);
606 container
.add(sSpinner
);
608 container
.add(bRadio
);
609 container
.add(bSpinner
);
611 rFull
= new JLabel("red full");
612 gFull
= new JLabel("green full");
613 bFull
= new JLabel("blue full");
616 container
.add(rFull
);
619 container
.add(gFull
);
622 container
.add(bFull
);
628 * This method returns the small display icon.
630 * @return The small display icon.
632 public Icon
getSmallDisplayIcon()
638 * This method returns the large display icon.
640 * @return The large display icon.
642 public Icon
getLargeDisplayIcon()
648 * This method paints the chooser panel.
650 * @param g The graphics object to paint with.
652 public void paint(Graphics g
)
658 * This method updates the gradient image with a new one taking the Hue
659 * value as the constant.
661 private void updateHLockImage()
664 int[] pix
= new int[imgWidth
* imgHeight
];
665 float hValue
= ((Number
) hSpinner
.getValue()).intValue() / 360f
;
667 for (int j
= 0; j
< imgHeight
; j
++)
668 for (int i
= 0; i
< imgWidth
; i
++)
669 pix
[index
++] = Color
.HSBtoRGB(hValue
, (imgWidth
- i
* 1f
) / imgWidth
,
670 (imgHeight
- j
* 1f
) / imgHeight
)
673 gradientImage
= createImage(new MemoryImageSource(imgWidth
, imgHeight
,
678 * This method updates the gradient image with a new one taking the
679 * Brightness value as the constant.
681 private void updateBLockImage()
683 int[] pix
= new int[imgWidth
* imgHeight
];
684 float bValue
= ((Number
) bSpinner
.getValue()).intValue() / 100f
;
687 for (int j
= 0; j
< imgHeight
; j
++)
688 for (int i
= 0; i
< imgWidth
; i
++)
689 pix
[index
++] = Color
.HSBtoRGB(i
* 1f
/ imgWidth
,
690 (imgHeight
- j
* 1f
) / imgHeight
, bValue
)
693 gradientImage
= createImage(new MemoryImageSource(imgWidth
, imgHeight
,
698 * This method updates the gradient image with a new one taking the
699 * Saturation value as the constant.
701 private void updateSLockImage()
703 int[] pix
= new int[imgWidth
* imgHeight
];
704 float sValue
= ((Number
) sSpinner
.getValue()).intValue() / 100f
;
707 for (int j
= 0; j
< imgHeight
; j
++)
708 for (int i
= 0; i
< imgWidth
; i
++)
709 pix
[index
++] = Color
.HSBtoRGB(i
* 1f
/ imgWidth
, sValue
,
710 (imgHeight
- j
* 1f
) / imgHeight
)
712 gradientImage
= createImage(new MemoryImageSource(imgWidth
, imgHeight
,
717 * This method calls the appropriate method to update the gradient image
718 * depending on which HSB value is constant.
720 private void updateImage()
737 * This method updates the TextFields with the correct RGB values.
739 private void updateTextFields()
741 int c
= getColorSelectionModel().getSelectedColor().getRGB();
743 rFull
.setText("" + (c
>> 16 & 0xff));
744 gFull
.setText("" + (c
>> 8 & 0xff));
745 bFull
.setText("" + (c
& 0xff));
751 * This method updates the slider in response to making a different HSB
752 * property the constant.
754 private void updateSlider()
759 slider
.setMinimum(0);
760 if (locked
== HLOCKED
)
762 slider
.setMaximum(359);
764 slider
.setValue(((Number
) hSpinner
.getValue()).intValue());
765 slider
.setInverted(true);
769 slider
.setMaximum(100);
770 slider
.setInverted(false);
771 if (sRadio
.isSelected())
772 slider
.setValue(((Number
) sSpinner
.getValue()).intValue());
774 slider
.setValue(((Number
) bSpinner
.getValue()).intValue());
780 * This method updates the track gradient image depending on which HSB
781 * property is constant.
783 private void updateTrack()
800 * This method updates the track gradient image if the Hue value is allowed
801 * to change (according to the JRadioButtons).
803 private void updateHTrack()
806 int[] trackPix
= new int[trackWidth
* imgHeight
];
808 for (int j
= 0; j
< imgHeight
; j
++)
809 for (int i
= 0; i
< trackWidth
; i
++)
810 trackPix
[trackIndex
++] = Color
.HSBtoRGB(j
* 1f
/ imgHeight
, 1f
, 1f
)
813 trackImage
= createImage(new MemoryImageSource(trackWidth
, imgHeight
,
814 trackPix
, 0, trackWidth
));
818 * This method updates the track gradient image if the Saturation value is
819 * allowed to change (according to the JRadioButtons).
821 private void updateSTrack()
823 int[] trackPix
= new int[trackWidth
* imgHeight
];
825 float hValue
= ((Number
) hSpinner
.getValue()).intValue() / 360f
;
826 float bValue
= ((Number
) bSpinner
.getValue()).intValue() / 100f
;
829 for (int j
= 0; j
< imgHeight
; j
++)
830 for (int i
= 0; i
< trackWidth
; i
++)
831 trackPix
[trackIndex
++] = Color
.HSBtoRGB(hValue
,
832 (imgHeight
- j
* 1f
) / imgHeight
,
833 bValue
) | (255 << 24);
835 trackImage
= createImage(new MemoryImageSource(trackWidth
, imgHeight
,
836 trackPix
, 0, trackWidth
));
840 * This method updates the track gradient image if the Brightness value is
841 * allowed to change (according to the JRadioButtons).
843 private void updateBTrack()
845 int[] trackPix
= new int[trackWidth
* imgHeight
];
847 float hValue
= ((Number
) hSpinner
.getValue()).intValue() / 360f
;
848 float sValue
= ((Number
) sSpinner
.getValue()).intValue() / 100f
;
851 for (int j
= 0; j
< imgHeight
; j
++)
852 for (int i
= 0; i
< trackWidth
; i
++)
853 trackPix
[trackIndex
++] = Color
.HSBtoRGB(hValue
, sValue
,
854 (imgHeight
- j
* 1f
) / imgHeight
)
857 trackImage
= createImage(new MemoryImageSource(trackWidth
, imgHeight
,
858 trackPix
, 0, trackWidth
));
862 * This method returns the HSB values for the currently selected color.
864 * @return The HSB values for the currently selected color.
866 private float[] getHSBValues()
868 Color c
= getColorFromModel();
869 float[] f
= Color
.RGBtoHSB(c
.getRed(), c
.getGreen(), c
.getBlue(), null);