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