001    /* ===========================================================
002     * JFreeChart : a free chart library for the Java(tm) platform
003     * ===========================================================
004     *
005     * (C) Copyright 2000-2009, by Object Refinery Limited and Contributors.
006     *
007     * Project Info:  http://www.jfree.org/jfreechart/index.html
008     *
009     * This library is free software; you can redistribute it and/or modify it
010     * under the terms of the GNU Lesser General Public License as published by
011     * the Free Software Foundation; either version 2.1 of the License, or
012     * (at your option) any later version.
013     *
014     * This library is distributed in the hope that it will be useful, but
015     * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016     * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017     * License for more details.
018     *
019     * You should have received a copy of the GNU Lesser General Public
020     * License along with this library; if not, write to the Free Software
021     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022     * USA.
023     *
024     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025     * in the United States and other countries.]
026     *
027     * -------------------
028     * GrayPaintScale.java
029     * -------------------
030     * (C) Copyright 2006-2009, by Object Refinery Limited.
031     *
032     * Original Author:  David Gilbert (for Object Refinery Limited);
033     * Contributor(s):   -;
034     *
035     * Changes
036     * -------
037     * 05-Jul-2006 : Version 1 (DG);
038     * 31-Jan-2007 : Renamed min and max to lowerBound and upperBound (DG);
039     * 26-Sep-2007 : Fixed bug 1767315, problem in getPaint() method (DG);
040     * 29-Jan-2009 : Added alpha transparency field and hashCode() method (DG);
041     *
042     */
043    
044    package org.jfree.chart.renderer;
045    
046    import java.awt.Color;
047    import java.awt.Paint;
048    import java.io.Serializable;
049    
050    import org.jfree.chart.HashUtilities;
051    import org.jfree.util.PublicCloneable;
052    
053    /**
054     * A paint scale that returns shades of gray.
055     *
056     * @since 1.0.4
057     */
058    public class GrayPaintScale
059            implements PaintScale, PublicCloneable, Serializable {
060    
061        /** The lower bound. */
062        private double lowerBound;
063    
064        /** The upper bound. */
065        private double upperBound;
066    
067        /**
068         * The alpha transparency (0-255).
069         *
070         * @since 1.0.13
071         */
072        private int alpha;
073    
074        /**
075         * Creates a new <code>GrayPaintScale</code> instance with default values.
076         */
077        public GrayPaintScale() {
078            this(0.0, 1.0);
079        }
080    
081        /**
082         * Creates a new paint scale for values in the specified range.
083         *
084         * @param lowerBound  the lower bound.
085         * @param upperBound  the upper bound.
086         *
087         * @throws IllegalArgumentException if <code>lowerBound</code> is not
088         *       less than <code>upperBound</code>.
089         */
090        public GrayPaintScale(double lowerBound, double upperBound) {
091            this(lowerBound, upperBound, 255);
092        }
093    
094        /**
095         * Creates a new paint scale for values in the specified range.
096         *
097         * @param lowerBound  the lower bound.
098         * @param upperBound  the upper bound.
099         * @param alpha  the alpha transparency (0-255).
100         *
101         * @throws IllegalArgumentException if <code>lowerBound</code> is not
102         *       less than <code>upperBound</code>, or <code>alpha</code> is not in
103         *       the range 0 to 255.
104         *
105         * @since 1.0.13
106         */
107        public GrayPaintScale(double lowerBound, double upperBound, int alpha) {
108            if (lowerBound >= upperBound) {
109                throw new IllegalArgumentException(
110                        "Requires lowerBound < upperBound.");
111            }
112            if (alpha < 0 || alpha > 255) {
113                throw new IllegalArgumentException(
114                        "Requires alpha in the range 0 to 255.");
115    
116            }
117            this.lowerBound = lowerBound;
118            this.upperBound = upperBound;
119            this.alpha = alpha;
120        }
121    
122        /**
123         * Returns the lower bound.
124         *
125         * @return The lower bound.
126         *
127         * @see #getUpperBound()
128         */
129        public double getLowerBound() {
130            return this.lowerBound;
131        }
132    
133        /**
134         * Returns the upper bound.
135         *
136         * @return The upper bound.
137         *
138         * @see #getLowerBound()
139         */
140        public double getUpperBound() {
141            return this.upperBound;
142        }
143    
144        /**
145         * Returns the alpha transparency that was specified in the constructor.
146         * 
147         * @return The alpha transparency (in the range 0 to 255).
148         * 
149         * @since 1.0.13
150         */
151        public int getAlpha() {
152            return this.alpha;
153        }
154    
155        /**
156         * Returns a paint for the specified value.
157         *
158         * @param value  the value (must be within the range specified by the
159         *         lower and upper bounds for the scale).
160         *
161         * @return A paint for the specified value.
162         */
163        public Paint getPaint(double value) {
164            double v = Math.max(value, this.lowerBound);
165            v = Math.min(v, this.upperBound);
166            int g = (int) ((v - this.lowerBound) / (this.upperBound
167                    - this.lowerBound) * 255.0);
168            // FIXME:  it probably makes sense to allocate an array of 256 Colors
169            // and lazily populate this array...
170            return new Color(g, g, g, this.alpha);
171        }
172    
173        /**
174         * Tests this <code>GrayPaintScale</code> instance for equality with an
175         * arbitrary object.  This method returns <code>true</code> if and only
176         * if:
177         * <ul>
178         * <li><code>obj</code> is not <code>null</code>;</li>
179         * <li><code>obj</code> is an instance of <code>GrayPaintScale</code>;</li>
180         * </ul>
181         *
182         * @param obj  the object (<code>null</code> permitted).
183         *
184         * @return A boolean.
185         */
186        public boolean equals(Object obj) {
187            if (obj == this) {
188                return true;
189            }
190            if (!(obj instanceof GrayPaintScale)) {
191                return false;
192            }
193            GrayPaintScale that = (GrayPaintScale) obj;
194            if (this.lowerBound != that.lowerBound) {
195                return false;
196            }
197            if (this.upperBound != that.upperBound) {
198                return false;
199            }
200            if (this.alpha != that.alpha) {
201                return false;
202            }
203            return true;
204        }
205    
206        /**
207         * Returns a hash code for this instance.
208         *
209         * @return A hash code.
210         */
211        public int hashCode() {
212            int hash = 7;
213            hash = HashUtilities.hashCode(hash, this.lowerBound);
214            hash = HashUtilities.hashCode(hash, this.upperBound);
215            hash = 43 * hash + this.alpha;
216            return hash;
217        }
218    
219        /**
220         * Returns a clone of this <code>GrayPaintScale</code> instance.
221         *
222         * @return A clone.
223         *
224         * @throws CloneNotSupportedException if there is a problem cloning this
225         *     instance.
226         */
227        public Object clone() throws CloneNotSupportedException {
228            return super.clone();
229        }
230    
231    }