Save This Page
Home » jcommon-1.0.13 » org.jfree » chart » renderer » category » [javadoc | source]
    1   /* ===========================================================
    2    * JFreeChart : a free chart library for the Java(tm) platform
    3    * ===========================================================
    4    *
    5    * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
    6    *
    7    * Project Info:  http://www.jfree.org/jfreechart/index.html
    8    *
    9    * This library is free software; you can redistribute it and/or modify it
   10    * under the terms of the GNU Lesser General Public License as published by
   11    * the Free Software Foundation; either version 2.1 of the License, or
   12    * (at your option) any later version.
   13    *
   14    * This library is distributed in the hope that it will be useful, but
   15    * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   16    * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
   17    * License for more details.
   18    *
   19    * You should have received a copy of the GNU Lesser General Public
   20    * License along with this library; if not, write to the Free Software
   21    * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
   22    * USA.
   23    *
   24    * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
   25    * in the United States and other countries.]
   26    *
   27    * ------------------
   28    * BarRenderer3D.java
   29    * ------------------
   30    * (C) Copyright 2001-2007, by Serge V. Grachov and Contributors.
   31    *
   32    * Original Author:  Serge V. Grachov;
   33    * Contributor(s):   David Gilbert (for Object Refinery Limited);
   34    *                   Tin Luu;
   35    *                   Milo Simpson;
   36    *                   Richard Atkinson;
   37    *                   Rich Unger;
   38    *                   Christian W. Zuckschwerdt;
   39    *
   40    * Changes
   41    * -------
   42    * 31-Oct-2001 : First version, contributed by Serge V. Grachov (DG);
   43    * 15-Nov-2001 : Modified to allow for null data values (DG);
   44    * 13-Dec-2001 : Added tooltips (DG);
   45    * 16-Jan-2002 : Added fix for single category or single series datasets,
   46    *               pointed out by Taoufik Romdhane (DG);
   47    * 24-May-2002 : Incorporated tooltips into chart entities (DG);
   48    * 11-Jun-2002 : Added check for (permitted) null info object, bug and fix
   49    *               reported by David Basten.  Also updated Javadocs. (DG);
   50    * 19-Jun-2002 : Added code to draw labels on bars (TL);
   51    * 26-Jun-2002 : Added bar clipping to avoid PRExceptions (DG);
   52    * 05-Aug-2002 : Small modification to drawCategoryItem method to support URLs
   53    *               for HTML image maps (RA);
   54    * 06-Aug-2002 : Value labels now use number formatter, thanks to Milo
   55    *               Simpson (DG);
   56    * 08-Aug-2002 : Applied fixed in bug id 592218 (DG);
   57    * 20-Sep-2002 : Added fix for categoryPaint by Rich Unger, and fixed errors
   58    *               reported by Checkstyle (DG);
   59    * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
   60    *               CategoryToolTipGenerator interface (DG);
   61    * 05-Nov-2002 : Replaced references to CategoryDataset with TableDataset (DG);
   62    * 06-Nov-2002 : Moved to the com.jrefinery.chart.renderer package (DG);
   63    * 28-Jan-2003 : Added an attribute to control the shading of the left and
   64    *               bottom walls in the plot background (DG);
   65    * 25-Mar-2003 : Implemented Serializable (DG);
   66    * 10-Apr-2003 : Removed category paint usage (DG);
   67    * 13-May-2003 : Renamed VerticalBarRenderer3D --> BarRenderer3D and merged with
   68    *               HorizontalBarRenderer3D (DG);
   69    * 30-Jul-2003 : Modified entity constructor (CZ);
   70    * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
   71    * 07-Oct-2003 : Added renderer state (DG);
   72    * 08-Oct-2003 : Removed clipping (replaced with flag in CategoryPlot to
   73    *               control order in which the data items are processed) (DG);
   74    * 20-Oct-2003 : Fixed bug (outline stroke not being used for bar
   75    *               outlines) (DG);
   76    * 21-Oct-2003 : Bar width moved into CategoryItemRendererState (DG);
   77    * 24-Nov-2003 : Fixed bug 846324 (item labels not showing) (DG);
   78    * 27-Nov-2003 : Added code to respect maxBarWidth setting (DG);
   79    * 02-Feb-2004 : Fixed bug where 'drawBarOutline' flag is not respected (DG);
   80    * 10-Feb-2004 : Small change to drawItem() method to make cut-and-paste
   81    *               overriding easier (DG);
   82    * 04-Oct-2004 : Fixed bug with item label positioning when plot alignment is
   83    *               horizontal (DG);
   84    * 05-Nov-2004 : Modified drawItem() signature (DG);
   85    * 20-Apr-2005 : Renamed CategoryLabelGenerator
   86    *               --> CategoryItemLabelGenerator (DG);
   87    * 25-Apr-2005 : Override initialise() method to fix bug 1189642 (DG);
   88    * 09-Jun-2005 : Use addEntityItem from super class (DG);
   89    * ------------- JFREECHART 1.0.x ---------------------------------------------
   90    * 07-Dec-2006 : Implemented equals() override (DG);
   91    * 17-Jan-2007 : Fixed bug in drawDomainGridline() method (DG);
   92    * 03-Apr-2007 : Fixed bugs in drawBackground() method (DG);
   93    * 16-Oct-2007 : Fixed bug in range marker drawing (DG);
   94    *
   95    */
   96   
   97   package org.jfree.chart.renderer.category;
   98   
   99   import java.awt.AlphaComposite;
  100   import java.awt.Color;
  101   import java.awt.Composite;
  102   import java.awt.Font;
  103   import java.awt.Graphics2D;
  104   import java.awt.Image;
  105   import java.awt.Paint;
  106   import java.awt.Stroke;
  107   import java.awt.geom.GeneralPath;
  108   import java.awt.geom.Line2D;
  109   import java.awt.geom.Point2D;
  110   import java.awt.geom.Rectangle2D;
  111   import java.io.IOException;
  112   import java.io.ObjectInputStream;
  113   import java.io.ObjectOutputStream;
  114   import java.io.Serializable;
  115   
  116   import org.jfree.chart.Effect3D;
  117   import org.jfree.chart.axis.CategoryAxis;
  118   import org.jfree.chart.axis.ValueAxis;
  119   import org.jfree.chart.entity.EntityCollection;
  120   import org.jfree.chart.event.RendererChangeEvent;
  121   import org.jfree.chart.labels.CategoryItemLabelGenerator;
  122   import org.jfree.chart.labels.ItemLabelAnchor;
  123   import org.jfree.chart.labels.ItemLabelPosition;
  124   import org.jfree.chart.plot.CategoryPlot;
  125   import org.jfree.chart.plot.Marker;
  126   import org.jfree.chart.plot.Plot;
  127   import org.jfree.chart.plot.PlotOrientation;
  128   import org.jfree.chart.plot.PlotRenderingInfo;
  129   import org.jfree.chart.plot.ValueMarker;
  130   import org.jfree.data.Range;
  131   import org.jfree.data.category.CategoryDataset;
  132   import org.jfree.io.SerialUtilities;
  133   import org.jfree.text.TextUtilities;
  134   import org.jfree.ui.LengthAdjustmentType;
  135   import org.jfree.ui.RectangleAnchor;
  136   import org.jfree.ui.RectangleEdge;
  137   import org.jfree.ui.TextAnchor;
  138   import org.jfree.util.PaintUtilities;
  139   import org.jfree.util.PublicCloneable;
  140   
  141   /**
  142    * A renderer for bars with a 3D effect, for use with the
  143    * {@link org.jfree.chart.plot.CategoryPlot} class.
  144    */
  145   public class BarRenderer3D extends BarRenderer
  146           implements Effect3D, Cloneable, PublicCloneable, Serializable {
  147   
  148       /** For serialization. */
  149       private static final long serialVersionUID = 7686976503536003636L;
  150   
  151       /** The default x-offset for the 3D effect. */
  152       public static final double DEFAULT_X_OFFSET = 12.0;
  153   
  154       /** The default y-offset for the 3D effect. */
  155       public static final double DEFAULT_Y_OFFSET = 8.0;
  156   
  157       /** The default wall paint. */
  158       public static final Paint DEFAULT_WALL_PAINT = new Color(0xDD, 0xDD, 0xDD);
  159   
  160       /** The size of x-offset for the 3D effect. */
  161       private double xOffset;
  162   
  163       /** The size of y-offset for the 3D effect. */
  164       private double yOffset;
  165   
  166       /** The paint used to shade the left and lower 3D wall. */
  167       private transient Paint wallPaint;
  168   
  169       /**
  170        * Default constructor, creates a renderer with a default '3D effect'.
  171        */
  172       public BarRenderer3D() {
  173           this(DEFAULT_X_OFFSET, DEFAULT_Y_OFFSET);
  174       }
  175   
  176       /**
  177        * Constructs a new renderer with the specified '3D effect'.
  178        *
  179        * @param xOffset  the x-offset for the 3D effect.
  180        * @param yOffset  the y-offset for the 3D effect.
  181        */
  182       public BarRenderer3D(double xOffset, double yOffset) {
  183   
  184           super();
  185           this.xOffset = xOffset;
  186           this.yOffset = yOffset;
  187           this.wallPaint = DEFAULT_WALL_PAINT;
  188           // set the default item label positions
  189           ItemLabelPosition p1 = new ItemLabelPosition(ItemLabelAnchor.INSIDE12,
  190                   TextAnchor.TOP_CENTER);
  191           setBasePositiveItemLabelPosition(p1);
  192           ItemLabelPosition p2 = new ItemLabelPosition(ItemLabelAnchor.INSIDE12,
  193                   TextAnchor.TOP_CENTER);
  194           setBaseNegativeItemLabelPosition(p2);
  195   
  196       }
  197   
  198       /**
  199        * Returns the x-offset for the 3D effect.
  200        *
  201        * @return The 3D effect.
  202        *
  203        * @see #getYOffset()
  204        */
  205       public double getXOffset() {
  206           return this.xOffset;
  207       }
  208   
  209       /**
  210        * Returns the y-offset for the 3D effect.
  211        *
  212        * @return The 3D effect.
  213        */
  214       public double getYOffset() {
  215           return this.yOffset;
  216       }
  217   
  218       /**
  219        * Returns the paint used to highlight the left and bottom wall in the plot
  220        * background.
  221        *
  222        * @return The paint.
  223        *
  224        * @see #setWallPaint(Paint)
  225        */
  226       public Paint getWallPaint() {
  227           return this.wallPaint;
  228       }
  229   
  230       /**
  231        * Sets the paint used to hightlight the left and bottom walls in the plot
  232        * background, and sends a {@link RendererChangeEvent} to all registered
  233        * listeners.
  234        *
  235        * @param paint  the paint (<code>null</code> not permitted).
  236        *
  237        * @see #getWallPaint()
  238        */
  239       public void setWallPaint(Paint paint) {
  240           if (paint == null) {
  241               throw new IllegalArgumentException("Null 'paint' argument.");
  242           }
  243           this.wallPaint = paint;
  244           fireChangeEvent();
  245       }
  246   
  247   
  248       /**
  249        * Initialises the renderer and returns a state object that will be passed
  250        * to subsequent calls to the drawItem method.  This method gets called
  251        * once at the start of the process of drawing a chart.
  252        *
  253        * @param g2  the graphics device.
  254        * @param dataArea  the area in which the data is to be plotted.
  255        * @param plot  the plot.
  256        * @param rendererIndex  the renderer index.
  257        * @param info  collects chart rendering information for return to caller.
  258        *
  259        * @return The renderer state.
  260        */
  261       public CategoryItemRendererState initialise(Graphics2D g2,
  262                                                   Rectangle2D dataArea,
  263                                                   CategoryPlot plot,
  264                                                   int rendererIndex,
  265                                                   PlotRenderingInfo info) {
  266   
  267           Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
  268                   dataArea.getY() + getYOffset(), dataArea.getWidth()
  269                   - getXOffset(), dataArea.getHeight() - getYOffset());
  270           CategoryItemRendererState state = super.initialise(g2, adjusted, plot,
  271                   rendererIndex, info);
  272           return state;
  273   
  274       }
  275   
  276       /**
  277        * Draws the background for the plot.
  278        *
  279        * @param g2  the graphics device.
  280        * @param plot  the plot.
  281        * @param dataArea  the area inside the axes.
  282        */
  283       public void drawBackground(Graphics2D g2, CategoryPlot plot,
  284                                  Rectangle2D dataArea) {
  285   
  286           float x0 = (float) dataArea.getX();
  287           float x1 = x0 + (float) Math.abs(this.xOffset);
  288           float x3 = (float) dataArea.getMaxX();
  289           float x2 = x3 - (float) Math.abs(this.xOffset);
  290   
  291           float y0 = (float) dataArea.getMaxY();
  292           float y1 = y0 - (float) Math.abs(this.yOffset);
  293           float y3 = (float) dataArea.getMinY();
  294           float y2 = y3 + (float) Math.abs(this.yOffset);
  295   
  296           GeneralPath clip = new GeneralPath();
  297           clip.moveTo(x0, y0);
  298           clip.lineTo(x0, y2);
  299           clip.lineTo(x1, y3);
  300           clip.lineTo(x3, y3);
  301           clip.lineTo(x3, y1);
  302           clip.lineTo(x2, y0);
  303           clip.closePath();
  304   
  305           Composite originalComposite = g2.getComposite();
  306           g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
  307                   plot.getBackgroundAlpha()));
  308   
  309           // fill background...
  310           Paint backgroundPaint = plot.getBackgroundPaint();
  311           if (backgroundPaint != null) {
  312               g2.setPaint(backgroundPaint);
  313               g2.fill(clip);
  314           }
  315   
  316           GeneralPath leftWall = new GeneralPath();
  317           leftWall.moveTo(x0, y0);
  318           leftWall.lineTo(x0, y2);
  319           leftWall.lineTo(x1, y3);
  320           leftWall.lineTo(x1, y1);
  321           leftWall.closePath();
  322           g2.setPaint(getWallPaint());
  323           g2.fill(leftWall);
  324   
  325           GeneralPath bottomWall = new GeneralPath();
  326           bottomWall.moveTo(x0, y0);
  327           bottomWall.lineTo(x1, y1);
  328           bottomWall.lineTo(x3, y1);
  329           bottomWall.lineTo(x2, y0);
  330           bottomWall.closePath();
  331           g2.setPaint(getWallPaint());
  332           g2.fill(bottomWall);
  333   
  334           // highlight the background corners...
  335           g2.setPaint(Color.lightGray);
  336           Line2D corner = new Line2D.Double(x0, y0, x1, y1);
  337           g2.draw(corner);
  338           corner.setLine(x1, y1, x1, y3);
  339           g2.draw(corner);
  340           corner.setLine(x1, y1, x3, y1);
  341           g2.draw(corner);
  342   
  343           // draw background image, if there is one...
  344           Image backgroundImage = plot.getBackgroundImage();
  345           if (backgroundImage != null) {
  346               Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX()
  347                       + getXOffset(), dataArea.getY(),
  348                       dataArea.getWidth() - getXOffset(),
  349                       dataArea.getHeight() - getYOffset());
  350               plot.drawBackgroundImage(g2, adjusted);
  351           }
  352   
  353           g2.setComposite(originalComposite);
  354   
  355       }
  356   
  357       /**
  358        * Draws the outline for the plot.
  359        *
  360        * @param g2  the graphics device.
  361        * @param plot  the plot.
  362        * @param dataArea  the area inside the axes.
  363        */
  364       public void drawOutline(Graphics2D g2, CategoryPlot plot,
  365                               Rectangle2D dataArea) {
  366   
  367           float x0 = (float) dataArea.getX();
  368           float x1 = x0 + (float) Math.abs(this.xOffset);
  369           float x3 = (float) dataArea.getMaxX();
  370           float x2 = x3 - (float) Math.abs(this.xOffset);
  371   
  372           float y0 = (float) dataArea.getMaxY();
  373           float y1 = y0 - (float) Math.abs(this.yOffset);
  374           float y3 = (float) dataArea.getMinY();
  375           float y2 = y3 + (float) Math.abs(this.yOffset);
  376   
  377           GeneralPath clip = new GeneralPath();
  378           clip.moveTo(x0, y0);
  379           clip.lineTo(x0, y2);
  380           clip.lineTo(x1, y3);
  381           clip.lineTo(x3, y3);
  382           clip.lineTo(x3, y1);
  383           clip.lineTo(x2, y0);
  384           clip.closePath();
  385   
  386           // put an outline around the data area...
  387           Stroke outlineStroke = plot.getOutlineStroke();
  388           Paint outlinePaint = plot.getOutlinePaint();
  389           if ((outlineStroke != null) && (outlinePaint != null)) {
  390               g2.setStroke(outlineStroke);
  391               g2.setPaint(outlinePaint);
  392               g2.draw(clip);
  393           }
  394   
  395       }
  396   
  397       /**
  398        * Draws a grid line against the domain axis.
  399        *
  400        * @param g2  the graphics device.
  401        * @param plot  the plot.
  402        * @param dataArea  the area for plotting data (not yet adjusted for any
  403        *                  3D effect).
  404        * @param value  the Java2D value at which the grid line should be drawn.
  405        *
  406        */
  407       public void drawDomainGridline(Graphics2D g2,
  408                                      CategoryPlot plot,
  409                                      Rectangle2D dataArea,
  410                                      double value) {
  411   
  412           Line2D line1 = null;
  413           Line2D line2 = null;
  414           PlotOrientation orientation = plot.getOrientation();
  415           if (orientation == PlotOrientation.HORIZONTAL) {
  416               double y0 = value;
  417               double y1 = value - getYOffset();
  418               double x0 = dataArea.getMinX();
  419               double x1 = x0 + getXOffset();
  420               double x2 = dataArea.getMaxX();
  421               line1 = new Line2D.Double(x0, y0, x1, y1);
  422               line2 = new Line2D.Double(x1, y1, x2, y1);
  423           }
  424           else if (orientation == PlotOrientation.VERTICAL) {
  425               double x0 = value;
  426               double x1 = value + getXOffset();
  427               double y0 = dataArea.getMaxY();
  428               double y1 = y0 - getYOffset();
  429               double y2 = dataArea.getMinY();
  430               line1 = new Line2D.Double(x0, y0, x1, y1);
  431               line2 = new Line2D.Double(x1, y1, x1, y2);
  432           }
  433           Paint paint = plot.getDomainGridlinePaint();
  434           Stroke stroke = plot.getDomainGridlineStroke();
  435           g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
  436           g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
  437           g2.draw(line1);
  438           g2.draw(line2);
  439   
  440       }
  441   
  442       /**
  443        * Draws a grid line against the range axis.
  444        *
  445        * @param g2  the graphics device.
  446        * @param plot  the plot.
  447        * @param axis  the value axis.
  448        * @param dataArea  the area for plotting data (not yet adjusted for any
  449        *                  3D effect).
  450        * @param value  the value at which the grid line should be drawn.
  451        *
  452        */
  453       public void drawRangeGridline(Graphics2D g2,
  454                                     CategoryPlot plot,
  455                                     ValueAxis axis,
  456                                     Rectangle2D dataArea,
  457                                     double value) {
  458   
  459           Range range = axis.getRange();
  460   
  461           if (!range.contains(value)) {
  462               return;
  463           }
  464   
  465           Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
  466                   dataArea.getY() + getYOffset(), dataArea.getWidth()
  467                   - getXOffset(), dataArea.getHeight() - getYOffset());
  468   
  469           Line2D line1 = null;
  470           Line2D line2 = null;
  471           PlotOrientation orientation = plot.getOrientation();
  472           if (orientation == PlotOrientation.HORIZONTAL) {
  473               double x0 = axis.valueToJava2D(value, adjusted,
  474                       plot.getRangeAxisEdge());
  475               double x1 = x0 + getXOffset();
  476               double y0 = dataArea.getMaxY();
  477               double y1 = y0 - getYOffset();
  478               double y2 = dataArea.getMinY();
  479               line1 = new Line2D.Double(x0, y0, x1, y1);
  480               line2 = new Line2D.Double(x1, y1, x1, y2);
  481           }
  482           else if (orientation == PlotOrientation.VERTICAL) {
  483               double y0 = axis.valueToJava2D(value, adjusted,
  484                       plot.getRangeAxisEdge());
  485               double y1 = y0 - getYOffset();
  486               double x0 = dataArea.getMinX();
  487               double x1 = x0 + getXOffset();
  488               double x2 = dataArea.getMaxX();
  489               line1 = new Line2D.Double(x0, y0, x1, y1);
  490               line2 = new Line2D.Double(x1, y1, x2, y1);
  491           }
  492           Paint paint = plot.getRangeGridlinePaint();
  493           Stroke stroke = plot.getRangeGridlineStroke();
  494           g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT);
  495           g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE);
  496           g2.draw(line1);
  497           g2.draw(line2);
  498   
  499       }
  500   
  501       /**
  502        * Draws a range marker.
  503        *
  504        * @param g2  the graphics device.
  505        * @param plot  the plot.
  506        * @param axis  the value axis.
  507        * @param marker  the marker.
  508        * @param dataArea  the area for plotting data (not including 3D effect).
  509        */
  510       public void drawRangeMarker(Graphics2D g2,
  511                                   CategoryPlot plot,
  512                                   ValueAxis axis,
  513                                   Marker marker,
  514                                   Rectangle2D dataArea) {
  515   
  516   
  517           Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
  518                   dataArea.getY() + getYOffset(), dataArea.getWidth()
  519                   - getXOffset(), dataArea.getHeight() - getYOffset());
  520           if (marker instanceof ValueMarker) {
  521               ValueMarker vm = (ValueMarker) marker;
  522               double value = vm.getValue();
  523               Range range = axis.getRange();
  524               if (!range.contains(value)) {
  525                   return;
  526               }
  527   
  528               GeneralPath path = null;
  529               PlotOrientation orientation = plot.getOrientation();
  530               if (orientation == PlotOrientation.HORIZONTAL) {
  531                   float x = (float) axis.valueToJava2D(value, adjusted,
  532                           plot.getRangeAxisEdge());
  533                   float y = (float) adjusted.getMaxY();
  534                   path = new GeneralPath();
  535                   path.moveTo(x, y);
  536                   path.lineTo((float) (x + getXOffset()),
  537                           y - (float) getYOffset());
  538                   path.lineTo((float) (x + getXOffset()),
  539                           (float) (adjusted.getMinY() - getYOffset()));
  540                   path.lineTo(x, (float) adjusted.getMinY());
  541                   path.closePath();
  542               }
  543               else if (orientation == PlotOrientation.VERTICAL) {
  544                   float y = (float) axis.valueToJava2D(value, adjusted,
  545                           plot.getRangeAxisEdge());
  546                   float x = (float) dataArea.getX();
  547                   path = new GeneralPath();
  548                   path.moveTo(x, y);
  549                   path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset);
  550                   path.lineTo((float) (adjusted.getMaxX() + this.xOffset),
  551                           y - (float) this.yOffset);
  552                   path.lineTo((float) (adjusted.getMaxX()), y);
  553                   path.closePath();
  554               }
  555               g2.setPaint(marker.getPaint());
  556               g2.fill(path);
  557               g2.setPaint(marker.getOutlinePaint());
  558               g2.draw(path);
  559   
  560               String label = marker.getLabel();
  561               RectangleAnchor anchor = marker.getLabelAnchor();
  562               if (label != null) {
  563                   Font labelFont = marker.getLabelFont();
  564                   g2.setFont(labelFont);
  565                   g2.setPaint(marker.getLabelPaint());
  566                   Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
  567                           g2, orientation, dataArea, path.getBounds2D(),
  568                           marker.getLabelOffset(), LengthAdjustmentType.EXPAND,
  569                           anchor);
  570                   TextUtilities.drawAlignedString(label, g2,
  571                           (float) coordinates.getX(), (float) coordinates.getY(),
  572                           marker.getLabelTextAnchor());
  573               }
  574   
  575           }
  576           else {
  577               super.drawRangeMarker(g2, plot, axis, marker, adjusted);
  578               // TODO: draw the interval marker with a 3D effect
  579           }
  580       }
  581   
  582       /**
  583        * Draws a 3D bar to represent one data item.
  584        *
  585        * @param g2  the graphics device.
  586        * @param state  the renderer state.
  587        * @param dataArea  the area for plotting the data.
  588        * @param plot  the plot.
  589        * @param domainAxis  the domain axis.
  590        * @param rangeAxis  the range axis.
  591        * @param dataset  the dataset.
  592        * @param row  the row index (zero-based).
  593        * @param column  the column index (zero-based).
  594        * @param pass  the pass index.
  595        */
  596       public void drawItem(Graphics2D g2,
  597                            CategoryItemRendererState state,
  598                            Rectangle2D dataArea,
  599                            CategoryPlot plot,
  600                            CategoryAxis domainAxis,
  601                            ValueAxis rangeAxis,
  602                            CategoryDataset dataset,
  603                            int row,
  604                            int column,
  605                            int pass) {
  606   
  607           // check the value we are plotting...
  608           Number dataValue = dataset.getValue(row, column);
  609           if (dataValue == null) {
  610               return;
  611           }
  612   
  613           double value = dataValue.doubleValue();
  614   
  615           Rectangle2D adjusted = new Rectangle2D.Double(dataArea.getX(),
  616                   dataArea.getY() + getYOffset(),
  617                   dataArea.getWidth() - getXOffset(),
  618                   dataArea.getHeight() - getYOffset());
  619   
  620           PlotOrientation orientation = plot.getOrientation();
  621   
  622           double barW0 = calculateBarW0(plot, orientation, adjusted, domainAxis,
  623                   state, row, column);
  624           double[] barL0L1 = calculateBarL0L1(value);
  625           if (barL0L1 == null) {
  626               return;  // the bar is not visible
  627           }
  628   
  629           RectangleEdge edge = plot.getRangeAxisEdge();
  630           double transL0 = rangeAxis.valueToJava2D(barL0L1[0], adjusted, edge);
  631           double transL1 = rangeAxis.valueToJava2D(barL0L1[1], adjusted, edge);
  632           double barL0 = Math.min(transL0, transL1);
  633           double barLength = Math.abs(transL1 - transL0);
  634   
  635           // draw the bar...
  636           Rectangle2D bar = null;
  637           if (orientation == PlotOrientation.HORIZONTAL) {
  638               bar = new Rectangle2D.Double(barL0, barW0, barLength,
  639                       state.getBarWidth());
  640           }
  641           else {
  642               bar = new Rectangle2D.Double(barW0, barL0, state.getBarWidth(),
  643                       barLength);
  644           }
  645           Paint itemPaint = getItemPaint(row, column);
  646           g2.setPaint(itemPaint);
  647           g2.fill(bar);
  648   
  649           double x0 = bar.getMinX();
  650           double x1 = x0 + getXOffset();
  651           double x2 = bar.getMaxX();
  652           double x3 = x2 + getXOffset();
  653   
  654           double y0 = bar.getMinY() - getYOffset();
  655           double y1 = bar.getMinY();
  656           double y2 = bar.getMaxY() - getYOffset();
  657           double y3 = bar.getMaxY();
  658   
  659           GeneralPath bar3dRight = null;
  660           GeneralPath bar3dTop = null;
  661           if (barLength > 0.0) {
  662               bar3dRight = new GeneralPath();
  663               bar3dRight.moveTo((float) x2, (float) y3);
  664               bar3dRight.lineTo((float) x2, (float) y1);
  665               bar3dRight.lineTo((float) x3, (float) y0);
  666               bar3dRight.lineTo((float) x3, (float) y2);
  667               bar3dRight.closePath();
  668   
  669               if (itemPaint instanceof Color) {
  670                   g2.setPaint(((Color) itemPaint).darker());
  671               }
  672               g2.fill(bar3dRight);
  673           }
  674   
  675           bar3dTop = new GeneralPath();
  676           bar3dTop.moveTo((float) x0, (float) y1);
  677           bar3dTop.lineTo((float) x1, (float) y0);
  678           bar3dTop.lineTo((float) x3, (float) y0);
  679           bar3dTop.lineTo((float) x2, (float) y1);
  680           bar3dTop.closePath();
  681           g2.fill(bar3dTop);
  682   
  683           if (isDrawBarOutline()
  684                   && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
  685               g2.setStroke(getItemOutlineStroke(row, column));
  686               g2.setPaint(getItemOutlinePaint(row, column));
  687               g2.draw(bar);
  688               if (bar3dRight != null) {
  689                   g2.draw(bar3dRight);
  690               }
  691               if (bar3dTop != null) {
  692                   g2.draw(bar3dTop);
  693               }
  694           }
  695   
  696           CategoryItemLabelGenerator generator
  697               = getItemLabelGenerator(row, column);
  698           if (generator != null && isItemLabelVisible(row, column)) {
  699               drawItemLabel(g2, dataset, row, column, plot, generator, bar,
  700                       (value < 0.0));
  701           }
  702   
  703           // add an item entity, if this information is being collected
  704           EntityCollection entities = state.getEntityCollection();
  705           if (entities != null) {
  706               GeneralPath barOutline = new GeneralPath();
  707               barOutline.moveTo((float) x0, (float) y3);
  708               barOutline.lineTo((float) x0, (float) y1);
  709               barOutline.lineTo((float) x1, (float) y0);
  710               barOutline.lineTo((float) x3, (float) y0);
  711               barOutline.lineTo((float) x3, (float) y2);
  712               barOutline.lineTo((float) x2, (float) y3);
  713               barOutline.closePath();
  714               addItemEntity(entities, dataset, row, column, barOutline);
  715           }
  716   
  717       }
  718   
  719       /**
  720        * Tests this renderer for equality with an arbitrary object.
  721        *
  722        * @param obj  the object (<code>null</code> permitted).
  723        *
  724        * @return A boolean.
  725        */
  726       public boolean equals(Object obj) {
  727           if (obj == this) {
  728               return true;
  729           }
  730           if (!(obj instanceof BarRenderer3D)) {
  731               return false;
  732           }
  733           BarRenderer3D that = (BarRenderer3D) obj;
  734           if (this.xOffset != that.xOffset) {
  735               return false;
  736           }
  737           if (this.yOffset != that.yOffset) {
  738               return false;
  739           }
  740           if (!PaintUtilities.equal(this.wallPaint, that.wallPaint)) {
  741               return false;
  742           }
  743           return super.equals(obj);
  744       }
  745   
  746       /**
  747        * Provides serialization support.
  748        *
  749        * @param stream  the output stream.
  750        *
  751        * @throws IOException  if there is an I/O error.
  752        */
  753       private void writeObject(ObjectOutputStream stream) throws IOException {
  754           stream.defaultWriteObject();
  755           SerialUtilities.writePaint(this.wallPaint, stream);
  756       }
  757   
  758       /**
  759        * Provides serialization support.
  760        *
  761        * @param stream  the input stream.
  762        *
  763        * @throws IOException  if there is an I/O error.
  764        * @throws ClassNotFoundException  if there is a classpath problem.
  765        */
  766       private void readObject(ObjectInputStream stream)
  767           throws IOException, ClassNotFoundException {
  768           stream.defaultReadObject();
  769           this.wallPaint = SerialUtilities.readPaint(stream);
  770       }
  771   
  772   }

Save This Page
Home » jcommon-1.0.13 » org.jfree » chart » renderer » category » [javadoc | source]