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-2008, 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    * LevelRenderer.java
   29    * ------------------
   30    * (C) Copyright 2004-2008, by Object Refinery Limited.
   31    *
   32    * Original Author:  David Gilbert (for Object Refinery Limited);
   33    * Contributor(s):   -;
   34    *
   35    * Changes
   36    * -------
   37    * 09-Jan-2004 : Version 1 (DG);
   38    * 05-Nov-2004 : Modified drawItem() signature (DG);
   39    * 20-Apr-2005 : Renamed CategoryLabelGenerator
   40    *               --> CategoryItemLabelGenerator (DG);
   41    * ------------- JFREECHART 1.0.x ---------------------------------------------
   42    * 23-Jan-2006 : Renamed getMaxItemWidth() --> getMaximumItemWidth() (DG);
   43    * 13-May-2008 : Code clean-up (DG);
   44    *
   45    */
   46   
   47   package org.jfree.chart.renderer.category;
   48   
   49   import java.awt.Graphics2D;
   50   import java.awt.Paint;
   51   import java.awt.Stroke;
   52   import java.awt.geom.Line2D;
   53   import java.awt.geom.Rectangle2D;
   54   import java.io.Serializable;
   55   
   56   import org.jfree.chart.axis.CategoryAxis;
   57   import org.jfree.chart.axis.ValueAxis;
   58   import org.jfree.chart.entity.EntityCollection;
   59   import org.jfree.chart.event.RendererChangeEvent;
   60   import org.jfree.chart.labels.CategoryItemLabelGenerator;
   61   import org.jfree.chart.plot.CategoryPlot;
   62   import org.jfree.chart.plot.PlotOrientation;
   63   import org.jfree.chart.plot.PlotRenderingInfo;
   64   import org.jfree.data.category.CategoryDataset;
   65   import org.jfree.ui.RectangleEdge;
   66   import org.jfree.util.PublicCloneable;
   67   
   68   /**
   69    * A {@link CategoryItemRenderer} that draws individual data items as
   70    * horizontal lines, spaced in the same way as bars in a bar chart.
   71    */
   72   public class LevelRenderer extends AbstractCategoryItemRenderer
   73           implements Cloneable, PublicCloneable, Serializable {
   74   
   75       /** For serialization. */
   76       private static final long serialVersionUID = -8204856624355025117L;
   77   
   78       /** The default item margin percentage. */
   79       public static final double DEFAULT_ITEM_MARGIN = 0.20;
   80   
   81       /** The margin between items within a category. */
   82       private double itemMargin;
   83   
   84       /** The maximum item width as a percentage of the available space. */
   85       private double maxItemWidth;
   86   
   87       /**
   88        * Creates a new renderer with default settings.
   89        */
   90       public LevelRenderer() {
   91           super();
   92           this.itemMargin = DEFAULT_ITEM_MARGIN;
   93           this.maxItemWidth = 1.0;  // 100 percent, so it will not apply unless
   94                                     // changed
   95       }
   96   
   97       /**
   98        * Returns the item margin.
   99        *
  100        * @return The margin.
  101        *
  102        * @see #setItemMargin(double)
  103        */
  104       public double getItemMargin() {
  105           return this.itemMargin;
  106       }
  107   
  108       /**
  109        * Sets the item margin and sends a {@link RendererChangeEvent} to all
  110        * registered listeners.  The value is expressed as a percentage of the
  111        * available width for plotting all the bars, with the resulting amount to
  112        * be distributed between all the bars evenly.
  113        *
  114        * @param percent  the new margin.
  115        *
  116        * @see #getItemMargin()
  117        */
  118       public void setItemMargin(double percent) {
  119           this.itemMargin = percent;
  120           fireChangeEvent();
  121       }
  122   
  123       /**
  124        * Returns the maximum width, as a percentage of the available drawing
  125        * space.
  126        *
  127        * @return The maximum width.
  128        *
  129        * @see #setMaximumItemWidth(double)
  130        */
  131       public double getMaximumItemWidth() {
  132           return getMaxItemWidth();
  133       }
  134   
  135       /**
  136        * Sets the maximum item width, which is specified as a percentage of the
  137        * available space for all items, and sends a {@link RendererChangeEvent}
  138        * to all registered listeners.
  139        *
  140        * @param percent  the percent.
  141        *
  142        * @see #getMaximumItemWidth()
  143        */
  144       public void setMaximumItemWidth(double percent) {
  145           setMaxItemWidth(percent);
  146       }
  147   
  148       /**
  149        * Initialises the renderer and returns a state object that will be passed
  150        * to subsequent calls to the drawItem method.
  151        * <p>
  152        * This method gets called once at the start of the process of drawing a
  153        * chart.
  154        *
  155        * @param g2  the graphics device.
  156        * @param dataArea  the area in which the data is to be plotted.
  157        * @param plot  the plot.
  158        * @param rendererIndex  the renderer index.
  159        * @param info  collects chart rendering information for return to caller.
  160        *
  161        * @return The renderer state.
  162        */
  163       public CategoryItemRendererState initialise(Graphics2D g2,
  164               Rectangle2D dataArea, CategoryPlot plot, int rendererIndex,
  165               PlotRenderingInfo info) {
  166   
  167           CategoryItemRendererState state = super.initialise(g2, dataArea, plot,
  168                   rendererIndex, info);
  169           calculateItemWidth(plot, dataArea, rendererIndex, state);
  170           return state;
  171   
  172       }
  173   
  174       /**
  175        * Calculates the bar width and stores it in the renderer state.
  176        *
  177        * @param plot  the plot.
  178        * @param dataArea  the data area.
  179        * @param rendererIndex  the renderer index.
  180        * @param state  the renderer state.
  181        */
  182       protected void calculateItemWidth(CategoryPlot plot,
  183               Rectangle2D dataArea, int rendererIndex,
  184               CategoryItemRendererState state) {
  185   
  186           CategoryAxis domainAxis = getDomainAxis(plot, rendererIndex);
  187           CategoryDataset dataset = plot.getDataset(rendererIndex);
  188           if (dataset != null) {
  189               int columns = dataset.getColumnCount();
  190               int rows = dataset.getRowCount();
  191               double space = 0.0;
  192               PlotOrientation orientation = plot.getOrientation();
  193               if (orientation == PlotOrientation.HORIZONTAL) {
  194                   space = dataArea.getHeight();
  195               }
  196               else if (orientation == PlotOrientation.VERTICAL) {
  197                   space = dataArea.getWidth();
  198               }
  199               double maxWidth = space * getMaximumItemWidth();
  200               double categoryMargin = 0.0;
  201               double currentItemMargin = 0.0;
  202               if (columns > 1) {
  203                   categoryMargin = domainAxis.getCategoryMargin();
  204               }
  205               if (rows > 1) {
  206                   currentItemMargin = getItemMargin();
  207               }
  208               double used = space * (1 - domainAxis.getLowerMargin()
  209                                        - domainAxis.getUpperMargin()
  210                                        - categoryMargin - currentItemMargin);
  211               if ((rows * columns) > 0) {
  212                   state.setBarWidth(Math.min(used / (rows * columns), maxWidth));
  213               }
  214               else {
  215                   state.setBarWidth(Math.min(used, maxWidth));
  216               }
  217           }
  218       }
  219   
  220       /**
  221        * Calculates the coordinate of the first "side" of a bar.  This will be
  222        * the minimum x-coordinate for a vertical bar, and the minimum
  223        * y-coordinate for a horizontal bar.
  224        *
  225        * @param plot  the plot.
  226        * @param orientation  the plot orientation.
  227        * @param dataArea  the data area.
  228        * @param domainAxis  the domain axis.
  229        * @param state  the renderer state (has the bar width precalculated).
  230        * @param row  the row index.
  231        * @param column  the column index.
  232        *
  233        * @return The coordinate.
  234        */
  235       protected double calculateBarW0(CategoryPlot plot,
  236                                       PlotOrientation orientation,
  237                                       Rectangle2D dataArea,
  238                                       CategoryAxis domainAxis,
  239                                       CategoryItemRendererState state,
  240                                       int row,
  241                                       int column) {
  242           // calculate bar width...
  243           double space = 0.0;
  244           if (orientation == PlotOrientation.HORIZONTAL) {
  245               space = dataArea.getHeight();
  246           }
  247           else {
  248               space = dataArea.getWidth();
  249           }
  250           double barW0 = domainAxis.getCategoryStart(column, getColumnCount(),
  251                   dataArea, plot.getDomainAxisEdge());
  252           int seriesCount = getRowCount();
  253           int categoryCount = getColumnCount();
  254           if (seriesCount > 1) {
  255               double seriesGap = space * getItemMargin()
  256                       / (categoryCount * (seriesCount - 1));
  257               double seriesW = calculateSeriesWidth(space, domainAxis,
  258                       categoryCount, seriesCount);
  259               barW0 = barW0 + row * (seriesW + seriesGap)
  260                             + (seriesW / 2.0) - (state.getBarWidth() / 2.0);
  261           }
  262           else {
  263               barW0 = domainAxis.getCategoryMiddle(column, getColumnCount(),
  264                       dataArea, plot.getDomainAxisEdge()) - state.getBarWidth()
  265                       / 2.0;
  266           }
  267           return barW0;
  268       }
  269   
  270       /**
  271        * Draws the bar for a single (series, category) data item.
  272        *
  273        * @param g2  the graphics device.
  274        * @param state  the renderer state.
  275        * @param dataArea  the data area.
  276        * @param plot  the plot.
  277        * @param domainAxis  the domain axis.
  278        * @param rangeAxis  the range axis.
  279        * @param dataset  the dataset.
  280        * @param row  the row index (zero-based).
  281        * @param column  the column index (zero-based).
  282        * @param pass  the pass index.
  283        */
  284       public void drawItem(Graphics2D g2, CategoryItemRendererState state,
  285               Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
  286               ValueAxis rangeAxis, CategoryDataset dataset, int row, int column,
  287               int pass) {
  288   
  289           // nothing is drawn for null values...
  290           Number dataValue = dataset.getValue(row, column);
  291           if (dataValue == null) {
  292               return;
  293           }
  294   
  295           double value = dataValue.doubleValue();
  296   
  297           PlotOrientation orientation = plot.getOrientation();
  298           double barW0 = calculateBarW0(plot, orientation, dataArea, domainAxis,
  299                   state, row, column);
  300           RectangleEdge edge = plot.getRangeAxisEdge();
  301           double barL = rangeAxis.valueToJava2D(value, dataArea, edge);
  302   
  303           // draw the bar...
  304           Line2D line = null;
  305           double x = 0.0;
  306           double y = 0.0;
  307           if (orientation == PlotOrientation.HORIZONTAL) {
  308               x = barL;
  309               y = barW0 + state.getBarWidth() / 2.0;
  310               line = new Line2D.Double(barL, barW0, barL,
  311                       barW0 + state.getBarWidth());
  312           }
  313           else {
  314               x = barW0 + state.getBarWidth() / 2.0;
  315               y = barL;
  316               line = new Line2D.Double(barW0, barL, barW0 + state.getBarWidth(),
  317                       barL);
  318           }
  319           Stroke itemStroke = getItemStroke(row, column);
  320           Paint itemPaint = getItemPaint(row, column);
  321           g2.setStroke(itemStroke);
  322           g2.setPaint(itemPaint);
  323           g2.draw(line);
  324   
  325           CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
  326                   column);
  327           if (generator != null && isItemLabelVisible(row, column)) {
  328               drawItemLabel(g2, orientation, dataset, row, column, x, y,
  329                       (value < 0.0));
  330           }
  331   
  332           // add an item entity, if this information is being collected
  333           EntityCollection entities = state.getEntityCollection();
  334           if (entities != null) {
  335               addItemEntity(entities, dataset, row, column, line.getBounds());
  336           }
  337   
  338       }
  339   
  340       /**
  341        * Calculates the available space for each series.
  342        *
  343        * @param space  the space along the entire axis (in Java2D units).
  344        * @param axis  the category axis.
  345        * @param categories  the number of categories.
  346        * @param series  the number of series.
  347        *
  348        * @return The width of one series.
  349        */
  350       protected double calculateSeriesWidth(double space, CategoryAxis axis,
  351                                             int categories, int series) {
  352           double factor = 1.0 - getItemMargin() - axis.getLowerMargin()
  353                           - axis.getUpperMargin();
  354           if (categories > 1) {
  355               factor = factor - axis.getCategoryMargin();
  356           }
  357           return (space * factor) / (categories * series);
  358       }
  359   
  360       /**
  361        * Tests an object for equality with this instance.
  362        *
  363        * @param obj  the object (<code>null</code> permitted).
  364        *
  365        * @return A boolean.
  366        */
  367       public boolean equals(Object obj) {
  368           if (obj == this) {
  369               return true;
  370           }
  371           if (!(obj instanceof LevelRenderer)) {
  372               return false;
  373           }
  374           LevelRenderer that = (LevelRenderer) obj;
  375           if (this.itemMargin != that.itemMargin) {
  376               return false;
  377           }
  378           if (this.maxItemWidth != that.maxItemWidth) {
  379               return false;
  380           }
  381           return super.equals(obj);
  382       }
  383   
  384       /**
  385        * Returns the maximum width, as a percentage of the available drawing
  386        * space.
  387        *
  388        * @return The maximum width.
  389        *
  390        * @deprecated Use {@link #getMaximumItemWidth()} instead.
  391        */
  392       public double getMaxItemWidth() {
  393           return this.maxItemWidth;
  394       }
  395   
  396       /**
  397        * Sets the maximum item width, which is specified as a percentage of the
  398        * available space for all items, and sends a {@link RendererChangeEvent}
  399        * to all registered listeners.
  400        *
  401        * @param percent  the percent.
  402        *
  403        * @deprecated Use {@link #setMaximumItemWidth(double)} instead.
  404        */
  405       public void setMaxItemWidth(double percent) {
  406           this.maxItemWidth = percent;
  407           fireChangeEvent();
  408       }
  409   
  410   }

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