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