001/* ===========================================================
002 * Orson Charts : a 3D chart library for the Java(tm) platform
003 * ===========================================================
004 * 
005 * (C)opyright 2013-2022, by David Gilbert.  All rights reserved.
006 * 
007 * https://github.com/jfree/orson-charts
008 * 
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as published by
011 * the Free Software Foundation, either version 3 of the License, or
012 * (at your option) any later version.
013 *
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 *
019 * You should have received a copy of the GNU General Public License
020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
021 * 
022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
023 * Other names may be trademarks of their respective owners.]
024 * 
025 * If you do not wish to be bound by the terms of the GPL, an alternative
026 * commercial license can be purchased.  For details, please see visit the
027 * Orson Charts home page:
028 * 
029 * http://www.object-refinery.com/orsoncharts/index.html
030 * 
031 */
032
033package org.jfree.chart3d.plot;
034
035import java.awt.Color;
036import java.io.Serializable;
037import java.util.Arrays;
038
039import org.jfree.chart3d.internal.Args;
040import org.jfree.chart3d.Colors;
041import org.jfree.chart3d.data.DefaultKeyedValues;
042
043/**
044 * A standard implementation of the {@link ColorSource} interface.
045 * <br><br>
046 * NOTE: This class is serializable, but the serialization format is subject 
047 * to change in future releases and should not be relied upon for persisting 
048 * instances of this class.
049 */
050@SuppressWarnings("serial")
051public final class StandardColorSource<K extends Comparable<K>>
052        implements ColorSource<K>, Serializable {
053
054    /** 
055     * An array of standard colors from which a color will be assigned if
056     * there is not one already stored for a given key. 
057     */
058    private Color[] standardColors;
059    
060    /** Storage for the colors assigned to keys. */
061    private DefaultKeyedValues<K, Color> colors;
062    
063    /**
064     * Creates a new instance with default colors.
065     */
066    public StandardColorSource() {
067        this(Colors.getDefaultColors());
068    }
069    
070    /**
071     * Creates a new instance with the supplied sequence of colors.  The
072     * supplied array must have at least one entry, and all entries must be
073     * non-{@code null}.
074     * 
075     * @param colors  the colors ({@code null} not permitted). 
076     */
077    public StandardColorSource(Color... colors) {
078        Args.nullNotPermitted(colors, "colors");
079        if (colors.length == 0) {
080            throw new IllegalArgumentException(
081                    "Zero length array not permitted.");
082        }
083        for (Color c: colors) {
084            if (c == null) { 
085                throw new IllegalArgumentException(
086                        "Null array entries not permitted.");
087            }
088        }
089        this.standardColors = colors.clone();
090        this.colors = new DefaultKeyedValues<>();
091    }
092 
093    /**
094     * Returns the color associated with the specified key.
095     * 
096     * @param key  the key ({@code null} not permitted).
097     * 
098     * @return The color (never {@code null}). 
099     */
100    @Override
101    public Color getColor(K key) {
102        // defer argument check
103        Color c = this.colors.getValue(key);
104        if (c != null) {
105            return c;
106        }
107        c = this.standardColors[this.colors.getItemCount() 
108                % this.standardColors.length];
109        this.colors.put(key, c);
110        return c;
111    }
112
113    /**
114     * Sets the color for the specified key.
115     * 
116     * @param key  the key ({@code null} not permitted).
117     * @param color  the color ({@code null} permitted).
118     */
119    @Override
120    public void setColor(K key, Color color) {
121        if (color != null) {
122            this.colors.put(key, color);
123        } else {
124            this.colors.remove(key);
125        }
126    }
127    
128    /**
129     * Clears existing color settings and sets the default colors to the 
130     * supplied value.  This method is used by the framework and is not
131     * normally called by client code.
132     * 
133     * @param colors  the colors ({@code null} not permitted).
134     * 
135     * @since 1.2
136     */
137    @Override
138    public void style(Color... colors) {
139        this.standardColors = colors;
140        this.colors.clear();
141    }
142
143    /**
144     * Tests this paint source for equality with an arbitrary object.
145     * 
146     * @param obj  the object ({@code null} permitted).
147     * 
148     * @return A boolean. 
149     */
150    @Override
151    public boolean equals(Object obj) {
152        if (obj == this) {
153            return true;
154        }
155        if (!(obj instanceof StandardColorSource)) {
156            return false;
157        }
158        StandardColorSource that = (StandardColorSource) obj;
159        if (!Arrays.equals(this.standardColors, that.standardColors)) {
160            return false;
161        }
162        if (!this.colors.equals(that.colors)) {
163            return false;
164        }
165        return true;
166    }
167
168}