    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2008, 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     * ColorBar.java
    029     * -------------
    030     * (C) Copyright 2002-2008, by David M. O'Donnell and Contributors.
    031     *
    032     * Original Author:  David M. O'Donnell;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *
    035     * Changes
    036     * -------
    037     * 26-Nov-2002 : Version 1 contributed by David M. O'Donnell (DG);
    038     * 14-Jan-2003 : Changed autoRangeMinimumSize from Number --> double (DG);
    039     * 17-Jan-2003 : Moved plot classes to separate package (DG);
    040     * 20-Jan-2003 : Removed unnecessary constructors (DG);
    041     * 26-Mar-2003 : Implemented Serializable (DG);
    042     * 09-Jul-2003 : Changed ColorBar from extending axis classes to enclosing
    043     *               them (DG);
    044     * 05-Aug-2003 : Applied changes in bug report 780298 (DG);
    045     * 14-Aug-2003 : Implemented Cloneable (DG);
    046     * 08-Sep-2003 : Changed ValueAxis API (DG);
    047     * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
    048     * ------------- JFREECHART 1.0.x ---------------------------------------------
    049     * 31-Jan-2007 : Deprecated (DG);
    050     *
    051     */
    052
    053    package org.jfree.chart.axis;
    054
    055    import java.awt.BasicStroke;
    056    import java.awt.Graphics2D;
    057    import java.awt.Paint;
    058    import java.awt.RenderingHints;
    059    import java.awt.Stroke;
    060    import java.awt.geom.Line2D;
    061    import java.awt.geom.Rectangle2D;
    062    import java.io.Serializable;
    063
    064    import org.jfree.chart.plot.ColorPalette;
    065    import org.jfree.chart.plot.ContourPlot;
    066    import org.jfree.chart.plot.Plot;
    067    import org.jfree.chart.plot.RainbowPalette;
    068    import org.jfree.chart.plot.XYPlot;
    069    import org.jfree.chart.renderer.xy.XYBlockRenderer;
    070    import org.jfree.ui.RectangleEdge;
    071
    072    /**
    073     * A color bar.
    074     *
    075     * @deprecated This class is no longer supported (as of version 1.0.4).  If
    076     *     you are creating contour plots, please try to use {@link XYPlot} and
    077     *     {@link XYBlockRenderer}.
    078     */
    079    public class ColorBar implements Cloneable, Serializable {
    080
    081        /** For serialization. */
    082        private static final long serialVersionUID = -2101776212647268103L;
    083
    084        /** The default color bar thickness. */
    085        public static final int DEFAULT_COLORBAR_THICKNESS = 0;
    086
    087        /** The default color bar thickness percentage. */
    088        public static final double DEFAULT_COLORBAR_THICKNESS_PERCENT = 0.10;
    089
    090        /** The default outer gap. */
    091        public static final int DEFAULT_OUTERGAP = 2;
    092
    093        /** The axis. */
    094        private ValueAxis axis;
    095
    096        /** The color bar thickness. */
    097        private int colorBarThickness = DEFAULT_COLORBAR_THICKNESS;
    098
    099        /**
    100         * The color bar thickness as a percentage of the height of the data area.
    101         */
    102        private double colorBarThicknessPercent
    103                = DEFAULT_COLORBAR_THICKNESS_PERCENT;
    104
    105        /** The color palette. */
    106        private ColorPalette colorPalette = null;
    107
    108        /** The color bar length. */
    109        private int colorBarLength = 0; // default make height of plotArea
    110
    111        /** The amount of blank space around the colorbar. */
    112        private int outerGap;
    113
    114        /**
    115         * Constructs a horizontal colorbar axis, using default values where
    116         * necessary.
    117         *
    118         * @param label  the axis label.
    119         */
    120        public ColorBar(String label) {
    121
    122            NumberAxis a = new NumberAxis(label);
    123            a.setAutoRangeIncludesZero(false);
    124            this.axis = a;
    125            this.axis.setLowerMargin(0.0);
    126            this.axis.setUpperMargin(0.0);
    127
    128            this.colorPalette = new RainbowPalette();
    129            this.colorBarThickness = DEFAULT_COLORBAR_THICKNESS;
    130            this.colorBarThicknessPercent = DEFAULT_COLORBAR_THICKNESS_PERCENT;
    131            this.outerGap = DEFAULT_OUTERGAP;
    132            this.colorPalette.setMinZ(this.axis.getRange().getLowerBound());
    133            this.colorPalette.setMaxZ(this.axis.getRange().getUpperBound());
    134
    135        }
    136
    137        /**
    138         * Configures the color bar.
    139         *
    140         * @param plot  the plot.
    141         */
    142        public void configure(ContourPlot plot) {
    143            double minZ = plot.getDataset().getMinZValue();
    144            double maxZ = plot.getDataset().getMaxZValue();
    145            setMinimumValue(minZ);
    146            setMaximumValue(maxZ);
    147        }
    148
    149        /**
    150         * Returns the axis.
    151         *
    152         * @return The axis.
    153         */
    154        public ValueAxis getAxis() {
    155            return this.axis;
    156        }
    157
    158        /**
    159         * Sets the axis.
    160         *
    161         * @param axis  the axis.
    162         */
    163        public void setAxis(ValueAxis axis) {
    164            this.axis = axis;
    165        }
    166
    167        /**
    168         * Rescales the axis to ensure that all data are visible.
    169         */
    170        public void autoAdjustRange() {
    171            this.axis.autoAdjustRange();
    172            this.colorPalette.setMinZ(this.axis.getLowerBound());
    173            this.colorPalette.setMaxZ(this.axis.getUpperBound());
    174        }
    175
    176        /**
    177         * Draws the plot on a Java 2D graphics device (such as the screen or a
    178         * printer).
    179         *
    180         * @param g2  the graphics device.
    181         * @param cursor  the cursor.
    182         * @param plotArea  the area within which the chart should be drawn.
    183         * @param dataArea  the area within which the plot should be drawn (a
    184         *                  subset of the drawArea).
    185         * @param reservedArea  the reserved area.
    186         * @param edge  the color bar location.
    187         *
    188         * @return The new cursor location.
    189         */
    190        public double draw(Graphics2D g2, double cursor,
    191                           Rectangle2D plotArea, Rectangle2D dataArea,
    192                           Rectangle2D reservedArea, RectangleEdge edge) {
    193
    194
    195            Rectangle2D colorBarArea = null;
    196
    197            double thickness = calculateBarThickness(dataArea, edge);
    198            if (this.colorBarThickness > 0) {
    199                thickness = this.colorBarThickness;  // allow fixed thickness
    200            }
    201
    202            double length = 0.0;
    203            if (RectangleEdge.isLeftOrRight(edge)) {
    204                length = dataArea.getHeight();
    205            }
    206            else {
    207                length = dataArea.getWidth();
    208            }
    209
    210            if (this.colorBarLength > 0) {
    211                length = this.colorBarLength;
    212            }
    213
    214            if (edge == RectangleEdge.BOTTOM) {
    215                colorBarArea = new Rectangle2D.Double(dataArea.getX(),
    216                        plotArea.getMaxY() + this.outerGap, length, thickness);
    217            }
    218            else if (edge == RectangleEdge.TOP) {
    219                colorBarArea = new Rectangle2D.Double(dataArea.getX(),
    220                        reservedArea.getMinY() + this.outerGap, length, thickness);
    221            }
    222            else if (edge == RectangleEdge.LEFT) {
    223                colorBarArea = new Rectangle2D.Double(plotArea.getX() - thickness
    224                        - this.outerGap, dataArea.getMinY(), thickness, length);
    225            }
    226            else if (edge == RectangleEdge.RIGHT) {
    227                colorBarArea = new Rectangle2D.Double(plotArea.getMaxX()
    228                        + this.outerGap, dataArea.getMinY(), thickness, length);
    229            }
    230
    231            // update, but dont draw tick marks (needed for stepped colors)
    232            this.axis.refreshTicks(g2, new AxisState(), colorBarArea, edge);
    233
    234            drawColorBar(g2, colorBarArea, edge);
    235
    236            AxisState state = null;
    237            if (edge == RectangleEdge.TOP) {
    238                cursor = colorBarArea.getMinY();
    239                state = this.axis.draw(g2, cursor, reservedArea, colorBarArea,
    240                        RectangleEdge.TOP, null);
    241            }
    242            else if (edge == RectangleEdge.BOTTOM) {
    243                cursor = colorBarArea.getMaxY();
    244                state = this.axis.draw(g2, cursor, reservedArea, colorBarArea,
    245                        RectangleEdge.BOTTOM, null);
    246            }
    247            else if (edge == RectangleEdge.LEFT) {
    248                cursor = colorBarArea.getMinX();
    249                state = this.axis.draw(g2, cursor, reservedArea, colorBarArea,
    250                        RectangleEdge.LEFT, null);
    251            }
    252            else if (edge == RectangleEdge.RIGHT) {
    253                cursor = colorBarArea.getMaxX();
    254                state = this.axis.draw(g2, cursor, reservedArea, colorBarArea,
    255                        RectangleEdge.RIGHT, null);
    256            }
    257            return state.getCursor();
    258
    259        }
    260
    261        /**
    262         * Draws the plot on a Java 2D graphics device (such as the screen or a
    263         * printer).
    264         *
    265         * @param g2  the graphics device.
    266         * @param colorBarArea  the area within which the axis should be drawn.
    267         * @param edge  the location.
    268         */
    269        public void drawColorBar(Graphics2D g2, Rectangle2D colorBarArea,
    270                                 RectangleEdge edge) {
    271
    272            Object antiAlias = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
    273            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
    274                                RenderingHints.VALUE_ANTIALIAS_OFF);
    275
    276            // setTickValues was missing from ColorPalette v. 0.96
    277            //colorPalette.setTickValues(this.axis.getTicks());
    278
    279            Stroke strokeSaved = g2.getStroke();
    280            g2.setStroke(new BasicStroke(1.0f));
    281
    282            if (RectangleEdge.isTopOrBottom(edge)) {
    283                double y1 = colorBarArea.getY();
    284                double y2 = colorBarArea.getMaxY();
    285                double xx = colorBarArea.getX();
    286                Line2D line = new Line2D.Double();
    287                while (xx <= colorBarArea.getMaxX()) {
    288                    double value = this.axis.java2DToValue(xx, colorBarArea, edge);
    289                    line.setLine(xx, y1, xx, y2);
    290                    g2.setPaint(getPaint(value));
    291                    g2.draw(line);
    292                    xx += 1;
    293                }
    294            }
    295            else {
    296                double y1 = colorBarArea.getX();
    297                double y2 = colorBarArea.getMaxX();
    298                double xx = colorBarArea.getY();
    299                Line2D line = new Line2D.Double();
    300                while (xx <= colorBarArea.getMaxY()) {
    301                    double value = this.axis.java2DToValue(xx, colorBarArea, edge);
    302                    line.setLine(y1, xx, y2, xx);
    303                    g2.setPaint(getPaint(value));
    304                    g2.draw(line);
    305                    xx += 1;
    306                }
    307            }
    308
    309            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias);
    310            g2.setStroke(strokeSaved);
    311
    312        }
    313
    314        /**
    315         * Returns the color palette.
    316         *
    317         * @return The color palette.
    318         */
    319        public ColorPalette getColorPalette() {
    320            return this.colorPalette;
    321        }
    322
    323        /**
    324         * Returns the Paint associated with a value.
    325         *
    326         * @param value  the value.
    327         *
    328         * @return The paint.
    329         */
    330        public Paint getPaint(double value) {
    331            return this.colorPalette.getPaint(value);
    332        }
    333
    334        /**
    335         * Sets the color palette.
    336         *
    337         * @param palette  the new palette.
    338         */
    339        public void setColorPalette(ColorPalette palette) {
    340            this.colorPalette = palette;
    341        }
    342
    343        /**
    344         * Sets the maximum value.
    345         *
    346         * @param value  the maximum value.
    347         */
    348        public void setMaximumValue(double value) {
    349            this.colorPalette.setMaxZ(value);
    350            this.axis.setUpperBound(value);
    351        }
    352
    353        /**
    354         * Sets the minimum value.
    355         *
    356         * @param value  the minimum value.
    357         */
    358        public void setMinimumValue(double value) {
    359            this.colorPalette.setMinZ(value);
    360            this.axis.setLowerBound(value);
    361        }
    362
    363        /**
    364         * Reserves the space required to draw the color bar.
    365         *
    366         * @param g2  the graphics device.
    367         * @param plot  the plot that the axis belongs to.
    368         * @param plotArea  the area within which the plot should be drawn.
    369         * @param dataArea  the data area.
    370         * @param edge  the axis location.
    371         * @param space  the space already reserved.
    372         *
    373         * @return The space required to draw the axis in the specified plot area.
    374         */
    375        public AxisSpace reserveSpace(Graphics2D g2, Plot plot,
    376                                      Rectangle2D plotArea,
    377                                      Rectangle2D dataArea, RectangleEdge edge,
    378                                      AxisSpace space) {
    379
    380            AxisSpace result = this.axis.reserveSpace(g2, plot, plotArea, edge,
    381                    space);
    382            double thickness = calculateBarThickness(dataArea, edge);
    383            result.add(thickness + 2 * this.outerGap, edge);
    384            return result;
    385
    386        }
    387
    388        /**
    389         * Calculates the bar thickness.
    390         *
    391         * @param plotArea  the plot area.
    392         * @param edge  the location.
    393         *
    394         * @return The thickness.
    395         */
    396        private double calculateBarThickness(Rectangle2D plotArea,
    397                                             RectangleEdge edge) {
    398            double result = 0.0;
    399            if (RectangleEdge.isLeftOrRight(edge)) {
    400                result = plotArea.getWidth() * this.colorBarThicknessPercent;
    401            }
    402            else {
    403                result = plotArea.getHeight() * this.colorBarThicknessPercent;
    404            }
    405            return result;
    406        }
    407
    408        /**
    409         * Returns a clone of the object.
    410         *
    411         * @return A clone.
    412         *
    413         * @throws CloneNotSupportedException if some component of the color bar
    414         *         does not support cloning.
    415         */
    416        public Object clone() throws CloneNotSupportedException {
    417
    418            ColorBar clone = (ColorBar) super.clone();
    419            clone.axis = (ValueAxis) this.axis.clone();
    420            return clone;
    421
    422        }
    423
    424        /**
    425         * Tests this object for equality with another.
    426         *
    427         * @param obj  the object to test against.
    428         *
    429         * @return A boolean.
    430         */
    431        public boolean equals(Object obj) {
    432
    433            if (obj == this) {
    434                return true;
    435            }
    436            if (!(obj instanceof ColorBar)) {
    437                return false;
    438            }
    439            ColorBar that = (ColorBar) obj;
    440            if (!this.axis.equals(that.axis)) {
    441                return false;
    442            }
    443            if (this.colorBarThickness != that.colorBarThickness) {
    444                return false;
    445            }
    446            if (this.colorBarThicknessPercent != that.colorBarThicknessPercent) {
    447                return false;
    448            }
    449            if (!this.colorPalette.equals(that.colorPalette)) {
    450                return false;
    451            }
    452            if (this.colorBarLength != that.colorBarLength) {
    453                return false;
    454            }
    455            if (this.outerGap != that.outerGap) {
    456                return false;
    457            }
    458            return true;
    459
    460        }
    461
    462        /**
    463         * Returns a hash code for this object.
    464         *
    465         * @return A hash code.
    466         */
    467        public int hashCode() {
    468            return this.axis.hashCode();
    469        }
    470
    471    }