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