1 7 8 package javax.swing.colorchooser; 9 10 import javax.swing.*; 11 import java.awt.*; 12 import java.awt.event.*; 13 import javax.swing.event.*; 14 import javax.swing.border.*; 15 import java.awt.image.*; 16 17 26 class DefaultHSBChooserPanel extends AbstractColorChooserPanel implements ChangeListener, HierarchyListener { 27 28 private transient HSBImage palette; 29 private transient HSBImage sliderPalette; 30 31 private transient Image paletteImage; 32 private transient Image sliderPaletteImage; 33 34 private JSlider slider; 35 private JSpinner hField; 36 private JSpinner sField; 37 private JSpinner bField; 38 39 private JTextField redField; 40 private JTextField greenField; 41 private JTextField blueField; 42 43 private boolean isAdjusting = false; private Point paletteSelection = new Point(); 45 private JLabel paletteLabel; 46 private JLabel sliderPaletteLabel; 47 48 private JRadioButton hRadio; 49 private JRadioButton sRadio; 50 private JRadioButton bRadio; 51 52 private static final int PALETTE_DIMENSION = 200; 53 private static final int MAX_HUE_VALUE = 359; 54 private static final int MAX_SATURATION_VALUE = 100; 55 private static final int MAX_BRIGHTNESS_VALUE = 100; 56 57 private int currentMode = HUE_MODE; 58 59 private static final int HUE_MODE = 0; 60 private static final int SATURATION_MODE = 1; 61 private static final int BRIGHTNESS_MODE = 2; 62 63 public DefaultHSBChooserPanel() { 64 } 65 66 private void addPaletteListeners() { 67 paletteLabel.addMouseListener(new MouseAdapter() { 68 public void mousePressed(MouseEvent e ) { 69 float[] hsb = new float[3]; 70 palette.getHSBForLocation( e.getX(), e.getY(), hsb ); 71 updateHSB( hsb[0], hsb[1], hsb[2] ); 72 } 73 }); 74 75 paletteLabel.addMouseMotionListener(new MouseMotionAdapter() { 76 public void mouseDragged( MouseEvent e ){ 77 int labelWidth = paletteLabel.getWidth(); 78 79 int labelHeight = paletteLabel.getHeight(); 80 int x = e.getX(); 81 int y = e.getY(); 82 83 if ( x >= labelWidth ) { 84 x = labelWidth - 1; 85 } 86 87 if ( y >= labelHeight ) { 88 y = labelHeight - 1; 89 } 90 91 if ( x < 0 ) { 92 x = 0; 93 } 94 95 if ( y < 0 ) { 96 y = 0; 97 } 98 99 float[] hsb = new float[3]; 100 palette.getHSBForLocation( x, y, hsb ); 101 updateHSB( hsb[0], hsb[1], hsb[2] ); 102 } 103 }); 104 } 105 106 private void updatePalette( float h, float s, float b ) { 107 int x = 0; 108 int y = 0; 109 110 switch ( currentMode ) { 111 case HUE_MODE: 112 if ( h != palette.getHue() ) { 113 palette.setHue( h ); 114 palette.nextFrame(); 115 } 116 x = PALETTE_DIMENSION - (int)(s * PALETTE_DIMENSION); 117 y = PALETTE_DIMENSION - (int)(b * PALETTE_DIMENSION); 118 break; 119 case SATURATION_MODE: 120 if ( s != palette.getSaturation() ) { 121 palette.setSaturation( s ); 122 palette.nextFrame(); 123 } 124 x = (int)(h * PALETTE_DIMENSION); 125 y = PALETTE_DIMENSION - (int)(b * PALETTE_DIMENSION); 126 break; 127 case BRIGHTNESS_MODE: 128 if ( b != palette.getBrightness() ) { 129 palette.setBrightness( b ); 130 palette.nextFrame(); 131 } 132 x = (int)(h * PALETTE_DIMENSION); 133 y = PALETTE_DIMENSION - (int)(s * PALETTE_DIMENSION); 134 break; 135 } 136 137 paletteSelection.setLocation( x, y ); 138 paletteLabel.repaint(); 139 } 140 141 private void updateSlider( float h, float s, float b ) { 142 if (currentMode != HUE_MODE && h != sliderPalette.getHue() ) { 146 sliderPalette.setHue( h ); 147 sliderPalette.nextFrame(); 148 } 149 150 float value = 0f; 151 152 switch ( currentMode ) { 153 case HUE_MODE: 154 value = h; 155 break; 156 case SATURATION_MODE: 157 value = s; 158 break; 159 case BRIGHTNESS_MODE: 160 value = b; 161 break; 162 } 163 164 slider.setValue( Math.round(value * (slider.getMaximum())) ); 165 } 166 167 private void updateHSBTextFields( float hue, float saturation, float brightness ) { 168 int h = Math.round(hue * 359); 169 int s = Math.round(saturation * 100); 170 int b = Math.round(brightness * 100); 171 172 if (((Integer )hField.getValue()).intValue() != h) { 173 hField.setValue(new Integer (h)); 174 } 175 if (((Integer )sField.getValue()).intValue() != s) { 176 sField.setValue(new Integer (s)); 177 } 178 if (((Integer )bField.getValue()).intValue() != b) { 179 bField.setValue(new Integer (b)); 180 } 181 } 182 183 186 private void updateRGBTextFields( Color color ) { 187 redField.setText(String.valueOf(color.getRed())); 188 greenField.setText(String.valueOf(color.getGreen())); 189 blueField.setText(String.valueOf(color.getBlue())); 190 } 191 192 195 private void updateHSB( float h, float s, float b ) { 196 if ( !isAdjusting ) { 197 isAdjusting = true; 198 199 updatePalette( h, s, b ); 200 updateSlider( h, s, b ); 201 updateHSBTextFields( h, s, b ); 202 203 Color color = Color.getHSBColor(h, s, b); 204 updateRGBTextFields( color ); 205 206 getColorSelectionModel().setSelectedColor( color ); 207 208 isAdjusting = false; 209 } 210 } 211 212 218 public void updateChooser() { 219 if ( !isAdjusting ) { 220 float[] hsb = getHSBColorFromModel(); 221 updateHSB( hsb[0], hsb[1], hsb[2] ); 222 } 223 } 224 225 public void installChooserPanel(JColorChooser enclosingChooser) { 226 super.installChooserPanel(enclosingChooser); 227 addHierarchyListener(this); 228 } 229 230 233 public void uninstallChooserPanel(JColorChooser enclosingChooser) { 234 super.uninstallChooserPanel(enclosingChooser); 235 cleanupPalettesIfNecessary(); 236 removeAll(); 237 removeHierarchyListener(this); 238 } 239 240 244 private float[] getHSBColorFromModel() { 245 Color color = getColorFromModel(); 246 float[] hsb = new float[3]; 247 Color.RGBtoHSB( color.getRed(), color.getGreen(), color.getBlue(), hsb ); 248 249 return hsb; 250 } 251 252 255 protected void buildChooser() { 256 setLayout(new BorderLayout()); 257 JComponent spp = buildSliderPalettePanel(); 258 add(spp, BorderLayout.BEFORE_LINE_BEGINS); 259 260 JPanel controlHolder = new JPanel(new SmartGridLayout (1,3)); 261 JComponent hsbControls = buildHSBControls(); 262 controlHolder.add(hsbControls); 263 264 controlHolder.add(new JLabel(" ")); 266 JComponent rgbControls = buildRGBControls(); 267 controlHolder.add(rgbControls); 268 269 controlHolder.setBorder(new EmptyBorder( 10, 5, 10, 5)); 270 add( controlHolder, BorderLayout.CENTER); 271 } 272 273 276 private JComponent buildRGBControls() { 277 JPanel panel = new JPanel(new SmartGridLayout (2,3)); 278 279 Color color = getColorFromModel(); 280 redField = new JTextField( String.valueOf(color.getRed()), 3 ); 281 redField.setEditable(false); 282 redField.setHorizontalAlignment( JTextField.RIGHT ); 283 284 greenField = new JTextField(String.valueOf(color.getGreen()), 3 ); 285 greenField.setEditable(false); 286 greenField.setHorizontalAlignment( JTextField.RIGHT ); 287 288 blueField = new JTextField( String.valueOf(color.getBlue()), 3 ); 289 blueField.setEditable(false); 290 blueField.setHorizontalAlignment( JTextField.RIGHT ); 291 292 String redString = UIManager.getString("ColorChooser.hsbRedText"); 293 String greenString = UIManager.getString("ColorChooser.hsbGreenText"); 294 String blueString = UIManager.getString("ColorChooser.hsbBlueText"); 295 296 panel.add( new JLabel(redString) ); 297 panel.add( redField ); 298 panel.add( new JLabel(greenString) ); 299 panel.add( greenField ); 300 panel.add( new JLabel(blueString) ); 301 panel.add( blueField ); 302 303 return panel; 304 } 305 306 309 private JComponent buildHSBControls() { 310 311 String hueString = UIManager.getString("ColorChooser.hsbHueText"); 312 String saturationString = UIManager.getString("ColorChooser.hsbSaturationText"); 313 String brightnessString = UIManager.getString("ColorChooser.hsbBrightnessText"); 314 315 RadioButtonHandler handler = new RadioButtonHandler(); 316 317 hRadio = new JRadioButton(hueString); 318 hRadio.addActionListener(handler); 319 hRadio.setSelected(true); 320 321 sRadio = new JRadioButton(saturationString); 322 sRadio.addActionListener(handler); 323 324 bRadio = new JRadioButton(brightnessString); 325 bRadio.addActionListener(handler); 326 327 ButtonGroup group = new ButtonGroup(); 328 group.add(hRadio); 329 group.add(sRadio); 330 group.add(bRadio); 331 332 float[] hsb = getHSBColorFromModel(); 333 334 hField = new JSpinner(new SpinnerNumberModel((int)(hsb[0] * 359), 0, 359, 1)); 335 sField = new JSpinner(new SpinnerNumberModel((int)(hsb[1] * 100), 0, 100, 1)); 336 bField = new JSpinner(new SpinnerNumberModel((int)(hsb[2] * 100), 0, 100, 1)); 337 338 hField.addChangeListener(this); 339 sField.addChangeListener(this); 340 bField.addChangeListener(this); 341 342 JPanel panel = new JPanel( new SmartGridLayout (2, 3) ); 343 344 panel.add(hRadio); 345 panel.add(hField); 346 panel.add(sRadio); 347 panel.add(sField); 348 panel.add(bRadio); 349 panel.add(bField); 350 351 return panel; 352 } 353 354 357 private class RadioButtonHandler implements ActionListener { 358 public void actionPerformed(ActionEvent evt) { 359 Object obj = evt.getSource(); 360 361 if (obj instanceof JRadioButton) { 362 JRadioButton button = (JRadioButton)obj; 363 if (button == hRadio) { 364 setMode(HUE_MODE); 365 } else if (button == sRadio) { 366 setMode(SATURATION_MODE); 367 } else if (button == bRadio) { 368 setMode(BRIGHTNESS_MODE); 369 } 370 } 371 } 372 } 373 374 private void setMode(int mode) { 375 if (currentMode == mode) { 376 return; 377 } 378 379 isAdjusting = true; currentMode = mode; 381 382 float[] hsb = getHSBColorFromModel(); 383 384 switch (currentMode) { 385 case HUE_MODE: 386 slider.setInverted(true); 387 slider.setMaximum(MAX_HUE_VALUE); 388 palette.setValues(HSBImage.HSQUARE, hsb[0], 1.0f, 1.0f); 389 sliderPalette.setValues(HSBImage.HSLIDER, 0f, 1.0f, 1.0f); 390 break; 391 case SATURATION_MODE: 392 slider.setInverted(false); 393 slider.setMaximum(MAX_SATURATION_VALUE); 394 palette.setValues(HSBImage.SSQUARE, hsb[0], hsb[1], 1.0f); 395 sliderPalette.setValues(HSBImage.SSLIDER, hsb[0], 1.0f, 1.0f); 396 break; 397 case BRIGHTNESS_MODE: 398 slider.setInverted(false); 399 slider.setMaximum(MAX_BRIGHTNESS_VALUE); 400 palette.setValues(HSBImage.BSQUARE, hsb[0], 1.0f, hsb[2]); 401 sliderPalette.setValues(HSBImage.BSLIDER, hsb[0], 1.0f, 1.0f); 402 break; 403 } 404 405 isAdjusting = false; 406 407 palette.nextFrame(); 408 sliderPalette.nextFrame(); 409 410 updateChooser(); 411 } 412 413 protected JComponent buildSliderPalettePanel() { 414 415 slider = new JSlider(JSlider.VERTICAL, 0, MAX_HUE_VALUE, 0); 417 slider.setInverted(true); 418 slider.setPaintTrack(false); 419 slider.setPreferredSize(new Dimension(slider.getPreferredSize().width, PALETTE_DIMENSION + 15)); 420 slider.addChangeListener(this); 421 slider.putClientProperty("Slider.paintThumbArrowShape", Boolean.TRUE); 424 paletteLabel = createPaletteLabel(); 425 addPaletteListeners(); 426 sliderPaletteLabel = new JLabel(); 427 428 JPanel panel = new JPanel(); 429 panel.add( paletteLabel ); 430 panel.add( slider ); 431 panel.add( sliderPaletteLabel ); 432 433 initializePalettesIfNecessary(); 434 435 return panel; 436 } 437 438 private void initializePalettesIfNecessary() { 439 if (palette != null) { 440 return; 441 } 442 443 float[] hsb = getHSBColorFromModel(); 444 445 switch(currentMode){ 446 case HUE_MODE: 447 palette = new HSBImage(HSBImage.HSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, hsb[0], 1.0f, 1.0f); 448 sliderPalette = new HSBImage(HSBImage.HSLIDER, 16, PALETTE_DIMENSION, 0f, 1.0f, 1.0f); 449 break; 450 case SATURATION_MODE: 451 palette = new HSBImage(HSBImage.SSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, 1.0f, hsb[1], 1.0f); 452 sliderPalette = new HSBImage(HSBImage.SSLIDER, 16, PALETTE_DIMENSION, 1.0f, 0f, 1.0f); 453 break; 454 case BRIGHTNESS_MODE: 455 palette = new HSBImage(HSBImage.BSQUARE, PALETTE_DIMENSION, PALETTE_DIMENSION, 1.0f, 1.0f, hsb[2]); 456 sliderPalette = new HSBImage(HSBImage.BSLIDER, 16, PALETTE_DIMENSION, 1.0f, 1.0f, 0f); 457 break; 458 } 459 paletteImage = Toolkit.getDefaultToolkit().createImage(palette); 460 sliderPaletteImage = Toolkit.getDefaultToolkit().createImage(sliderPalette); 461 462 paletteLabel.setIcon(new ImageIcon(paletteImage)); 463 sliderPaletteLabel.setIcon(new ImageIcon(sliderPaletteImage)); 464 } 465 466 private void cleanupPalettesIfNecessary() { 467 if (palette == null) { 468 return; 469 } 470 471 palette.aborted = true; 472 sliderPalette.aborted = true; 473 474 palette.nextFrame(); 475 sliderPalette.nextFrame(); 476 477 palette = null; 478 sliderPalette = null; 479 480 paletteImage = null; 481 sliderPaletteImage = null; 482 483 paletteLabel.setIcon(null); 484 sliderPaletteLabel.setIcon(null); 485 } 486 487 protected JLabel createPaletteLabel() { 488 return new JLabel() { 489 protected void paintComponent( Graphics g ) { 490 super.paintComponent( g ); 491 g.setColor( Color.white ); 492 g.drawOval( paletteSelection.x - 4, paletteSelection.y - 4, 8, 8 ); 493 } 494 }; 495 } 496 497 public String getDisplayName() { 498 return UIManager.getString("ColorChooser.hsbNameText"); 499 } 500 501 520 public int getMnemonic() { 521 return getInt("ColorChooser.hsbMnemonic", -1); 522 } 523 524 548 public int getDisplayedMnemonicIndex() { 549 return getInt("ColorChooser.hsbDisplayedMnemonicIndex", -1); 550 } 551 552 public Icon getSmallDisplayIcon() { 553 return null; 554 } 555 556 public Icon getLargeDisplayIcon() { 557 return null; 558 } 559 560 563 class HSBImage extends SyntheticImage { 564 protected float h = .0f; 565 protected float s = .0f; 566 protected float b = .0f; 567 protected float[] hsb = new float[3]; 568 569 protected boolean isDirty = true; 570 protected int cachedY; 571 protected int cachedColor; 572 protected int type; 573 574 private static final int HSQUARE = 0; 575 private static final int SSQUARE = 1; 576 private static final int BSQUARE = 2; 577 private static final int HSLIDER = 3; 578 private static final int SSLIDER = 4; 579 private static final int BSLIDER = 5; 580 581 protected HSBImage(int type, int width, int height, float h, float s, float b) { 582 super(width, height); 583 setValues(type, h, s, b); 584 } 585 586 public void setValues(int type, float h, float s, float b) { 587 this.type = type; 588 cachedY = -1; 589 cachedColor = 0; 590 setHue( h ); 591 setSaturation( s ); 592 setBrightness( b ); 593 } 594 595 public final void setHue( float hue ) { 596 h = hue; 597 } 598 599 public final void setSaturation( float saturation ) { 600 s = saturation; 601 } 602 603 public final void setBrightness( float brightness ) { 604 b = brightness; 605 } 606 607 public final float getHue() { 608 return h; 609 } 610 611 public final float getSaturation() { 612 return s; 613 } 614 615 public final float getBrightness() { 616 return b; 617 } 618 619 protected boolean isStatic() { 620 return false; 621 } 622 623 public synchronized void nextFrame() { 624 isDirty = true; 625 notifyAll(); 626 } 627 628 public synchronized void addConsumer(ImageConsumer ic) { 629 isDirty = true; 630 super.addConsumer(ic); 631 } 632 633 private int getRGBForLocation( int x, int y ) { 634 if (type >= HSLIDER && y == cachedY) { 635 return cachedColor; 636 } 637 638 getHSBForLocation( x, y, hsb ); 639 cachedY = y; 640 cachedColor = Color.HSBtoRGB( hsb[0], hsb[1], hsb[2] ); 641 642 return cachedColor; 643 } 644 645 public void getHSBForLocation( int x, int y, float[] hsbArray ) { 646 switch (type) { 647 case HSQUARE: { 648 float saturationStep = ((float)x) / width; 649 float brightnessStep = ((float)y) / height; 650 hsbArray[0] = h; 651 hsbArray[1] = s - saturationStep; 652 hsbArray[2] = b - brightnessStep; 653 break; 654 } 655 case SSQUARE: { 656 float brightnessStep = ((float)y) / height; 657 float step = 1.0f / ((float)width); 658 hsbArray[0] = x * step; 659 hsbArray[1] = s; 660 hsbArray[2] = 1.0f - brightnessStep; 661 break; 662 } 663 case BSQUARE: { 664 float saturationStep = ((float)y) / height; 665 float step = 1.0f / ((float)width); 666 hsbArray[0] = x * step; 667 hsbArray[1] = 1.0f - saturationStep; 668 hsbArray[2] = b; 669 break; 670 } 671 case HSLIDER: { 672 float step = 1.0f / ((float)height); 673 hsbArray[0] = y * step; 674 hsbArray[1] = s; 675 hsbArray[2] = b; 676 break; 677 } 678 case SSLIDER: { 679 float saturationStep = ((float)y) / height; 680 hsbArray[0] = h; 681 hsbArray[1] = s - saturationStep; 682 hsbArray[2] = b; 683 break; 684 } 685 case BSLIDER: { 686 float brightnessStep = ((float)y) / height; 687 hsbArray[0] = h; 688 hsbArray[1] = s; 689 hsbArray[2] = b - brightnessStep; 690 break; 691 } 692 } 693 } 694 695 698 protected void computeRow( int y, int[] row ) { 699 if ( y == 0 ) { 700 synchronized ( this ) { 701 try { 702 while ( !isDirty ) { 703 wait(); 704 } 705 } catch (InterruptedException ie) { 706 } 707 isDirty = false; 708 } 709 } 710 711 if (aborted) { 712 return; 713 } 714 715 for ( int i = 0; i < row.length; ++i ) { 716 row[i] = getRGBForLocation( i, y ); 717 } 718 } 719 } 720 721 public void stateChanged(ChangeEvent e) { 722 if (e.getSource() == slider) { 723 boolean modelIsAdjusting = slider.getModel().getValueIsAdjusting(); 724 725 if (!modelIsAdjusting && !isAdjusting) { 726 int sliderValue = slider.getValue(); 727 int sliderRange = slider.getMaximum(); 728 float value = (float)sliderValue / (float)sliderRange; 729 730 float[] hsb = getHSBColorFromModel(); 731 732 switch ( currentMode ){ 733 case HUE_MODE: 734 updateHSB(value, hsb[1], hsb[2]); 735 break; 736 case SATURATION_MODE: 737 updateHSB(hsb[0], value, hsb[2]); 738 break; 739 case BRIGHTNESS_MODE: 740 updateHSB(hsb[0], hsb[1], value); 741 break; 742 } 743 } 744 } else if (e.getSource() instanceof JSpinner) { 745 float hue = ((Integer )hField.getValue()).floatValue() / 359f; 746 float saturation = ((Integer )sField.getValue()).floatValue() / 100f; 747 float brightness = ((Integer )bField.getValue()).floatValue() / 100f; 748 749 updateHSB(hue, saturation, brightness); 750 } 751 } 752 753 public void hierarchyChanged(HierarchyEvent he) { 754 if ((he.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) { 755 if (isDisplayable()) { 756 initializePalettesIfNecessary(); 757 } else { 758 cleanupPalettesIfNecessary(); 759 } 760 } 761 } 762 763 } 764 | Popular Tags |