1 /*
   2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javax.swing.plaf.basic;
  27 
  28 import javax.swing.*;
  29 import javax.swing.colorchooser.*;
  30 import javax.swing.event.*;
  31 import javax.swing.border.*;
  32 import javax.swing.plaf.*;
  33 import java.awt.*;
  34 import java.awt.event.*;
  35 import java.beans.PropertyChangeEvent;
  36 import java.beans.PropertyChangeListener;
  37 
  38 import sun.swing.DefaultLookup;
  39 
  40 /**
  41  * Provides the basic look and feel for a JColorChooser.
  42  * <p>
  43  * @author Tom Santos
  44  * @author Steve Wilson
  45  */
  46 
  47 public class BasicColorChooserUI extends ColorChooserUI
  48 {
  49     /**
  50      * JColorChooser this BasicColorChooserUI is installed on.
  51      *
  52      * @since 1.5
  53      */
  54     protected JColorChooser chooser;
  55 
  56     JTabbedPane tabbedPane;
  57     JPanel singlePanel;
  58 
  59     JPanel previewPanelHolder;
  60     JComponent previewPanel;
  61     boolean isMultiPanel = false;
  62     private static TransferHandler defaultTransferHandler = new ColorTransferHandler();
  63 
  64     protected AbstractColorChooserPanel[] defaultChoosers;
  65 
  66     protected ChangeListener previewListener;
  67     protected PropertyChangeListener propertyChangeListener;
  68     private Handler handler;
  69 
  70     public static ComponentUI createUI(JComponent c) {
  71         return new BasicColorChooserUI();
  72     }
  73 
  74     protected AbstractColorChooserPanel[] createDefaultChoosers() {
  75         AbstractColorChooserPanel[] panels = ColorChooserComponentFactory.getDefaultChooserPanels();
  76         return panels;
  77     }
  78 
  79     protected void uninstallDefaultChoosers() {
  80         AbstractColorChooserPanel[] choosers = chooser.getChooserPanels();
  81         for( int i = 0 ; i < choosers.length; i++) {
  82             chooser.removeChooserPanel( choosers[i] );
  83         }
  84     }
  85 
  86     public void installUI( JComponent c ) {
  87         chooser = (JColorChooser)c;
  88 
  89         super.installUI( c );
  90 
  91         installDefaults();
  92         installListeners();
  93 
  94         tabbedPane = new JTabbedPane();
  95         tabbedPane.setName("ColorChooser.tabPane");
  96         tabbedPane.setInheritsPopupMenu(true);
  97         tabbedPane.getAccessibleContext().setAccessibleDescription(tabbedPane.getName());
  98         singlePanel = new JPanel(new CenterLayout());
  99         singlePanel.setName("ColorChooser.panel");
 100         singlePanel.setInheritsPopupMenu(true);
 101 
 102         chooser.setLayout( new BorderLayout() );
 103 
 104         defaultChoosers = createDefaultChoosers();
 105         chooser.setChooserPanels(defaultChoosers);
 106 
 107         previewPanelHolder = new JPanel(new CenterLayout());
 108         previewPanelHolder.setName("ColorChooser.previewPanelHolder");
 109 
 110         if (DefaultLookup.getBoolean(chooser, this,
 111                                   "ColorChooser.showPreviewPanelText", true)) {
 112             String previewString = UIManager.getString(
 113                 "ColorChooser.previewText", chooser.getLocale());
 114             previewPanelHolder.setBorder(new TitledBorder(previewString));
 115         }
 116         previewPanelHolder.setInheritsPopupMenu(true);
 117 
 118         installPreviewPanel();
 119         chooser.applyComponentOrientation(c.getComponentOrientation());
 120     }
 121 
 122     public void uninstallUI( JComponent c ) {
 123         chooser.remove(tabbedPane);
 124         chooser.remove(singlePanel);
 125         chooser.remove(previewPanelHolder);
 126 
 127         uninstallDefaultChoosers();
 128         uninstallListeners();
 129         uninstallPreviewPanel();
 130         uninstallDefaults();
 131 
 132         previewPanelHolder = null;
 133         previewPanel = null;
 134         defaultChoosers = null;
 135         chooser = null;
 136         tabbedPane = null;
 137 
 138         handler = null;
 139     }
 140 
 141     protected void installPreviewPanel() {
 142         JComponent previewPanel = this.chooser.getPreviewPanel();
 143         if (previewPanel == null) {
 144             previewPanel = ColorChooserComponentFactory.getPreviewPanel();
 145         }
 146         else if (JPanel.class.equals(previewPanel.getClass()) && (0 == previewPanel.getComponentCount())) {
 147             previewPanel = null;
 148         }
 149         this.previewPanel = previewPanel;
 150         if (previewPanel != null) {
 151             chooser.add(previewPanelHolder, BorderLayout.SOUTH);
 152             previewPanel.setForeground(chooser.getColor());
 153             previewPanelHolder.add(previewPanel);
 154             previewPanel.addMouseListener(getHandler());
 155             previewPanel.setInheritsPopupMenu(true);
 156         }
 157     }
 158 
 159     /**
 160      * Removes installed preview panel from the UI delegate.
 161      *
 162      * @since 1.7
 163      */
 164     protected void uninstallPreviewPanel() {
 165         if (this.previewPanel != null) {
 166             this.previewPanel.removeMouseListener(getHandler());
 167             this.previewPanelHolder.remove(this.previewPanel);
 168         }
 169         this.chooser.remove(this.previewPanelHolder);
 170     }
 171 
 172     protected void installDefaults() {
 173         LookAndFeel.installColorsAndFont(chooser, "ColorChooser.background",
 174                                               "ColorChooser.foreground",
 175                                               "ColorChooser.font");
 176         LookAndFeel.installProperty(chooser, "opaque", Boolean.TRUE);
 177         TransferHandler th = chooser.getTransferHandler();
 178         if (th == null || th instanceof UIResource) {
 179             chooser.setTransferHandler(defaultTransferHandler);
 180         }
 181     }
 182 
 183     protected void uninstallDefaults() {
 184         if (chooser.getTransferHandler() instanceof UIResource) {
 185             chooser.setTransferHandler(null);
 186         }
 187     }
 188 
 189 
 190     protected void installListeners() {
 191         propertyChangeListener = createPropertyChangeListener();
 192         chooser.addPropertyChangeListener( propertyChangeListener );
 193 
 194         previewListener = getHandler();
 195         chooser.getSelectionModel().addChangeListener(previewListener);
 196     }
 197 
 198     private Handler getHandler() {
 199         if (handler == null) {
 200             handler = new Handler();
 201         }
 202         return handler;
 203     }
 204 
 205     protected PropertyChangeListener createPropertyChangeListener() {
 206         return getHandler();
 207     }
 208 
 209     protected void uninstallListeners() {
 210         chooser.removePropertyChangeListener( propertyChangeListener );
 211         chooser.getSelectionModel().removeChangeListener(previewListener);
 212         previewListener = null;
 213     }
 214 
 215     private void selectionChanged(ColorSelectionModel model) {
 216         JComponent previewPanel = this.chooser.getPreviewPanel();
 217         if (previewPanel != null) {
 218             previewPanel.setForeground(model.getSelectedColor());
 219             previewPanel.repaint();
 220         }
 221         AbstractColorChooserPanel[] panels = this.chooser.getChooserPanels();
 222         if (panels != null) {
 223             for (AbstractColorChooserPanel panel : panels) {
 224                 if (panel != null) {
 225                     panel.updateChooser();
 226                 }
 227             }
 228         }
 229     }
 230 
 231     private class Handler implements ChangeListener, MouseListener,
 232             PropertyChangeListener {
 233         //
 234         // ChangeListener
 235         //
 236         public void stateChanged(ChangeEvent evt) {
 237             selectionChanged((ColorSelectionModel) evt.getSource());
 238         }
 239 
 240         //
 241         // MouseListener
 242         public void mousePressed(MouseEvent evt) {
 243             if (chooser.getDragEnabled()) {
 244                 TransferHandler th = chooser.getTransferHandler();
 245                 th.exportAsDrag(chooser, evt, TransferHandler.COPY);
 246             }
 247         }
 248         public void mouseReleased(MouseEvent evt) {}
 249         public void mouseClicked(MouseEvent evt) {}
 250         public void mouseEntered(MouseEvent evt) {}
 251         public void mouseExited(MouseEvent evt) {}
 252 
 253         //
 254         // PropertyChangeListener
 255         //
 256         public void propertyChange(PropertyChangeEvent evt) {
 257             String prop = evt.getPropertyName();
 258 
 259             if (prop == JColorChooser.CHOOSER_PANELS_PROPERTY) {
 260                 AbstractColorChooserPanel[] oldPanels =
 261                     (AbstractColorChooserPanel[])evt.getOldValue();
 262                 AbstractColorChooserPanel[] newPanels =
 263                     (AbstractColorChooserPanel[])evt.getNewValue();
 264 
 265                 for (int i = 0; i < oldPanels.length; i++) {  // remove old panels
 266                    Container wrapper = oldPanels[i].getParent();
 267                     if (wrapper != null) {
 268                       Container parent = wrapper.getParent();
 269                       if (parent != null)
 270                           parent.remove(wrapper);  // remove from hierarchy
 271                       oldPanels[i].uninstallChooserPanel(chooser); // uninstall
 272                     }
 273                 }
 274 
 275                 int numNewPanels = newPanels.length;
 276                 if (numNewPanels == 0) {  // removed all panels and added none
 277                     chooser.remove(tabbedPane);
 278                     return;
 279                 }
 280                 else if (numNewPanels == 1) {  // one panel case
 281                     chooser.remove(tabbedPane);
 282                     JPanel centerWrapper = new JPanel( new CenterLayout() );
 283                     centerWrapper.setInheritsPopupMenu(true);
 284                     centerWrapper.add(newPanels[0]);
 285                     singlePanel.add(centerWrapper, BorderLayout.CENTER);
 286                     chooser.add(singlePanel);
 287                 }
 288                 else {   // multi-panel case
 289                     if ( oldPanels.length < 2 ) {// moving from single to multiple
 290                         chooser.remove(singlePanel);
 291                         chooser.add(tabbedPane, BorderLayout.CENTER);
 292                     }
 293 
 294                     for (int i = 0; i < newPanels.length; i++) {
 295                         JPanel centerWrapper = new JPanel( new CenterLayout() );
 296                         centerWrapper.setInheritsPopupMenu(true);
 297                         String name = newPanels[i].getDisplayName();
 298                         int mnemonic = newPanels[i].getMnemonic();
 299                         centerWrapper.add(newPanels[i]);
 300                         tabbedPane.addTab(name, centerWrapper);
 301                         if (mnemonic > 0) {
 302                             tabbedPane.setMnemonicAt(i, mnemonic);
 303                             int index = newPanels[i].getDisplayedMnemonicIndex();
 304                             if (index >= 0) {
 305                                 tabbedPane.setDisplayedMnemonicIndexAt(i, index);
 306                             }
 307                         }
 308                     }
 309                 }
 310                 chooser.applyComponentOrientation(chooser.getComponentOrientation());
 311                 for (int i = 0; i < newPanels.length; i++) {
 312                     newPanels[i].installChooserPanel(chooser);
 313                 }
 314             }
 315             else if (prop == JColorChooser.PREVIEW_PANEL_PROPERTY) {
 316                 uninstallPreviewPanel();
 317                 installPreviewPanel();
 318             }
 319             else if (prop == JColorChooser.SELECTION_MODEL_PROPERTY) {
 320                 ColorSelectionModel oldModel = (ColorSelectionModel) evt.getOldValue();
 321                 oldModel.removeChangeListener(previewListener);
 322                 ColorSelectionModel newModel = (ColorSelectionModel) evt.getNewValue();
 323                 newModel.addChangeListener(previewListener);
 324                 selectionChanged(newModel);
 325             }
 326             else if (prop == "componentOrientation") {
 327                 ComponentOrientation o =
 328                     (ComponentOrientation)evt.getNewValue();
 329                 JColorChooser cc = (JColorChooser)evt.getSource();
 330                 if (o != (ComponentOrientation)evt.getOldValue()) {
 331                     cc.applyComponentOrientation(o);
 332                     cc.updateUI();
 333                 }
 334             }
 335         }
 336     }
 337 
 338     /**
 339      * This class should be treated as a &quot;protected&quot; inner class.
 340      * Instantiate it only within subclasses of {@code BasicColorChooserUI}.
 341      */
 342     public class PropertyHandler implements PropertyChangeListener {
 343         public void propertyChange(PropertyChangeEvent e) {
 344             getHandler().propertyChange(e);
 345         }
 346     }
 347 
 348     static class ColorTransferHandler extends TransferHandler implements UIResource {
 349 
 350         ColorTransferHandler() {
 351             super("color");
 352         }
 353     }
 354 }