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