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