    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2006, 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     * CategoryAxis3D.java
    029     * -------------------
    030     * (C) Copyright 2003-2006, by Klaus Rheinwald and Contributors.
    031     *
    032     * Original Author:  Klaus Rheinwald;
    033     * Contributor(s):   Tin Luu,
    034     *                   David Gilbert (for Object Refinery Limited);
    035     *                   Adriaan Joubert;
    036     *
    037     * Changes
    038     * -------
    039     * 19-Feb-2003 : File creation;
    040     * 21-Mar-2003 : Added to JFreeChart CVS, see bug id 685501 for code
    041     *               contribution from KR (DG);
    042     * 26-Mar-2003 : Implemented Serializable (DG);
    043     * 13-May-2003 : Renamed HorizontalCategoryAxis3D --> CategoryAxis3D, and
    044     *               modified to take into account the plot orientation (DG);
    045     * 14-Aug-2003 : Implemented Cloneable (DG);
    046     * 21-Aug-2003 : Fixed draw() method bugs (DG);
    047     * 22-Mar-2004 : Added workaround for bug 920959 (null pointer exception with
    048     *               no renderer) (DG);
    049     * ------------- JFREECHART 1.0.x ---------------------------------------------
    050     * 18-Aug-2006 : Fix for bug drawing category labels, thanks to Adriaan
    051     *               Joubert (1277726) (DG);
    052     *
    053     */
    054
    055    package org.jfree.chart.axis;
    056
    057    import java.awt.Graphics2D;
    058    import java.awt.geom.Rectangle2D;
    059    import java.io.Serializable;
    060
    061    import org.jfree.chart.Effect3D;
    062    import org.jfree.chart.plot.CategoryPlot;
    063    import org.jfree.chart.plot.PlotRenderingInfo;
    064    import org.jfree.chart.renderer.category.CategoryItemRenderer;
    065    import org.jfree.ui.RectangleEdge;
    066
    067    /**
    068     * An axis that displays categories and has a 3D effect.
    069     * Used for bar charts and line charts.
    070     */
    071    public class CategoryAxis3D extends CategoryAxis
    072                                implements Cloneable, Serializable {
    073
    074        /** For serialization. */
    075        private static final long serialVersionUID = 4114732251353700972L;
    076
    077        /**
    078         * Creates a new axis.
    079         */
    080        public CategoryAxis3D() {
    081            this(null);
    082        }
    083
    084        /**
    085         * Creates a new axis using default attribute values.
    086         *
    087         * @param label  the axis label (<code>null</code> permitted).
    088         */
    089        public CategoryAxis3D(String label) {
    090            super(label);
    091        }
    092
    093        /**
    094         * Draws the axis on a Java 2D graphics device (such as the screen or a
    095         * printer).
    096         *
    097         * @param g2  the graphics device (<code>null</code> not permitted).
    098         * @param cursor  the cursor location.
    099         * @param plotArea  the area within which the axis should be drawn
    100         *                  (<code>null</code> not permitted).
    101         * @param dataArea  the area within which the plot is being drawn
    102         *                  (<code>null</code> not permitted).
    103         * @param edge  the location of the axis (<code>null</code> not permitted).
    104         * @param plotState  collects information about the plot (<code>null</code>
    105         *                   permitted).
    106         *
    107         * @return The axis state (never <code>null</code>).
    108         */
    109        public AxisState draw(Graphics2D g2,
    110                              double cursor,
    111                              Rectangle2D plotArea,
    112                              Rectangle2D dataArea,
    113                              RectangleEdge edge,
    114                              PlotRenderingInfo plotState) {
    115
    116            // if the axis is not visible, don't draw it...
    117            if (!isVisible()) {
    118                return new AxisState(cursor);
    119            }
    120
    121            // calculate the adjusted data area taking into account the 3D effect...
    122            // this assumes that there is a 3D renderer, all this 3D effect is a
    123            // bit of an ugly hack...
    124            CategoryPlot plot = (CategoryPlot) getPlot();
    125
    126            Rectangle2D adjustedDataArea = new Rectangle2D.Double();
    127            if (plot.getRenderer() instanceof Effect3D) {
    128                Effect3D e3D = (Effect3D) plot.getRenderer();
    129                double adjustedX = dataArea.getMinX();
    130                double adjustedY = dataArea.getMinY();
    131                double adjustedW = dataArea.getWidth() - e3D.getXOffset();
    132                double adjustedH = dataArea.getHeight() - e3D.getYOffset();
    133
    134                if (edge == RectangleEdge.LEFT || edge == RectangleEdge.BOTTOM) {
    135                    adjustedY += e3D.getYOffset();
    136                }
    137                else if (edge == RectangleEdge.RIGHT || edge == RectangleEdge.TOP) {
    138                    adjustedX += e3D.getXOffset();
    139                }
    140                adjustedDataArea.setRect(adjustedX, adjustedY, adjustedW,
    141                        adjustedH);
    142            }
    143            else {
    144                adjustedDataArea.setRect(dataArea);
    145            }
    146
    147            // draw the category labels and axis label
    148            AxisState state = new AxisState(cursor);
    149            state = drawCategoryLabels(g2, plotArea, adjustedDataArea, edge,
    150                    state, plotState);
    151            state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state);
    152
    153            return state;
    154
    155        }
    156
    157        /**
    158         * Returns the Java 2D coordinate for a category.
    159         *
    160         * @param anchor  the anchor point.
    161         * @param category  the category index.
    162         * @param categoryCount  the category count.
    163         * @param area  the data area.
    164         * @param edge  the location of the axis.
    165         *
    166         * @return The coordinate.
    167         */
    168        public double getCategoryJava2DCoordinate(CategoryAnchor anchor,
    169                                                  int category,
    170                                                  int categoryCount,
    171                                                  Rectangle2D area,
    172                                                  RectangleEdge edge) {
    173
    174            double result = 0.0;
    175            Rectangle2D adjustedArea = area;
    176            CategoryPlot plot = (CategoryPlot) getPlot();
    177            CategoryItemRenderer renderer = plot.getRenderer();
    178            if (renderer instanceof Effect3D) {
    179                Effect3D e3D = (Effect3D) renderer;
    180                double adjustedX = area.getMinX();
    181                double adjustedY = area.getMinY();
    182                double adjustedW = area.getWidth() - e3D.getXOffset();
    183                double adjustedH = area.getHeight() - e3D.getYOffset();
    184
    185                if (edge == RectangleEdge.LEFT || edge == RectangleEdge.BOTTOM) {
    186                    adjustedY += e3D.getYOffset();
    187                }
    188                else if (edge == RectangleEdge.RIGHT || edge == RectangleEdge.TOP) {
    189                    adjustedX += e3D.getXOffset();
    190                }
    191                adjustedArea = new Rectangle2D.Double(adjustedX, adjustedY,
    192                        adjustedW, adjustedH);
    193            }
    194
    195            if (anchor == CategoryAnchor.START) {
    196                result = getCategoryStart(category, categoryCount, adjustedArea,
    197                        edge);
    198            }
    199            else if (anchor == CategoryAnchor.MIDDLE) {
    200                result = getCategoryMiddle(category, categoryCount, adjustedArea,
    201                        edge);
    202            }
    203            else if (anchor == CategoryAnchor.END) {
    204                result = getCategoryEnd(category, categoryCount, adjustedArea,
    205                        edge);
    206            }
    207            return result;
    208
    209        }
    210
    211        /**
    212         * Returns a clone of the axis.
    213         *
    214         * @return A clone.
    215         *
    216         * @throws CloneNotSupportedException If the axis is not cloneable for
    217         *         some reason.
    218         */
    219        public Object clone() throws CloneNotSupportedException {
    220            return super.clone();
    221        }
    222
    223    }