    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     * CategoryAxis3D.java
    029     * -------------------
    030     * (C) Copyright 2003-2009, 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     * 16-Apr-2009 : Draw axis line and tick marks (DG);
    053     *
    054     */
    055
    056    package org.jfree.chart.axis;
    057
    058    import java.awt.Graphics2D;
    059    import java.awt.geom.Rectangle2D;
    060    import java.io.Serializable;
    061
    062    import org.jfree.chart.Effect3D;
    063    import org.jfree.chart.plot.CategoryPlot;
    064    import org.jfree.chart.plot.PlotRenderingInfo;
    065    import org.jfree.chart.renderer.category.CategoryItemRenderer;
    066    import org.jfree.ui.RectangleEdge;
    067
    068    /**
    069     * An axis that displays categories and has a 3D effect.
    070     * Used for bar charts and line charts.
    071     */
    072    public class CategoryAxis3D extends CategoryAxis
    073            implements Cloneable, Serializable {
    074
    075        /** For serialization. */
    076        private static final long serialVersionUID = 4114732251353700972L;
    077
    078        /**
    079         * Creates a new axis.
    080         */
    081        public CategoryAxis3D() {
    082            this(null);
    083        }
    084
    085        /**
    086         * Creates a new axis using default attribute values.
    087         *
    088         * @param label  the axis label (<code>null</code> permitted).
    089         */
    090        public CategoryAxis3D(String label) {
    091            super(label);
    092        }
    093
    094        /**
    095         * Draws the axis on a Java 2D graphics device (such as the screen or a
    096         * printer).
    097         *
    098         * @param g2  the graphics device (<code>null</code> not permitted).
    099         * @param cursor  the cursor location.
    100         * @param plotArea  the area within which the axis should be drawn
    101         *                  (<code>null</code> not permitted).
    102         * @param dataArea  the area within which the plot is being drawn
    103         *                  (<code>null</code> not permitted).
    104         * @param edge  the location of the axis (<code>null</code> not permitted).
    105         * @param plotState  collects information about the plot (<code>null</code>
    106         *                   permitted).
    107         *
    108         * @return The axis state (never <code>null</code>).
    109         */
    110        public AxisState draw(Graphics2D g2,
    111                              double cursor,
    112                              Rectangle2D plotArea,
    113                              Rectangle2D dataArea,
    114                              RectangleEdge edge,
    115                              PlotRenderingInfo plotState) {
    116
    117            // if the axis is not visible, don't draw it...
    118            if (!isVisible()) {
    119                return new AxisState(cursor);
    120            }
    121
    122            // calculate the adjusted data area taking into account the 3D effect...
    123            // this assumes that there is a 3D renderer, all this 3D effect is a
    124            // bit of an ugly hack...
    125            CategoryPlot plot = (CategoryPlot) getPlot();
    126
    127            Rectangle2D adjustedDataArea = new Rectangle2D.Double();
    128            if (plot.getRenderer() instanceof Effect3D) {
    129                Effect3D e3D = (Effect3D) plot.getRenderer();
    130                double adjustedX = dataArea.getMinX();
    131                double adjustedY = dataArea.getMinY();
    132                double adjustedW = dataArea.getWidth() - e3D.getXOffset();
    133                double adjustedH = dataArea.getHeight() - e3D.getYOffset();
    134
    135                if (edge == RectangleEdge.LEFT || edge == RectangleEdge.BOTTOM) {
    136                    adjustedY += e3D.getYOffset();
    137                }
    138                else if (edge == RectangleEdge.RIGHT || edge == RectangleEdge.TOP) {
    139                    adjustedX += e3D.getXOffset();
    140                }
    141                adjustedDataArea.setRect(adjustedX, adjustedY, adjustedW,
    142                        adjustedH);
    143            }
    144            else {
    145                adjustedDataArea.setRect(dataArea);
    146            }
    147
    148            if (isAxisLineVisible()) {
    149                drawAxisLine(g2, cursor, adjustedDataArea, edge);
    150            }
    151            // draw the category labels and axis label
    152            AxisState state = new AxisState(cursor);
    153            if (isTickMarksVisible()) {
    154                drawTickMarks(g2, cursor, adjustedDataArea, edge, state);
    155            }
    156            state = drawCategoryLabels(g2, plotArea, adjustedDataArea, edge,
    157                    state, plotState);
    158            state = drawLabel(getLabel(), g2, plotArea, dataArea, edge, state);
    159
    160            return state;
    161
    162        }
    163
    164        /**
    165         * Returns the Java 2D coordinate for a category.
    166         *
    167         * @param anchor  the anchor point.
    168         * @param category  the category index.
    169         * @param categoryCount  the category count.
    170         * @param area  the data area.
    171         * @param edge  the location of the axis.
    172         *
    173         * @return The coordinate.
    174         */
    175        public double getCategoryJava2DCoordinate(CategoryAnchor anchor,
    176                                                  int category,
    177                                                  int categoryCount,
    178                                                  Rectangle2D area,
    179                                                  RectangleEdge edge) {
    180
    181            double result = 0.0;
    182            Rectangle2D adjustedArea = area;
    183            CategoryPlot plot = (CategoryPlot) getPlot();
    184            CategoryItemRenderer renderer = plot.getRenderer();
    185            if (renderer instanceof Effect3D) {
    186                Effect3D e3D = (Effect3D) renderer;
    187                double adjustedX = area.getMinX();
    188                double adjustedY = area.getMinY();
    189                double adjustedW = area.getWidth() - e3D.getXOffset();
    190                double adjustedH = area.getHeight() - e3D.getYOffset();
    191
    192                if (edge == RectangleEdge.LEFT || edge == RectangleEdge.BOTTOM) {
    193                    adjustedY += e3D.getYOffset();
    194                }
    195                else if (edge == RectangleEdge.RIGHT || edge == RectangleEdge.TOP) {
    196                    adjustedX += e3D.getXOffset();
    197                }
    198                adjustedArea = new Rectangle2D.Double(adjustedX, adjustedY,
    199                        adjustedW, adjustedH);
    200            }
    201
    202            if (anchor == CategoryAnchor.START) {
    203                result = getCategoryStart(category, categoryCount, adjustedArea,
    204                        edge);
    205            }
    206            else if (anchor == CategoryAnchor.MIDDLE) {
    207                result = getCategoryMiddle(category, categoryCount, adjustedArea,
    208                        edge);
    209            }
    210            else if (anchor == CategoryAnchor.END) {
    211                result = getCategoryEnd(category, categoryCount, adjustedArea,
    212                        edge);
    213            }
    214            return result;
    215
    216        }
    217
    218        /**
    219         * Returns a clone of the axis.
    220         *
    221         * @return A clone.
    222         *
    223         * @throws CloneNotSupportedException If the axis is not cloneable for
    224         *         some reason.
    225         */
    226        public Object clone() throws CloneNotSupportedException {
    227            return super.clone();
    228        }
    229
    230    }