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
055package org.jfree.chart.axis;
056
057import java.awt.Graphics2D;
058import java.awt.geom.Rectangle2D;
059import java.io.Serializable;
060
061import org.jfree.chart.Effect3D;
062import org.jfree.chart.plot.CategoryPlot;
063import org.jfree.chart.plot.PlotRenderingInfo;
064import org.jfree.chart.renderer.category.CategoryItemRenderer;
065import 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 */
071public 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}