Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / colorchooser / DefaultHSBChooserPanel.java
blobc2494039b8dfcca1ecab2486bfac9aa43b9f81cf
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)
9 any later version.
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
19 02111-1307 USA.
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.
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;
68 /**
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
140 * internally.
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
161 * handled.
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)
193 return;
195 gradientPoint = p;
196 update(p);
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)
206 // Do nothing.
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())
218 updateH(p);
219 else if (sSpinner.isEnabled())
220 updateS(p);
221 else
222 updateB(p);
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)));
242 revalidate();
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)));
260 revalidate();
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)));
278 revalidate();
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)
295 if (internalChange)
296 return;
298 Integer value = new Integer(slider.getValue());
300 switch (locked)
302 case HLOCKED:
303 hSpinner.setValue(value);
304 break;
305 case SLOCKED:
306 sSpinner.setValue(value);
307 break;
308 case BLOCKED:
309 bSpinner.setValue(value);
310 break;
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)
328 JSpinner change;
329 if (e.getSource() == hRadio)
331 locked = HLOCKED;
332 change = hSpinner;
334 else if (e.getSource() == sRadio)
336 locked = SLOCKED;
337 change = sSpinner;
339 else
341 locked = BLOCKED;
342 change = bSpinner;
345 change.setEnabled(((AbstractButton) e.getSource()).isSelected());
346 updateSlider();
347 updateTrack();
348 updateImage();
349 repaint();
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)
366 if (internalChange)
367 return;
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,
375 b)));
376 spinnerTrigger = false;
378 if (! handlingMouse && slider != null && ! slider.getValueIsAdjusting())
380 updateImage();
381 updateTrack();
383 repaint();
388 * Creates a new DefaultHSBChooserPanel object.
390 DefaultHSBChooserPanel()
392 super();
396 * This method returns the name displayed by the JColorChooser tab that
397 * holds this panel.
399 * @return The name displayed in the JColorChooser tab.
401 public String getDisplayName()
403 return "HSB";
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(),
416 null);
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)));
427 switch (locked)
429 case HLOCKED:
430 if (slider != null)
431 slider.setValue(((Number) hSpinner.getValue()).intValue());
432 if (! handlingMouse)
434 gradientPoint.x = (int) ((1
435 - ((Number) sSpinner.getValue()).intValue() / 100f) * imgWidth);
436 gradientPoint.y = (int) ((1
437 - ((Number) bSpinner.getValue()).intValue() / 100f) * imgHeight);
439 break;
440 case SLOCKED:
441 if (slider != null)
442 slider.setValue(((Number) sSpinner.getValue()).intValue());
443 if (! handlingMouse)
445 gradientPoint.x = (int) (((Number) hSpinner.getValue()).intValue() / 360f * imgWidth);
446 gradientPoint.y = (int) ((1
447 - ((Number) bSpinner.getValue()).intValue() / 100f) * imgHeight);
449 break;
450 case BLOCKED:
451 if (slider != null)
452 slider.setValue(((Number) bSpinner.getValue()).intValue());
453 if (! handlingMouse)
455 gradientPoint.x = (int) (((Number) hSpinner.getValue()).intValue() / 360f * imgWidth);
456 gradientPoint.y = (int) ((1
457 - ((Number) sSpinner.getValue()).intValue() / 100f) * imgHeight);
459 break;
461 internalChange = false;
463 if (! handlingMouse && slider != null && ! slider.getValueIsAdjusting())
464 updateImage();
466 if (! handlingMouse || locked != HLOCKED)
467 updateTrack();
468 updateTextFields();
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);
498 g.setColor(saved);
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);
526 updateSlider();
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());
534 repaint();
538 * This method uninstalls the DefaultHSBPanel.
540 * @param chooser The JColorChooser to remove this panel from.
542 public void uninstallChooserPanel(JColorChooser chooser)
544 trackImage = null;
545 gradientImage = null;
546 gradientPanel = null;
547 slider = null;
549 hSpinner = null;
550 sSpinner = null;
551 bSpinner = null;
553 hRadio = null;
554 sRadio = null;
555 bRadio = null;
557 removeAll();
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();
577 group.add(hRadio);
578 group.add(sRadio);
579 group.add(bRadio);
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");
615 container.add(R);
616 container.add(rFull);
618 container.add(G);
619 container.add(gFull);
621 container.add(B);
622 container.add(bFull);
624 return container;
628 * This method returns the small display icon.
630 * @return The small display icon.
632 public Icon getSmallDisplayIcon()
634 return null;
638 * This method returns the large display icon.
640 * @return The large display icon.
642 public Icon getLargeDisplayIcon()
644 return null;
648 * This method paints the chooser panel.
650 * @param g The graphics object to paint with.
652 public void paint(Graphics g)
654 super.paint(g);
658 * This method updates the gradient image with a new one taking the Hue
659 * value as the constant.
661 private void updateHLockImage()
663 int index = 0;
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)
671 | (255 << 24);
673 gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight,
674 pix, 0, imgWidth));
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;
686 int index = 0;
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)
691 | (255 << 24);
693 gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight,
694 pix, 0, imgWidth));
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;
706 int index = 0;
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)
711 | (255 << 24);
712 gradientImage = createImage(new MemoryImageSource(imgWidth, imgHeight,
713 pix, 0, imgWidth));
717 * This method calls the appropriate method to update the gradient image
718 * depending on which HSB value is constant.
720 private void updateImage()
722 switch (locked)
724 case HLOCKED:
725 updateHLockImage();
726 break;
727 case SLOCKED:
728 updateSLockImage();
729 break;
730 case BLOCKED:
731 updateBLockImage();
732 break;
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));
747 repaint();
751 * This method updates the slider in response to making a different HSB
752 * property the constant.
754 private void updateSlider()
756 if (slider == null)
757 return;
759 slider.setMinimum(0);
760 if (locked == HLOCKED)
762 slider.setMaximum(359);
764 slider.setValue(((Number) hSpinner.getValue()).intValue());
765 slider.setInverted(true);
767 else
769 slider.setMaximum(100);
770 slider.setInverted(false);
771 if (sRadio.isSelected())
772 slider.setValue(((Number) sSpinner.getValue()).intValue());
773 else
774 slider.setValue(((Number) bSpinner.getValue()).intValue());
776 repaint();
780 * This method updates the track gradient image depending on which HSB
781 * property is constant.
783 private void updateTrack()
785 switch (locked)
787 case HLOCKED:
788 updateHTrack();
789 break;
790 case SLOCKED:
791 updateSTrack();
792 break;
793 case BLOCKED:
794 updateBTrack();
795 break;
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()
805 int trackIndex = 0;
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)
811 | (255 << 24);
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;
828 int trackIndex = 0;
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;
850 int trackIndex = 0;
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)
855 | (255 << 24);
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);
870 return f;