001 /*
002 * Copyright 1998-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.swing.colorchooser;
027
028 import javax.swing.*;
029 import java.awt.*;
030 import java.awt.event.*;
031 import javax.swing.event.*;
032 import javax.swing.border.*;
033 import java.awt.image.*;
034
035 /**
036 * Implements the default HSB Color chooser
037 *
038 * @version 1.33 05/05/07
039 * @author Tom Santos
040 * @author Steve Wilson
041 * @author Mark Davidson
042 * @author Shannon Hickey
043 */
044 class DefaultHSBChooserPanel extends AbstractColorChooserPanel
045 implements ChangeListener, HierarchyListener {
046
047 private transient HSBImage palette;
048 private transient HSBImage sliderPalette;
049
050 private transient Image paletteImage;
051 private transient Image sliderPaletteImage;
052
053 private JSlider slider;
054 private JSpinner hField;
055 private JSpinner sField;
056 private JSpinner bField;
057
058 private JTextField redField;
059 private JTextField greenField;
060 private JTextField blueField;
061
062 private boolean isAdjusting = false; // Flag which indicates that values are set internally
063 private Point paletteSelection = new Point();
064 private JLabel paletteLabel;
065 private JLabel sliderPaletteLabel;
066
067 private JRadioButton hRadio;
068 private JRadioButton sRadio;
069 private JRadioButton bRadio;
070
071 private static final int PALETTE_DIMENSION = 200;
072 private static final int MAX_HUE_VALUE = 359;
073 private static final int MAX_SATURATION_VALUE = 100;
074 private static final int MAX_BRIGHTNESS_VALUE = 100;
075
076 private int currentMode = HUE_MODE;
077
078 private static final int HUE_MODE = 0;
079 private static final int SATURATION_MODE = 1;
080 private static final int BRIGHTNESS_MODE = 2;
081
082 public DefaultHSBChooserPanel() {
083 }
084
085 private void addPaletteListeners() {
086 paletteLabel.addMouseListener(new MouseAdapter() {
087 public void mousePressed(MouseEvent e) {
088 float[] hsb = new float[3];
089 palette.getHSBForLocation(e.getX(), e.getY(), hsb);
090 updateHSB(hsb[0], hsb[1], hsb[2]);
091 }
092 });
093
094 paletteLabel.addMouseMotionListener(new MouseMotionAdapter() {
095 public void mouseDragged(MouseEvent e) {
096 int labelWidth = paletteLabel.getWidth();
097
098 int labelHeight = paletteLabel.getHeight();
099 int x = e.getX();
100 int y = e.getY();
101
102 if (x >= labelWidth) {
103 x = labelWidth - 1;
104 }
105
106 if (y >= labelHeight) {
107 y = labelHeight - 1;
108 }
109
110 if (x < 0) {
111 x = 0;
112 }
113
114 if (y < 0) {
115 y = 0;
116 }
117
118 float[] hsb = new float[3];
119 palette.getHSBForLocation(x, y, hsb);
120 updateHSB(hsb[0], hsb[1], hsb[2]);
121 }
122 });
123 }
124
125 private void updatePalette(float h, float s, float b) {
126 int x = 0;
127 int y = 0;
128
129 switch (currentMode) {
130 case HUE_MODE:
131 if (h != palette.getHue()) {
132 palette.setHue(h);
133 palette.nextFrame();
134 }
135 x = PALETTE_DIMENSION - (int) (s * PALETTE_DIMENSION);
136 y = PALETTE_DIMENSION - (int) (b * PALETTE_DIMENSION);
137 break;
138 case SATURATION_MODE:
139 if (s != palette.getSaturation()) {
140 palette.setSaturation(s);
141 palette.nextFrame();
142 }
143 x = (int) (h * PALETTE_DIMENSION);
144 y = PALETTE_DIMENSION - (int) (b * PALETTE_DIMENSION);
145 break;
146 case BRIGHTNESS_MODE:
147 if (b != palette.getBrightness()) {
148 palette.setBrightness(b);
149 palette.nextFrame();
150 }
151 x = (int) (h * PALETTE_DIMENSION);
152 y = PALETTE_DIMENSION - (int) (s * PALETTE_DIMENSION);
153 break;
154 }
155
156 paletteSelection.setLocation(x, y);
157 paletteLabel.repaint();
158 }
159
160 private void updateSlider(float h, float s, float b) {
161 // Update the slider palette if necessary.
162 // When the slider is the hue slider or the hue hasn't changed,
163 // the hue of the palette will not need to be updated.
164 if (currentMode != HUE_MODE && h != sliderPalette.getHue()) {
165 sliderPalette.setHue(h);
166 sliderPalette.nextFrame();
167 }
168
169 float value = 0f;
170
171 switch (currentMode) {
172 case HUE_MODE:
173 value = h;
174 break;
175 case SATURATION_MODE:
176 value = s;
177 break;
178 case BRIGHTNESS_MODE:
179 value = b;
180 break;
181 }
182
183 slider.setValue(Math.round(value * (slider.getMaximum())));
184 }
185
186 private void updateHSBTextFields(float hue, float saturation,
187 float brightness) {
188 int h = Math.round(hue * 359);
189 int s = Math.round(saturation * 100);
190 int b = Math.round(brightness * 100);
191
192 if (((Integer) hField.getValue()).intValue() != h) {
193 hField.setValue(new Integer(h));
194 }
195 if (((Integer) sField.getValue()).intValue() != s) {
196 sField.setValue(new Integer(s));
197 }
198 if (((Integer) bField.getValue()).intValue() != b) {
199 bField.setValue(new Integer(b));
200 }
201 }
202
203 /**
204 * Updates the values of the RGB fields to reflect the new color change
205 */
206 private void updateRGBTextFields(Color color) {
207 redField.setText(String.valueOf(color.getRed()));
208 greenField.setText(String.valueOf(color.getGreen()));
209 blueField.setText(String.valueOf(color.getBlue()));
210 }
211
212 /**
213 * Main internal method of updating the ui controls and the color model.
214 */
215 private void updateHSB(float h, float s, float b) {
216 if (!isAdjusting) {
217 isAdjusting = true;
218
219 updatePalette(h, s, b);
220 updateSlider(h, s, b);
221 updateHSBTextFields(h, s, b);
222
223 Color color = Color.getHSBColor(h, s, b);
224 updateRGBTextFields(color);
225
226 getColorSelectionModel().setSelectedColor(color);
227
228 isAdjusting = false;
229 }
230 }
231
232 /**
233 * Invoked automatically when the model's state changes.
234 * It is also called by <code>installChooserPanel</code> to allow
235 * you to set up the initial state of your chooser.
236 * Override this method to update your <code>ChooserPanel</code>.
237 */
238 public void updateChooser() {
239 if (!isAdjusting) {
240 float[] hsb = getHSBColorFromModel();
241 updateHSB(hsb[0], hsb[1], hsb[2]);
242 }
243 }
244
245 public void installChooserPanel(JColorChooser enclosingChooser) {
246 super .installChooserPanel(enclosingChooser);
247 setInheritsPopupMenu(true);
248 addHierarchyListener(this );
249 }
250
251 /**
252 * Invoked when the panel is removed from the chooser.
253 */
254 public void uninstallChooserPanel(JColorChooser enclosingChooser) {
255 super .uninstallChooserPanel(enclosingChooser);
256 cleanupPalettesIfNecessary();
257 removeAll();
258 removeHierarchyListener(this );
259 }
260
261 /**
262 * Returns an float array containing the HSB values of the selected color from
263 * the ColorSelectionModel
264 */
265 private float[] getHSBColorFromModel() {
266 Color color = getColorFromModel();
267 float[] hsb = new float[3];
268 Color.RGBtoHSB(color.getRed(), color.getGreen(), color
269 .getBlue(), hsb);
270
271 return hsb;
272 }
273
274 /**
275 * Builds a new chooser panel.
276 */
277 protected void buildChooser() {
278 setLayout(new BorderLayout());
279 JComponent spp = buildSliderPalettePanel();
280 spp.setInheritsPopupMenu(true);
281 add(spp, BorderLayout.BEFORE_LINE_BEGINS);
282
283 JPanel controlHolder = new JPanel(new SmartGridLayout(1, 3));
284 JComponent hsbControls = buildHSBControls();
285 hsbControls.setInheritsPopupMenu(true);
286 controlHolder.add(hsbControls);
287
288 controlHolder.add(new JLabel(" ")); // spacer
289
290 JComponent rgbControls = buildRGBControls();
291 rgbControls.setInheritsPopupMenu(true);
292 controlHolder.add(rgbControls);
293 controlHolder.setInheritsPopupMenu(true);
294
295 controlHolder.setBorder(new EmptyBorder(10, 5, 10, 5));
296 add(controlHolder, BorderLayout.CENTER);
297 }
298
299 /**
300 * Creates the panel with the uneditable RGB field
301 */
302 private JComponent buildRGBControls() {
303 JPanel panel = new JPanel(new SmartGridLayout(2, 3));
304 panel.setInheritsPopupMenu(true);
305
306 Color color = getColorFromModel();
307 redField = new JTextField(String.valueOf(color.getRed()), 3);
308 redField.setEditable(false);
309 redField.setHorizontalAlignment(JTextField.RIGHT);
310 redField.setInheritsPopupMenu(true);
311
312 greenField = new JTextField(String.valueOf(color.getGreen()), 3);
313 greenField.setEditable(false);
314 greenField.setHorizontalAlignment(JTextField.RIGHT);
315 greenField.setInheritsPopupMenu(true);
316
317 blueField = new JTextField(String.valueOf(color.getBlue()), 3);
318 blueField.setEditable(false);
319 blueField.setHorizontalAlignment(JTextField.RIGHT);
320 blueField.setInheritsPopupMenu(true);
321
322 String redString = UIManager
323 .getString("ColorChooser.hsbRedText");
324 String greenString = UIManager
325 .getString("ColorChooser.hsbGreenText");
326 String blueString = UIManager
327 .getString("ColorChooser.hsbBlueText");
328
329 panel.add(new JLabel(redString));
330 panel.add(redField);
331 panel.add(new JLabel(greenString));
332 panel.add(greenField);
333 panel.add(new JLabel(blueString));
334 panel.add(blueField);
335
336 return panel;
337 }
338
339 /**
340 * Creates the panel with the editable HSB fields and the radio buttons.
341 */
342 private JComponent buildHSBControls() {
343
344 String hueString = UIManager
345 .getString("ColorChooser.hsbHueText");
346 String saturationString = UIManager
347 .getString("ColorChooser.hsbSaturationText");
348 String brightnessString = UIManager
349 .getString("ColorChooser.hsbBrightnessText");
350
351 RadioButtonHandler handler = new RadioButtonHandler();
352
353 hRadio = new JRadioButton(hueString);
354 hRadio.addActionListener(handler);
355 hRadio.setSelected(true);
356 hRadio.setInheritsPopupMenu(true);
357
358 sRadio = new JRadioButton(saturationString);
359 sRadio.addActionListener(handler);
360 sRadio.setInheritsPopupMenu(true);
361
362 bRadio = new JRadioButton(brightnessString);
363 bRadio.addActionListener(handler);
364 bRadio.setInheritsPopupMenu(true);
365
366 ButtonGroup group = new ButtonGroup();
367 group.add(hRadio);
368 group.add(sRadio);
369 group.add(bRadio);
370
371 float[] hsb = getHSBColorFromModel();
372
373 hField = new JSpinner(new SpinnerNumberModel(
374 (int) (hsb[0] * 359), 0, 359, 1));
375 sField = new JSpinner(new SpinnerNumberModel(
376 (int) (hsb[1] * 100), 0, 100, 1));
377 bField = new JSpinner(new SpinnerNumberModel(
378 (int) (hsb[2] * 100), 0, 100, 1));
379
380 hField.addChangeListener(this );
381 sField.addChangeListener(this );
382 bField.addChangeListener(this );
383
384 hField.setInheritsPopupMenu(true);
385 sField.setInheritsPopupMenu(true);
386 bField.setInheritsPopupMenu(true);
387
388 JPanel panel = new JPanel(new SmartGridLayout(2, 3));
389
390 panel.add(hRadio);
391 panel.add(hField);
392 panel.add(sRadio);
393 panel.add(sField);
394 panel.add(bRadio);
395 panel.add(bField);
396 panel.setInheritsPopupMenu(true);
397
398 return panel;
399 }
400
401 /**
402 * Handler for the radio button classes.
403 */
404 private class RadioButtonHandler implements ActionListener {
405 public void actionPerformed(ActionEvent evt) {
406 Object obj = evt.getSource();
407
408 if (obj instanceof JRadioButton) {
409 JRadioButton button = (JRadioButton) obj;
410 if (button == hRadio) {
411 setMode(HUE_MODE);
412 } else if (button == sRadio) {
413 setMode(SATURATION_MODE);
414 } else if (button == bRadio) {
415 setMode(BRIGHTNESS_MODE);
416 }
417 }
418 }
419 }
420
421 private void setMode(int mode) {
422 if (currentMode == mode) {
423 return;
424 }
425
426 isAdjusting = true; // Ensure no events propagate from changing slider value.
427 currentMode = mode;
428
429 float[] hsb = getHSBColorFromModel();
430
431 switch (currentMode) {
432 case HUE_MODE:
433 slider.setInverted(true);
434 slider.setMaximum(MAX_HUE_VALUE);
435 palette.setValues(HSBImage.HSQUARE, hsb[0], 1.0f, 1.0f);
436 sliderPalette.setValues(HSBImage.HSLIDER, 0f, 1.0f, 1.0f);
437 break;
438 case SATURATION_MODE:
439 slider.setInverted(false);
440 slider.setMaximum(MAX_SATURATION_VALUE);
441 palette.setValues(HSBImage.SSQUARE, hsb[0], hsb[1], 1.0f);
442 sliderPalette.setValues(HSBImage.SSLIDER, hsb[0], 1.0f,
443 1.0f);
444 break;
445 case BRIGHTNESS_MODE:
446 slider.setInverted(false);
447 slider.setMaximum(MAX_BRIGHTNESS_VALUE);
448 palette.setValues(HSBImage.BSQUARE, hsb[0], 1.0f, hsb[2]);
449 sliderPalette.setValues(HSBImage.BSLIDER, hsb[0], 1.0f,
450 1.0f);
451 break;
452 }
453
454 isAdjusting = false;
455
456 palette.nextFrame();
457 sliderPalette.nextFrame();
458
459 updateChooser();
460 }
461
462 protected JComponent buildSliderPalettePanel() {
463
464 // This slider has to have a minimum of 0. A lot of math in this file is simplified due to this.
465 slider = new JSlider(JSlider.VERTICAL, 0, MAX_HUE_VALUE, 0);
466 slider.setInverted(true);
467 slider.setPaintTrack(false);
468 slider
469 .setPreferredSize(new Dimension(slider
470 .getPreferredSize().width,
471 PALETTE_DIMENSION + 15));
472 slider.addChangeListener(this );
473 slider.setInheritsPopupMenu(true);
474 // We're not painting ticks, but need to ask UI classes to
475 // paint arrow shape anyway, if possible.
476 slider.putClientProperty("Slider.paintThumbArrowShape",
477 Boolean.TRUE);
478 paletteLabel = createPaletteLabel();
479 addPaletteListeners();
480 sliderPaletteLabel = new JLabel();
481
482 JPanel panel = new JPanel();
483 panel.add(paletteLabel);
484 panel.add(slider);
485 panel.add(sliderPaletteLabel);
486
487 initializePalettesIfNecessary();
488
489 return panel;
490 }
491
492 private void initializePalettesIfNecessary() {
493 if (palette != null) {
494 return;
495 }
496
497 float[] hsb = getHSBColorFromModel();
498
499 switch (currentMode) {
500 case HUE_MODE:
501 palette = new HSBImage(HSBImage.HSQUARE, PALETTE_DIMENSION,
502 PALETTE_DIMENSION, hsb[0], 1.0f, 1.0f);
503 sliderPalette = new HSBImage(HSBImage.HSLIDER, 16,
504 PALETTE_DIMENSION, 0f, 1.0f, 1.0f);
505 break;
506 case SATURATION_MODE:
507 palette = new HSBImage(HSBImage.SSQUARE, PALETTE_DIMENSION,
508 PALETTE_DIMENSION, 1.0f, hsb[1], 1.0f);
509 sliderPalette = new HSBImage(HSBImage.SSLIDER, 16,
510 PALETTE_DIMENSION, 1.0f, 0f, 1.0f);
511 break;
512 case BRIGHTNESS_MODE:
513 palette = new HSBImage(HSBImage.BSQUARE, PALETTE_DIMENSION,
514 PALETTE_DIMENSION, 1.0f, 1.0f, hsb[2]);
515 sliderPalette = new HSBImage(HSBImage.BSLIDER, 16,
516 PALETTE_DIMENSION, 1.0f, 1.0f, 0f);
517 break;
518 }
519 paletteImage = Toolkit.getDefaultToolkit().createImage(palette);
520 sliderPaletteImage = Toolkit.getDefaultToolkit().createImage(
521 sliderPalette);
522
523 paletteLabel.setIcon(new ImageIcon(paletteImage));
524 sliderPaletteLabel.setIcon(new ImageIcon(sliderPaletteImage));
525 }
526
527 private void cleanupPalettesIfNecessary() {
528 if (palette == null) {
529 return;
530 }
531
532 palette.aborted = true;
533 sliderPalette.aborted = true;
534
535 palette.nextFrame();
536 sliderPalette.nextFrame();
537
538 palette = null;
539 sliderPalette = null;
540
541 paletteImage = null;
542 sliderPaletteImage = null;
543
544 paletteLabel.setIcon(null);
545 sliderPaletteLabel.setIcon(null);
546 }
547
548 protected JLabel createPaletteLabel() {
549 return new JLabel() {
550 protected void paintComponent(Graphics g) {
551 super .paintComponent(g);
552 g.setColor(Color.white);
553 g.drawOval(paletteSelection.x - 4,
554 paletteSelection.y - 4, 8, 8);
555 }
556 };
557 }
558
559 public String getDisplayName() {
560 return UIManager.getString("ColorChooser.hsbNameText");
561 }
562
563 /**
564 * Provides a hint to the look and feel as to the
565 * <code>KeyEvent.VK</code> constant that can be used as a mnemonic to
566 * access the panel. A return value <= 0 indicates there is no mnemonic.
567 * <p>
568 * The return value here is a hint, it is ultimately up to the look
569 * and feel to honor the return value in some meaningful way.
570 * <p>
571 * This implementation looks up the value from the default
572 * <code>ColorChooser.hsbMnemonic</code>, or if it
573 * isn't available (or not an <code>Integer</code>) returns -1.
574 * The lookup for the default is done through the <code>UIManager</code>:
575 * <code>UIManager.get("ColorChooser.rgbMnemonic");</code>.
576 *
577 * @return KeyEvent.VK constant identifying the mnemonic; <= 0 for no
578 * mnemonic
579 * @see #getDisplayedMnemonicIndex
580 * @since 1.4
581 */
582 public int getMnemonic() {
583 return getInt("ColorChooser.hsbMnemonic", -1);
584 }
585
586 /**
587 * Provides a hint to the look and feel as to the index of the character in
588 * <code>getDisplayName</code> that should be visually identified as the
589 * mnemonic. The look and feel should only use this if
590 * <code>getMnemonic</code> returns a value > 0.
591 * <p>
592 * The return value here is a hint, it is ultimately up to the look
593 * and feel to honor the return value in some meaningful way. For example,
594 * a look and feel may wish to render each
595 * <code>AbstractColorChooserPanel</code> in a <code>JTabbedPane</code>,
596 * and further use this return value to underline a character in
597 * the <code>getDisplayName</code>.
598 * <p>
599 * This implementation looks up the value from the default
600 * <code>ColorChooser.rgbDisplayedMnemonicIndex</code>, or if it
601 * isn't available (or not an <code>Integer</code>) returns -1.
602 * The lookup for the default is done through the <code>UIManager</code>:
603 * <code>UIManager.get("ColorChooser.hsbDisplayedMnemonicIndex");</code>.
604 *
605 * @return Character index to render mnemonic for; -1 to provide no
606 * visual identifier for this panel.
607 * @see #getMnemonic
608 * @since 1.4
609 */
610 public int getDisplayedMnemonicIndex() {
611 return getInt("ColorChooser.hsbDisplayedMnemonicIndex", -1);
612 }
613
614 public Icon getSmallDisplayIcon() {
615 return null;
616 }
617
618 public Icon getLargeDisplayIcon() {
619 return null;
620 }
621
622 /**
623 * Class for the slider and palette images.
624 */
625 class HSBImage extends SyntheticImage {
626 protected float h = .0f;
627 protected float s = .0f;
628 protected float b = .0f;
629 protected float[] hsb = new float[3];
630
631 protected boolean isDirty = true;
632 protected int cachedY;
633 protected int cachedColor;
634 protected int type;
635
636 private static final int HSQUARE = 0;
637 private static final int SSQUARE = 1;
638 private static final int BSQUARE = 2;
639 private static final int HSLIDER = 3;
640 private static final int SSLIDER = 4;
641 private static final int BSLIDER = 5;
642
643 protected HSBImage(int type, int width, int height, float h,
644 float s, float b) {
645 super (width, height);
646 setValues(type, h, s, b);
647 }
648
649 public void setValues(int type, float h, float s, float b) {
650 this .type = type;
651 cachedY = -1;
652 cachedColor = 0;
653 setHue(h);
654 setSaturation(s);
655 setBrightness(b);
656 }
657
658 public final void setHue(float hue) {
659 h = hue;
660 }
661
662 public final void setSaturation(float saturation) {
663 s = saturation;
664 }
665
666 public final void setBrightness(float brightness) {
667 b = brightness;
668 }
669
670 public final float getHue() {
671 return h;
672 }
673
674 public final float getSaturation() {
675 return s;
676 }
677
678 public final float getBrightness() {
679 return b;
680 }
681
682 protected boolean isStatic() {
683 return false;
684 }
685
686 public synchronized void nextFrame() {
687 isDirty = true;
688 notifyAll();
689 }
690
691 public synchronized void addConsumer(ImageConsumer ic) {
692 isDirty = true;
693 super .addConsumer(ic);
694 }
695
696 private int getRGBForLocation(int x, int y) {
697 if (type >= HSLIDER && y == cachedY) {
698 return cachedColor;
699 }
700
701 getHSBForLocation(x, y, hsb);
702 cachedY = y;
703 cachedColor = Color.HSBtoRGB(hsb[0], hsb[1], hsb[2]);
704
705 return cachedColor;
706 }
707
708 public void getHSBForLocation(int x, int y, float[] hsbArray) {
709 switch (type) {
710 case HSQUARE: {
711 float saturationStep = ((float) x) / width;
712 float brightnessStep = ((float) y) / height;
713 hsbArray[0] = h;
714 hsbArray[1] = s - saturationStep;
715 hsbArray[2] = b - brightnessStep;
716 break;
717 }
718 case SSQUARE: {
719 float brightnessStep = ((float) y) / height;
720 float step = 1.0f / ((float) width);
721 hsbArray[0] = x * step;
722 hsbArray[1] = s;
723 hsbArray[2] = 1.0f - brightnessStep;
724 break;
725 }
726 case BSQUARE: {
727 float saturationStep = ((float) y) / height;
728 float step = 1.0f / ((float) width);
729 hsbArray[0] = x * step;
730 hsbArray[1] = 1.0f - saturationStep;
731 hsbArray[2] = b;
732 break;
733 }
734 case HSLIDER: {
735 float step = 1.0f / ((float) height);
736 hsbArray[0] = y * step;
737 hsbArray[1] = s;
738 hsbArray[2] = b;
739 break;
740 }
741 case SSLIDER: {
742 float saturationStep = ((float) y) / height;
743 hsbArray[0] = h;
744 hsbArray[1] = s - saturationStep;
745 hsbArray[2] = b;
746 break;
747 }
748 case BSLIDER: {
749 float brightnessStep = ((float) y) / height;
750 hsbArray[0] = h;
751 hsbArray[1] = s;
752 hsbArray[2] = b - brightnessStep;
753 break;
754 }
755 }
756 }
757
758 /**
759 * Overriden method from SyntheticImage
760 */
761 protected void computeRow(int y, int[] row) {
762 if (y == 0) {
763 synchronized (this ) {
764 try {
765 while (!isDirty) {
766 wait();
767 }
768 } catch (InterruptedException ie) {
769 }
770 isDirty = false;
771 }
772 }
773
774 if (aborted) {
775 return;
776 }
777
778 for (int i = 0; i < row.length; ++i) {
779 row[i] = getRGBForLocation(i, y);
780 }
781 }
782 }
783
784 public void stateChanged(ChangeEvent e) {
785 if (e.getSource() == slider) {
786 boolean modelIsAdjusting = slider.getModel()
787 .getValueIsAdjusting();
788
789 if (!modelIsAdjusting && !isAdjusting) {
790 int sliderValue = slider.getValue();
791 int sliderRange = slider.getMaximum();
792 float value = (float) sliderValue / (float) sliderRange;
793
794 float[] hsb = getHSBColorFromModel();
795
796 switch (currentMode) {
797 case HUE_MODE:
798 updateHSB(value, hsb[1], hsb[2]);
799 break;
800 case SATURATION_MODE:
801 updateHSB(hsb[0], value, hsb[2]);
802 break;
803 case BRIGHTNESS_MODE:
804 updateHSB(hsb[0], hsb[1], value);
805 break;
806 }
807 }
808 } else if (e.getSource() instanceof JSpinner) {
809 float hue = ((Integer) hField.getValue()).floatValue() / 359f;
810 float saturation = ((Integer) sField.getValue())
811 .floatValue() / 100f;
812 float brightness = ((Integer) bField.getValue())
813 .floatValue() / 100f;
814
815 updateHSB(hue, saturation, brightness);
816 }
817 }
818
819 public void hierarchyChanged(HierarchyEvent he) {
820 if ((he.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
821 if (isDisplayable()) {
822 initializePalettesIfNecessary();
823 } else {
824 cleanupPalettesIfNecessary();
825 }
826 }
827 }
828
829 }
|