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:       // Nothing to do here.
  91:     }
  92: 
  93:     /**
  94:      * getAccessibleRole
  95:      *
  96:      * @return AccessibleRole
  97:      */
  98:     public AccessibleRole getAccessibleRole()
  99:     {
 100:       return AccessibleRole.COLOR_CHOOSER;
 101:     } // getAccessibleRole()
 102:   } // AccessibleJColorChooser
 103: 
 104:   /** The model used with the JColorChooser. */
 105:   private ColorSelectionModel selectionModel;
 106: 
 107:   /** The preview panel associated with the JColorChooser. */
 108:   private JComponent previewPanel;
 109: 
 110:   /**
 111:    * The set of AbstractColorChooserPanels associated with the JColorChooser.
 112:    */
 113:   private AbstractColorChooserPanel[] chooserPanels;
 114: 
 115:   /** A Drag and Drop property. */
 116:   private boolean dragEnabled;
 117: 
 118:   /**
 119:    * The property fired by the JColorChooser when the selectionModel property
 120:    * changes.
 121:    */
 122:   public static final String SELECTION_MODEL_PROPERTY = "selectionModel";
 123: 
 124:   /**
 125:    * The property fired by the JColorChooser when the previewPanel property
 126:    * changes.
 127:    */
 128:   public static final String PREVIEW_PANEL_PROPERTY = "previewPanel";
 129: 
 130:   /**
 131:    * The property fired by the JColorChooser when the chooserPanels property
 132:    * changes.
 133:    */
 134:   public static final String CHOOSER_PANELS_PROPERTY = "chooserPanels";
 135: 
 136:   /** accessibleContext */
 137:   protected AccessibleContext accessibleContext;
 138: 
 139:   /**
 140:    * This method creates a new JColorChooser with the default initial color.
 141:    */
 142:   public JColorChooser()
 143:   {
 144:     this(new DefaultColorSelectionModel());
 145:   } // JColorChooser()
 146: 
 147:   /**
 148:    * This method creates a new JColorChooser with the given initial color.
 149:    *
 150:    * @param initial The initial color.
 151:    */
 152:   public JColorChooser(Color initial)
 153:   {
 154:     this(new DefaultColorSelectionModel(initial));
 155:   } // JColorChooser()
 156: 
 157:   /**
 158:    * This method creates a new JColorChooser with the given model. The model
 159:    * will dictate what the initial color for the JColorChooser is.
 160:    *
 161:    * @param model The Model to use with the JColorChooser.
 162:    */
 163:   public JColorChooser(ColorSelectionModel model)
 164:   {
 165:     if (model == null)
 166:       model = new DefaultColorSelectionModel();
 167:     selectionModel = model;
 168:     updateUI();
 169:   } // JColorChooser()
 170: 
 171:   /**
 172:    * This method sets the current color for the JColorChooser.
 173:    *
 174:    * @param color The new color for the JColorChooser.
 175:    */
 176:   public void setColor(Color color)
 177:   {
 178:     if (color != null)
 179:       selectionModel.setSelectedColor(color);
 180:   } // setColor()
 181: 
 182:   /**
 183:    * This method sets the current color for the JColorChooser using RGB
 184:    * values.
 185:    *
 186:    * @param r The red value.
 187:    * @param g The green value.
 188:    * @param b The blue value.
 189:    */
 190:   public void setColor(int r, int g, int b)
 191:   {
 192:     selectionModel.setSelectedColor(new Color(r, g, b));
 193:   } // setColor()
 194: 
 195:   /**
 196:    * This method sets the current color for the JColorChooser using the
 197:    * integer value. Bits 0-7 represent the blue value. Bits 8-15 represent
 198:    * the green value. Bits 16-23 represent the red value.
 199:    *
 200:    * @param color The new current color of the JColorChooser.
 201:    */
 202:   public void setColor(int color)
 203:   {
 204:     setColor(new Color(color, false));
 205:   } // setColor()
 206: 
 207:   /**
 208:    * This method shows a JColorChooser inside a JDialog. The JDialog will
 209:    * block until it is hidden. The JDialog comes with three buttons: OK,
 210:    * Cancel, and Reset. Pressing OK or Cancel hide the JDialog. Pressing
 211:    * Reset will reset the JColorChooser to its initial value.
 212:    *
 213:    * @param component The Component that parents the JDialog.
 214:    * @param title The title displayed in the JDialog.
 215:    * @param initial The initial color.
 216:    *
 217:    * @return The selected color.
 218:    */
 219:   public static Color showDialog(Component component, String title,
 220:                                  Color initial)
 221:   {
 222:     JColorChooser choose = new JColorChooser(initial);
 223: 
 224:     JDialog dialog = createDialog(component, title, true, choose, null, null);
 225: 
 226:     dialog.getContentPane().add(choose);
 227:     dialog.pack();
 228:     dialog.show();
 229: 
 230:     return choose.getColor();
 231:   } // showDialog()
 232: 
 233:   /**
 234:    * This is a helper method to make the given JDialog block until it is
 235:    * hidden.  This is package-private to avoid an accessor method.
 236:    *
 237:    * @param dialog The JDialog to block.
 238:    */
 239:   static void makeModal(JDialog dialog)
 240:   {
 241:     try
 242:       {
 243:         synchronized (dialog)
 244:           {
 245:             while (dialog.isVisible())
 246:               dialog.wait();
 247:           }
 248:       }
 249:     catch (InterruptedException e)
 250:       {
 251:         // TODO: Should this be handled?
 252:       }
 253:   }
 254: 
 255:   /**
 256:    * This is a helper method to find the first Frame or Dialog ancestor of the
 257:    * given Component.
 258:    *
 259:    * @param c The Component to find ancestors for.
 260:    *
 261:    * @return A Frame or Dialog ancestor. Null if none are found.
 262:    */
 263:   private static Component findParent(Component c)
 264:   {
 265:     Component parent = SwingUtilities.getAncestorOfClass(Frame.class, c);
 266:     if (parent != null)
 267:       return parent;
 268:     parent = SwingUtilities.getAncestorOfClass(Dialog.class, c);
 269:     return parent;
 270:   }
 271: 
 272:   /**
 273:    * This method will take the given JColorChooser and place it in a JDialog
 274:    * with the given modal property. Three buttons are displayed in the
 275:    * JDialog: OK, Cancel and Reset. If OK or Cancel are pressed, the JDialog
 276:    * is hidden. If Reset is pressed, then the JColorChooser will take on its
 277:    * default color value. The given okListener will be registered to the OK
 278:    * button and the cancelListener will be registered to the Cancel button.
 279:    * If the modal property is set, then the JDialog will block until it is
 280:    * hidden.
 281:    *
 282:    * @param component The Component that will parent the JDialog.
 283:    * @param title The title displayed in the JDialog.
 284:    * @param modal The modal property.
 285:    * @param chooserPane The JColorChooser to place in the JDialog.
 286:    * @param okListener The ActionListener to register to the OK button.
 287:    * @param cancelListener The ActionListener to register to the Cancel
 288:    *        button.
 289:    *
 290:    * @return A JDialog with the JColorChooser inside of it.
 291:    *
 292:    * @throws AWTError If the component is not a suitable parent.
 293:    */
 294:   public static JDialog createDialog(Component component, String title,
 295:                                      boolean modal, JColorChooser chooserPane,
 296:                                      ActionListener okListener,
 297:                                      ActionListener cancelListener)
 298:   {
 299:     Component parent = findParent(component);
 300:     if (parent == null)
 301:       throw new AWTError("No suitable parent found for Component.");
 302:     JDialog dialog;
 303:     if (parent instanceof Frame)
 304:       dialog = new JDialog((Frame) parent, title, true);
 305:     else
 306:       dialog = new JDialog((Dialog) parent, title, true);
 307: 
 308:     dialog.getContentPane().setLayout(new BorderLayout());
 309: 
 310:     JPanel panel = new JPanel();
 311:     panel.setLayout(new FlowLayout());
 312: 
 313:     ActionListener al = new DefaultOKCancelListener(dialog);
 314: 
 315:     JButton ok = new JButton("OK");
 316:     ok.addActionListener(okListener);
 317:     ok.addActionListener(al);
 318: 
 319:     JButton cancel = new JButton("Cancel");
 320:     cancel.addActionListener(cancelListener);
 321:     cancel.addActionListener(al);
 322: 
 323:     JButton reset = new JButton("Reset");
 324:     reset.addActionListener(new DefaultResetListener(chooserPane));
 325: 
 326:     dialog.getContentPane().add(chooserPane, BorderLayout.NORTH);
 327: 
 328:     panel.add(ok);
 329:     panel.add(cancel);
 330:     panel.add(reset);
 331: 
 332:     dialog.getContentPane().add(panel, BorderLayout.SOUTH);
 333: 
 334:     return dialog;
 335:   } // createDialog()
 336: 
 337:   /**
 338:    * This method returns the UI Component used for this JColorChooser.
 339:    *
 340:    * @return The UI Component for this JColorChooser.
 341:    */
 342:   public ColorChooserUI getUI()
 343:   {
 344:     return (ColorChooserUI) ui;
 345:   } // getUI()
 346: 
 347:   /**
 348:    * This method sets the UI Component used for this JColorChooser.
 349:    *
 350:    * @param ui The UI Component to use with this JColorChooser.
 351:    */
 352:   public void setUI(ColorChooserUI ui)
 353:   {
 354:     super.setUI(ui);
 355:   } // setUI()
 356: 
 357:   /**
 358:    * This method resets the UI Component property to the Look and Feel
 359:    * default.
 360:    */
 361:   public void updateUI()
 362:   {
 363:     setUI((ColorChooserUI) UIManager.getUI(this));
 364:   }
 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: }