Source for javax.swing.JColorChooser

   1: /* JColorChooser.java --
   2:    Copyright (C) 2002, 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   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.
  10: 
  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.
  15: 
  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., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  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.
  25: 
  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. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import java.awt.AWTError;
  42: import java.awt.BorderLayout;
  43: import java.awt.Color;
  44: import java.awt.Component;
  45: import java.awt.Dialog;
  46: import java.awt.FlowLayout;
  47: import java.awt.Frame;
  48: import java.awt.event.ActionEvent;
  49: import java.awt.event.ActionListener;
  50: 
  51: import javax.accessibility.Accessible;
  52: import javax.accessibility.AccessibleContext;
  53: import javax.accessibility.AccessibleRole;
  54: import javax.swing.colorchooser.AbstractColorChooserPanel;
  55: import javax.swing.colorchooser.ColorSelectionModel;
  56: import javax.swing.colorchooser.DefaultColorSelectionModel;
  57: import javax.swing.plaf.ColorChooserUI;
  58: 
  59: 
  60: /**
  61:  * A Swing widget that offers users different ways to
  62:  * select a color. By default, three different panels are presented to the
  63:  * user that are capable of changing the selected color. There are three ways
  64:  * to utilize JColorChooser. The first is to build a JColorChooser and add it
  65:  * to the content pane. The second is to use the createDialog method to
  66:  * create a JDialog that holds a JColorChooser. The third is to show a
  67:  * JColorChooser in a JDialog directly using the showDialog method.
  68:  *
  69:  * @author original author unknown
  70:  */
  71: public class JColorChooser extends JComponent implements Accessible
  72: {
  73:   /** DOCUMENT ME! */
  74:   private static final long serialVersionUID = 9168066781620640889L;
  75: 
  76:   /**
  77:    * Accessibility support for <code>JColorChooser</code>.
  78:    */
  79:   protected class AccessibleJColorChooser
  80:     extends JComponent.AccessibleJComponent
  81:   {
  82:     /** DOCUMENT ME! */
  83:     private static final long serialVersionUID = -2038297864782299082L;
  84: 
  85:     /**
  86:      * Constructor AccessibleJColorChooser
  87:      */
  88:     protected AccessibleJColorChooser()
  89:     {
  90:     }
  91: 
  92:     /**
  93:      * getAccessibleRole
  94:      *
  95:      * @return AccessibleRole
  96:      */
  97:     public AccessibleRole getAccessibleRole()
  98:     {
  99:       return AccessibleRole.COLOR_CHOOSER;
 100:     } // getAccessibleRole()
 101:   } // AccessibleJColorChooser
 102: 
 103:   /** The model used with the JColorChooser. */
 104:   private ColorSelectionModel selectionModel;
 105: 
 106:   /** The preview panel associated with the JColorChooser. */
 107:   private JComponent previewPanel;
 108: 
 109:   /**
 110:    * The set of AbstractColorChooserPanels associated with the JColorChooser.
 111:    */
 112:   private AbstractColorChooserPanel[] chooserPanels;
 113: 
 114:   /** A Drag and Drop property. */
 115:   private boolean dragEnabled;
 116: 
 117:   /**
 118:    * The property fired by the JColorChooser when the selectionModel property
 119:    * changes.
 120:    */
 121:   public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
 122: 
 123:   /**
 124:    * The property fired by the JColorChooser when the previewPanel property
 125:    * changes.
 126:    */
 127:   public static final String PREVIEW_PANEL_PROPERTY = "previewPanel";
 128: 
 129:   /**
 130:    * The property fired by the JColorChooser when the chooserPanels property
 131:    * changes.
 132:    */
 133:   public static final String CHOOSER_PANELS_PROPERTY = "chooserPanels";
 134: 
 135:   /** accessibleContext */
 136:   protected AccessibleContext accessibleContext;
 137: 
 138:   /**
 139:    * This method creates a new JColorChooser with the default initial color.
 140:    */
 141:   public JColorChooser()
 142:   {
 143:     this(new DefaultColorSelectionModel());
 144:   } // JColorChooser()
 145: 
 146:   /**
 147:    * This method creates a new JColorChooser with the given initial color.
 148:    *
 149:    * @param initial The initial color.
 150:    */
 151:   public JColorChooser(Color initial)
 152:   {
 153:     this(new DefaultColorSelectionModel(initial));
 154:   } // JColorChooser()
 155: 
 156:   /**
 157:    * This method creates a new JColorChooser with the given model. The model
 158:    * will dictate what the initial color for the JColorChooser is.
 159:    *
 160:    * @param model The Model to use with the JColorChooser.
 161:    */
 162:   public JColorChooser(ColorSelectionModel model)
 163:   {
 164:     if (model == null)
 165:       model = new DefaultColorSelectionModel();
 166:     selectionModel = model;
 167:     updateUI();
 168:   } // JColorChooser()
 169: 
 170:   /**
 171:    * This method sets the current color for the JColorChooser.
 172:    *
 173:    * @param color The new color for the JColorChooser.
 174:    */
 175:   public void setColor(Color color)
 176:   {
 177:     if (color != null)
 178:       selectionModel.setSelectedColor(color);
 179:   } // setColor()
 180: 
 181:   /**
 182:    * This method sets the current color for the JColorChooser using RGB
 183:    * values.
 184:    *
 185:    * @param r The red value.
 186:    * @param g The green value.
 187:    * @param b The blue value.
 188:    */
 189:   public void setColor(int r, int g, int b)
 190:   {
 191:     selectionModel.setSelectedColor(new Color(r, g, b));
 192:   } // setColor()
 193: 
 194:   /**
 195:    * This method sets the current color for the JColorChooser using the
 196:    * integer value. Bits 0-7 represent the blue value. Bits 8-15 represent
 197:    * the green value. Bits 16-23 represent the red value.
 198:    *
 199:    * @param color The new current color of the JColorChooser.
 200:    */
 201:   public void setColor(int color)
 202:   {
 203:     setColor(new Color(color, false));
 204:   } // setColor()
 205: 
 206:   /**
 207:    * This method shows a JColorChooser inside a JDialog. The JDialog will
 208:    * block until it is hidden. The JDialog comes with three buttons: OK,
 209:    * Cancel, and Reset. Pressing OK or Cancel hide the JDialog. Pressing
 210:    * Reset will reset the JColorChooser to its initial value.
 211:    *
 212:    * @param component The Component that parents the JDialog.
 213:    * @param title The title displayed in the JDialog.
 214:    * @param initial The initial color.
 215:    *
 216:    * @return The selected color.
 217:    */
 218:   public static Color showDialog(Component component, String title,
 219:                                  Color initial)
 220:   {
 221:     JColorChooser choose = new JColorChooser(initial);
 222: 
 223:     JDialog dialog = createDialog(component, title, true, choose, null, null);
 224: 
 225:     dialog.getContentPane().add(choose);
 226:     dialog.pack();
 227:     dialog.show();
 228: 
 229:     return choose.getColor();
 230:   } // showDialog()
 231: 
 232:   /**
 233:    * This is a helper method to make the given JDialog block until it is
 234:    * hidden.  This is package-private to avoid an accessor method.
 235:    *
 236:    * @param dialog The JDialog to block.
 237:    */
 238:   static void makeModal(JDialog dialog)
 239:   {
 240:     try
 241:       {
 242:         synchronized (dialog)
 243:           {
 244:             while (dialog.isVisible())
 245:               dialog.wait();
 246:           }
 247:       }
 248:     catch (InterruptedException e)
 249:       {
 250:       }
 251:   }
 252: 
 253:   /**
 254:    * This is a helper method to find the first Frame or Dialog ancestor of the
 255:    * given Component.
 256:    *
 257:    * @param c The Component to find ancestors for.
 258:    *
 259:    * @return A Frame or Dialog ancestor. Null if none are found.
 260:    */
 261:   private static Component findParent(Component c)
 262:   {
 263:     Component parent = SwingUtilities.getAncestorOfClass(Frame.class, c);
 264:     if (parent != null)
 265:       return parent;
 266:     parent = SwingUtilities.getAncestorOfClass(Dialog.class, c);
 267:     return parent;
 268:   }
 269: 
 270:   /**
 271:    * This method will take the given JColorChooser and place it in a JDialog
 272:    * with the given modal property. Three buttons are displayed in the
 273:    * JDialog: OK, Cancel and Reset. If OK or Cancel are pressed, the JDialog
 274:    * is hidden. If Reset is pressed, then the JColorChooser will take on its
 275:    * default color value. The given okListener will be registered to the OK
 276:    * button and the cancelListener will be registered to the Cancel button.
 277:    * If the modal property is set, then the JDialog will block until it is
 278:    * hidden.
 279:    *
 280:    * @param component The Component that will parent the JDialog.
 281:    * @param title The title displayed in the JDialog.
 282:    * @param modal The modal property.
 283:    * @param chooserPane The JColorChooser to place in the JDialog.
 284:    * @param okListener The ActionListener to register to the OK button.
 285:    * @param cancelListener The ActionListener to register to the Cancel
 286:    *        button.
 287:    *
 288:    * @return A JDialog with the JColorChooser inside of it.
 289:    *
 290:    * @throws AWTError If the component is not a suitable parent.
 291:    */
 292:   public static JDialog createDialog(Component component, String title,
 293:                                      boolean modal, JColorChooser chooserPane,
 294:                                      ActionListener okListener,
 295:                                      ActionListener cancelListener)
 296:   {
 297:     Component parent = findParent(component);
 298:     if (parent == null)
 299:       throw new AWTError("No suitable parent found for Component.");
 300:     JDialog dialog;
 301:     if (parent instanceof Frame)
 302:       dialog = new ModalDialog((Frame) parent, title);
 303:     else
 304:       dialog = new ModalDialog((Dialog) parent, title);
 305:     dialog.setModal(modal);
 306: 
 307:     dialog.getContentPane().setLayout(new BorderLayout());
 308: 
 309:     JPanel panel = new JPanel();
 310:     panel.setLayout(new FlowLayout());
 311: 
 312:     ActionListener al = new DefaultOKCancelListener(dialog);
 313: 
 314:     JButton ok = new JButton("OK");
 315:     ok.addActionListener(okListener);
 316:     ok.addActionListener(al);
 317: 
 318:     JButton cancel = new JButton("Cancel");
 319:     cancel.addActionListener(cancelListener);
 320:     cancel.addActionListener(al);
 321: 
 322:     JButton reset = new JButton("Reset");
 323:     reset.addActionListener(new DefaultResetListener(chooserPane));
 324: 
 325:     dialog.getContentPane().add(chooserPane, BorderLayout.NORTH);
 326: 
 327:     panel.add(ok);
 328:     panel.add(cancel);
 329:     panel.add(reset);
 330: 
 331:     dialog.getContentPane().add(panel, BorderLayout.SOUTH);
 332: 
 333:     return dialog;
 334:   } // createDialog()
 335: 
 336:   /**
 337:    * This method returns the UI Component used for this JColorChooser.
 338:    *
 339:    * @return The UI Component for this JColorChooser.
 340:    */
 341:   public ColorChooserUI getUI()
 342:   {
 343:     return (ColorChooserUI) ui;
 344:   } // getUI()
 345: 
 346:   /**
 347:    * This method sets the UI Component used for this JColorChooser.
 348:    *
 349:    * @param ui The UI Component to use with this JColorChooser.
 350:    */
 351:   public void setUI(ColorChooserUI ui)
 352:   {
 353:     super.setUI(ui);
 354:   } // setUI()
 355: 
 356:   /**
 357:    * This method resets the UI Component property to the Look and Feel
 358:    * default.
 359:    */
 360:   public void updateUI()
 361:   {
 362:     setUI((ColorChooserUI) UIManager.getUI(this));
 363:     revalidate();
 364:   } // updateUI()
 365: 
 366:   /**
 367:    * This method returns a String identifier for the UI Class to be used with
 368:    * the JColorChooser.
 369:    *
 370:    * @return The String identifier for the UI Class.
 371:    */
 372:   public String getUIClassID()
 373:   {
 374:     return "ColorChooserUI";
 375:   } // getUIClassID()
 376: 
 377:   /**
 378:    * This method returns the current color for the JColorChooser.
 379:    *
 380:    * @return The current color for the JColorChooser.
 381:    */
 382:   public Color getColor()
 383:   {
 384:     return selectionModel.getSelectedColor(); // TODO
 385:   } // getColor()
 386: 
 387:   /**
 388:    * This method changes the previewPanel property for the JTabbedPane. The
 389:    * previewPanel is responsible for indicating the current color of the
 390:    * JColorChooser.
 391:    *
 392:    * @param component The Component that will act as the previewPanel.
 393:    */
 394:   public void setPreviewPanel(JComponent component)
 395:   {
 396:     if (component != previewPanel)
 397:       {
 398:         JComponent old = previewPanel;
 399:         previewPanel = component;
 400:         firePropertyChange(PREVIEW_PANEL_PROPERTY, old, previewPanel);
 401:       }
 402:   } // setPreviewPanel()
 403: 
 404:   /**
 405:    * This method returns the current previewPanel used with this
 406:    * JColorChooser.
 407:    *
 408:    * @return The current previewPanel.
 409:    */
 410:   public JComponent getPreviewPanel()
 411:   {
 412:     return previewPanel; // TODO
 413:   } // getPreviewPanel()
 414: 
 415:   /**
 416:    * This method adds the given AbstractColorChooserPanel to the list of the
 417:    * JColorChooser's chooserPanels.
 418:    *
 419:    * @param panel The AbstractColorChooserPanel to add.
 420:    */
 421:   public void addChooserPanel(AbstractColorChooserPanel panel)
 422:   {
 423:     if (panel == null)
 424:       return;
 425:     AbstractColorChooserPanel[] old = chooserPanels;
 426:     AbstractColorChooserPanel[] newPanels =
 427:       new AbstractColorChooserPanel[(old == null) ? 1 : old.length + 1];
 428:     if (old != null)
 429:       System.arraycopy(old, 0, newPanels, 0, old.length);
 430:     newPanels[newPanels.length - 1] = panel;
 431:     chooserPanels = newPanels;
 432:     panel.installChooserPanel(this);
 433:     firePropertyChange(CHOOSER_PANELS_PROPERTY, old, newPanels);
 434:   } // addChooserPanel()
 435: 
 436:   /**
 437:    * This method removes the given AbstractColorChooserPanel from the
 438:    * JColorChooser's list of chooserPanels.
 439:    *
 440:    * @param panel The AbstractColorChooserPanel to remove.
 441:    *
 442:    * @return The AbstractColorChooserPanel that was removed.
 443:    */
 444:   public AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel panel)
 445:   {
 446:     int index = -1;
 447:     for (int i = 0; i < chooserPanels.length; i++)
 448:       if (panel == chooserPanels[i])
 449:         {
 450:           index = i;
 451:           break;
 452:         }
 453: 
 454:     if (index == -1)
 455:       return null;
 456: 
 457:     AbstractColorChooserPanel[] old = chooserPanels;
 458:     if (chooserPanels.length == 1)
 459:       chooserPanels = null;
 460:     else
 461:       {
 462:         AbstractColorChooserPanel[] newPanels =
 463:           new AbstractColorChooserPanel[chooserPanels.length - 1];
 464:         System.arraycopy(chooserPanels, 0, newPanels, 0, index);
 465:         System.arraycopy(chooserPanels, index, newPanels, index - 1,
 466:                          chooserPanels.length - index);
 467:         chooserPanels = newPanels;
 468:       }
 469:     panel.uninstallChooserPanel(this);
 470:     firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels);
 471:     return panel;
 472:   }
 473: 
 474:   /**
 475:    * This method sets the chooserPanels property for this JColorChooser.
 476:    *
 477:    * @param panels The new set of AbstractColorChooserPanels to use.
 478:    */
 479:   public void setChooserPanels(AbstractColorChooserPanel[] panels)
 480:   {
 481:     if (panels != chooserPanels)
 482:       {
 483:         if (chooserPanels != null)
 484:           for (int i = 0; i < chooserPanels.length; i++)
 485:             if (chooserPanels[i] != null)
 486:               chooserPanels[i].uninstallChooserPanel(this);
 487: 
 488:         AbstractColorChooserPanel[] old = chooserPanels;
 489:         chooserPanels = panels;
 490: 
 491:         if (panels != null)
 492:           for (int i = 0; i < panels.length; i++)
 493:             if (panels[i] != null)
 494:               panels[i].installChooserPanel(this);
 495: 
 496:         firePropertyChange(CHOOSER_PANELS_PROPERTY, old, chooserPanels);
 497:       }
 498:   } // setChooserPanels()
 499: 
 500:   /**
 501:    * This method returns the AbstractColorChooserPanels used with this
 502:    * JColorChooser.
 503:    *
 504:    * @return The AbstractColorChooserPanels used with this JColorChooser.
 505:    */
 506:   public AbstractColorChooserPanel[] getChooserPanels()
 507:   {
 508:     return chooserPanels;
 509:   } // getChooserPanels()
 510: 
 511:   /**
 512:    * This method returns the ColorSelectionModel used with this JColorChooser.
 513:    *
 514:    * @return The ColorSelectionModel.
 515:    */
 516:   public ColorSelectionModel getSelectionModel()
 517:   {
 518:     return selectionModel;
 519:   } // getSelectionModel()
 520: 
 521:   /**
 522:    * This method sets the ColorSelectionModel to be used with this
 523:    * JColorChooser.
 524:    *
 525:    * @param model The ColorSelectionModel to be used with this JColorChooser.
 526:    *
 527:    * @throws AWTError If the given model is null.
 528:    */
 529:   public void setSelectionModel(ColorSelectionModel model)
 530:   {
 531:     if (model == null)
 532:       throw new AWTError("ColorSelectionModel is not allowed to be null.");
 533:     selectionModel = model;
 534:   } // setSelectionModel()
 535: 
 536:   /**
 537:    * DOCUMENT ME!
 538:    *
 539:    * @return DOCUMENT ME!
 540:    */
 541:   public boolean getDragEnabled()
 542:   {
 543:     return dragEnabled;
 544:   }
 545: 
 546:   /**
 547:    * DOCUMENT ME!
 548:    *
 549:    * @param b DOCUMENT ME!
 550:    */
 551:   public void setDragEnabled(boolean b)
 552:   {
 553:     dragEnabled = b;
 554:   }
 555: 
 556:   /**
 557:    * This method returns a String describing the JColorChooser.
 558:    *
 559:    * @return A String describing the JColorChooser.
 560:    */
 561:   protected String paramString()
 562:   {
 563:     return "JColorChooser";
 564:   } // paramString()
 565: 
 566:   /**
 567:    * getAccessibleContext
 568:    *
 569:    * @return AccessibleContext
 570:    */
 571:   public AccessibleContext getAccessibleContext()
 572:   {
 573:     if (accessibleContext == null)
 574:       accessibleContext = new AccessibleJColorChooser();
 575: 
 576:     return accessibleContext;
 577:   }
 578: 
 579:   /**
 580:    * A helper class that hides a JDialog when the action is performed.
 581:    */
 582:   static class DefaultOKCancelListener implements ActionListener
 583:   {
 584:     /** The JDialog to hide. */
 585:     private JDialog dialog;
 586: 
 587:     /**
 588:      * Creates a new DefaultOKCancelListener with the given JDialog to hide.
 589:      *
 590:      * @param dialog The JDialog to hide.
 591:      */
 592:     public DefaultOKCancelListener(JDialog dialog)
 593:     {
 594:       super();
 595:       this.dialog = dialog;
 596:     }
 597: 
 598:     /**
 599:      * This method hides the JDialog when called.
 600:      *
 601:      * @param e The ActionEvent.
 602:      */
 603:     public void actionPerformed(ActionEvent e)
 604:     {
 605:       dialog.hide();
 606:     }
 607:   }
 608: 
 609:   /**
 610:    * This method resets the JColorChooser color to the initial color when the
 611:    * action is performed.
 612:    */
 613:   static class DefaultResetListener implements ActionListener
 614:   {
 615:     /** The JColorChooser to reset. */
 616:     private JColorChooser chooser;
 617: 
 618:     /** The initial color. */
 619:     private Color init;
 620: 
 621:     /**
 622:      * Creates a new DefaultResetListener with the given JColorChooser.
 623:      *
 624:      * @param chooser The JColorChooser to reset.
 625:      */
 626:     public DefaultResetListener(JColorChooser chooser)
 627:     {
 628:       super();
 629:       this.chooser = chooser;
 630:       init = chooser.getColor();
 631:     }
 632: 
 633:     /**
 634:      * This method resets the JColorChooser to its initial color.
 635:      *
 636:      * @param e The ActionEvent.
 637:      */
 638:     public void actionPerformed(ActionEvent e)
 639:     {
 640:       chooser.setColor(init);
 641:     }
 642:   }
 643: 
 644:   /**
 645:    * This is a custom JDialog that will notify when it is hidden and the modal
 646:    * property is set.
 647:    */
 648:   static class ModalDialog extends JDialog
 649:   {
 650:     /** The modal property. */
 651:     private boolean modal;
 652: 
 653:     /**
 654:      * Creates a new ModalDialog object with the given parent and title.
 655:      *
 656:      * @param parent The parent of the JDialog.
 657:      * @param title The title of the JDialog.
 658:      */
 659:     public ModalDialog(Frame parent, String title)
 660:     {
 661:       super(parent, title);
 662:     }
 663: 
 664:     /**
 665:      * Creates a new ModalDialog object with the given parent and title.
 666:      *
 667:      * @param parent The parent of the JDialog.
 668:      * @param title The title of the JDialog.
 669:      */
 670:     public ModalDialog(Dialog parent, String title)
 671:     {
 672:       super(parent, title);
 673:     }
 674: 
 675:     /**
 676:      * This method sets the modal property.
 677:      *
 678:      * @param modal The modal property.
 679:      */
 680:     public void setModal(boolean modal)
 681:     {
 682:       this.modal = modal;
 683:     }
 684: 
 685:     /**
 686:      * This method shows the ModalDialog.
 687:      */
 688:     public void show()
 689:     {
 690:       super.show();
 691:       if (modal)
 692:     makeModal(this);
 693:     }
 694: 
 695:     /**
 696:      * This method hides the ModalDialog.
 697:      */
 698:     public synchronized void hide()
 699:     {
 700:       super.hide();
 701:       notifyAll();
 702:     }
 703:   }
 704: }