1 /*
   2  * Copyright (c) 1998, 2014, 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.colorchooser;
  27 
  28 import java.awt.*;
  29 import java.beans.PropertyChangeEvent;
  30 import java.beans.PropertyChangeListener;
  31 import javax.swing.*;
  32 
  33 /**
  34  * This is the abstract superclass for color choosers.  If you want to add
  35  * a new color chooser panel into a <code>JColorChooser</code>, subclass
  36  * this class.
  37  * <p>
  38  * <strong>Warning:</strong>
  39  * Serialized objects of this class will not be compatible with
  40  * future Swing releases. The current serialization support is
  41  * appropriate for short term storage or RMI between applications running
  42  * the same version of Swing.  As of 1.4, support for long term storage
  43  * of all JavaBeans&trade;
  44  * has been added to the <code>java.beans</code> package.
  45  * Please see {@link java.beans.XMLEncoder}.
  46  *
  47  * @author Tom Santos
  48  * @author Steve Wilson
  49  */
  50 @SuppressWarnings("serial") // Same-version serialization only
  51 public abstract class AbstractColorChooserPanel extends JPanel {
  52 
  53 
  54     /**
  55      * Identifies that the transparency of the color (alpha value) can be
  56      * selected
  57      */
  58     public static final String TRANSPARENCY_ENABLED_PROPERTY
  59             = "TransparencyEnabled";
  60 
  61     private final PropertyChangeListener enabledListener = new PropertyChangeListener() {
  62         public void propertyChange(PropertyChangeEvent event) {
  63             Object value = event.getNewValue();
  64             if (value instanceof Boolean) {
  65                 setEnabled((Boolean) value);
  66             }
  67         }
  68     };
  69 
  70     /**
  71      *
  72      */
  73     private JColorChooser chooser;
  74 
  75     /**
  76       * Invoked automatically when the model's state changes.
  77       * It is also called by <code>installChooserPanel</code> to allow
  78       * you to set up the initial state of your chooser.
  79       * Override this method to update your <code>ChooserPanel</code>.
  80       */
  81     public abstract void updateChooser();
  82 
  83     /**
  84      * Builds a new chooser panel.
  85      */
  86     protected abstract void buildChooser();
  87 
  88     /**
  89      * Returns a string containing the display name of the panel.
  90      * @return the name of the display panel
  91      */
  92     public abstract String getDisplayName();
  93 
  94     /**
  95      * Provides a hint to the look and feel as to the
  96      * <code>KeyEvent.VK</code> constant that can be used as a mnemonic to
  97      * access the panel. A return value &lt;= 0 indicates there is no mnemonic.
  98      * <p>
  99      * The return value here is a hint, it is ultimately up to the look
 100      * and feel to honor the return value in some meaningful way.
 101      * <p>
 102      * This implementation returns 0, indicating the
 103      * <code>AbstractColorChooserPanel</code> does not support a mnemonic,
 104      * subclasses wishing a mnemonic will need to override this.
 105      *
 106      * @return KeyEvent.VK constant identifying the mnemonic; &lt;= 0 for no
 107      *         mnemonic
 108      * @see #getDisplayedMnemonicIndex
 109      * @since 1.4
 110      */
 111     public int getMnemonic() {
 112         return 0;
 113     }
 114 
 115     /**
 116      * Provides a hint to the look and feel as to the index of the character in
 117      * <code>getDisplayName</code> that should be visually identified as the
 118      * mnemonic. The look and feel should only use this if
 119      * <code>getMnemonic</code> returns a value &gt; 0.
 120      * <p>
 121      * The return value here is a hint, it is ultimately up to the look
 122      * and feel to honor the return value in some meaningful way. For example,
 123      * a look and feel may wish to render each
 124      * <code>AbstractColorChooserPanel</code> in a <code>JTabbedPane</code>,
 125      * and further use this return value to underline a character in
 126      * the <code>getDisplayName</code>.
 127      * <p>
 128      * This implementation returns -1, indicating the
 129      * <code>AbstractColorChooserPanel</code> does not support a mnemonic,
 130      * subclasses wishing a mnemonic will need to override this.
 131      *
 132      * @return Character index to render mnemonic for; -1 to provide no
 133      *                   visual identifier for this panel.
 134      * @see #getMnemonic
 135      * @since 1.4
 136      */
 137     public int getDisplayedMnemonicIndex() {
 138         return -1;
 139     }
 140 
 141     /**
 142      * Returns the small display icon for the panel.
 143      * @return the small display icon
 144      */
 145     public abstract Icon getSmallDisplayIcon();
 146 
 147     /**
 148      * Returns the large display icon for the panel.
 149      * @return the large display icon
 150      */
 151     public abstract Icon getLargeDisplayIcon();
 152 
 153     /**
 154      * Invoked when the panel is added to the chooser.
 155      * If you override this, be sure to call <code>super</code>.
 156      *
 157      * @param enclosingChooser the chooser to which the panel is to be added
 158      * @exception RuntimeException  if the chooser panel has already been
 159      *                          installed
 160      */
 161     public void installChooserPanel(JColorChooser enclosingChooser) {
 162         if (chooser != null) {
 163             throw new RuntimeException ("This chooser panel is already installed");
 164         }
 165         chooser = enclosingChooser;
 166         chooser.addPropertyChangeListener("enabled", enabledListener);
 167         setEnabled(chooser.isEnabled());
 168         buildChooser();
 169         updateChooser();
 170     }
 171 
 172     /**
 173      * Invoked when the panel is removed from the chooser.
 174      * If override this, be sure to call <code>super</code>.
 175      *
 176      * @param enclosingChooser the chooser from which the panel is to be removed
 177      */
 178   public void uninstallChooserPanel(JColorChooser enclosingChooser) {
 179         chooser.removePropertyChangeListener("enabled", enabledListener);
 180         chooser = null;
 181     }
 182 
 183     /**
 184       * Returns the model that the chooser panel is editing.
 185       * @return the <code>ColorSelectionModel</code> model this panel
 186       *         is editing
 187       */
 188     public ColorSelectionModel getColorSelectionModel() {
 189         return (this.chooser != null)
 190                 ? this.chooser.getSelectionModel()
 191                 : null;
 192     }
 193 
 194     /**
 195      * Returns the color that is currently selected.
 196      * @return the <code>Color</code> that is selected
 197      */
 198     protected Color getColorFromModel() {
 199         ColorSelectionModel model = getColorSelectionModel();
 200         return (model != null)
 201                 ? model.getSelectedColor()
 202                 : null;
 203     }
 204 
 205     void setSelectedColor(Color color) {
 206         ColorSelectionModel model = getColorSelectionModel();
 207         if (model != null) {
 208             model.setSelectedColor(color);
 209         }
 210     }
 211 
 212     /**
 213      * Sets whether color chooser panel allows to select the transparency
 214      * (alpha value) of a color.
 215      * This method fires a property-changed event, using the string value of
 216      * {@code TRANSPARENCY_ENABLED_PROPERTY} as the name
 217      * of the property.
 218      *
 219      * <p>The value is a hint and may not be applicable to all types of chooser
 220      * panel.
 221      *
 222      * <p>The default value is {@code true}.
 223      *
 224      * @param b true if the transparency of a color can be selected
 225      *
 226      * @beaninfo
 227      *       bound: true
 228      * description: Sets the transparency of a color selection on or off.
 229      *
 230      * @see #isColorTransparencySelectionEnabled()
 231      */
 232     public void setColorTransparencySelectionEnabled(boolean b){
 233     }
 234 
 235     /**
 236      * Gets whether color chooser panel allows to select the transparency
 237      * (alpha value) of a color.
 238      *
 239      * @return true if the transparency of a color can be selected
 240      * @see #setColorTransparencySelectionEnabled(boolean)
 241      */
 242     public boolean isColorTransparencySelectionEnabled(){
 243         return true;
 244     }
 245 
 246     /**
 247      * Draws the panel.
 248      * @param g  the <code>Graphics</code> object
 249      */
 250     public void paint(Graphics g) {
 251         super.paint(g);
 252     }
 253 
 254     /**
 255      * Returns an integer from the defaults table. If <code>key</code> does
 256      * not map to a valid <code>Integer</code>, <code>default</code> is
 257      * returned.
 258      *
 259      * @param key  an <code>Object</code> specifying the int
 260      * @param defaultValue Returned value if <code>key</code> is not available,
 261      *                     or is not an Integer
 262      * @return the int
 263      */
 264     int getInt(Object key, int defaultValue) {
 265         Object value = UIManager.get(key, getLocale());
 266 
 267         if (value instanceof Integer) {
 268             return ((Integer)value).intValue();
 269         }
 270         if (value instanceof String) {
 271             try {
 272                 return Integer.parseInt((String)value);
 273             } catch (NumberFormatException nfe) {}
 274         }
 275         return defaultValue;
 276     }
 277 }