1 /* =========================================================== 2 * JFreeChart : a free chart library for the Java(tm) platform 3 * =========================================================== 4 * 5 * (C) Copyright 2000-2013, 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 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 25 * Other names may be trademarks of their respective owners.] 26 * 27 * --------------------------- 28 * AbstractXYItemRenderer.java 29 * --------------------------- 30 * (C) Copyright 2002-2013, by Object Refinery Limited and Contributors. 31 * 32 * Original Author: David Gilbert (for Object Refinery Limited); 33 * Contributor(s): Richard Atkinson; 34 * Focus Computer Services Limited; 35 * Tim Bardzil; 36 * Sergei Ivanov; 37 * Peter Kolb (patch 2809117); 38 * Martin Krauskopf; 39 * 40 * Changes: 41 * -------- 42 * 15-Mar-2002 : Version 1 (DG); 43 * 09-Apr-2002 : Added a getToolTipGenerator() method reflecting the change in 44 * the XYItemRenderer interface (DG); 45 * 05-Aug-2002 : Added a urlGenerator member variable to support HTML image 46 * maps (RA); 47 * 20-Aug-2002 : Added property change events for the tooltip and URL 48 * generators (DG); 49 * 22-Aug-2002 : Moved property change support into AbstractRenderer class (DG); 50 * 23-Sep-2002 : Fixed errors reported by Checkstyle tool (DG); 51 * 18-Nov-2002 : Added methods for drawing grid lines (DG); 52 * 17-Jan-2003 : Moved plot classes into a separate package (DG); 53 * 25-Mar-2003 : Implemented Serializable (DG); 54 * 01-May-2003 : Modified initialise() return type and drawItem() method 55 * signature (DG); 56 * 15-May-2003 : Modified to take into account the plot orientation (DG); 57 * 21-May-2003 : Added labels to markers (DG); 58 * 05-Jun-2003 : Added domain and range grid bands (sponsored by Focus Computer 59 * Services Ltd) (DG); 60 * 27-Jul-2003 : Added getRangeType() to support stacked XY area charts (RA); 61 * 31-Jul-2003 : Deprecated all but the default constructor (DG); 62 * 13-Aug-2003 : Implemented Cloneable (DG); 63 * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG); 64 * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG); 65 * 05-Nov-2003 : Fixed marker rendering bug (833623) (DG); 66 * 11-Feb-2004 : Updated labelling for markers (DG); 67 * 25-Feb-2004 : Added updateCrosshairValues() method. Moved deprecated code 68 * to bottom of source file (DG); 69 * 16-Apr-2004 : Added support for IntervalMarker in drawRangeMarker() method 70 * - thanks to Tim Bardzil (DG); 71 * 05-May-2004 : Fixed bug (948310) where interval markers extend beyond axis 72 * range (DG); 73 * 03-Jun-2004 : Fixed more bugs in drawing interval markers (DG); 74 * 26-Aug-2004 : Added the addEntity() method (DG); 75 * 29-Sep-2004 : Added annotation support (with layers) (DG); 76 * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities --> 77 * TextUtilities (DG); 78 * 06-Oct-2004 : Added findDomainBounds() method and renamed 79 * getRangeExtent() --> findRangeBounds() (DG); 80 * 07-Jan-2005 : Removed deprecated code (DG); 81 * 27-Jan-2005 : Modified getLegendItem() to omit hidden series (DG); 82 * 24-Feb-2005 : Added getLegendItems() method (DG); 83 * 08-Mar-2005 : Fixed positioning of marker labels (DG); 84 * 20-Apr-2005 : Renamed XYLabelGenerator --> XYItemLabelGenerator and 85 * added generators for legend labels, tooltips and URLs (DG); 86 * 01-Jun-2005 : Handle one dimension of the marker label adjustment 87 * automatically (DG); 88 * ------------- JFREECHART 1.0.x --------------------------------------------- 89 * 20-Jul-2006 : Set dataset and series indices in LegendItem (DG); 90 * 24-Oct-2006 : Respect alpha setting in markers (see patch 1567843 by Sergei 91 * Ivanov) (DG); 92 * 24-Oct-2006 : Added code to draw outlines for interval markers (DG); 93 * 24-Nov-2006 : Fixed cloning for legend item generators (DG); 94 * 06-Feb-2007 : Added new updateCrosshairValues() method that takes into 95 * account multiple axis plots (see bug 1086307) (DG); 96 * 20-Feb-2007 : Fixed equals() method implementation (DG); 97 * 01-Mar-2007 : Fixed interval marker drawing (patch 1670686 thanks to 98 * Sergei Ivanov) (DG); 99 * 22-Mar-2007 : Modified the tool tip generator look up (DG); 100 * 23-Mar-2007 : Added drawDomainLine() method (DG); 101 * 20-Apr-2007 : Updated getLegendItem() for renderer change, and deprecated 102 * itemLabelGenerator and toolTipGenerator override fields (DG); 103 * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG); 104 * 12-Nov-2007 : Fixed domain and range band drawing methods (DG); 105 * 07-Apr-2008 : Minor API doc update (DG); 106 * 14-May-2008 : Updated addEntity() method to take plot orientation into 107 * account when the incoming area is null (DG); 108 * 02-Jun-2008 : Added isPointInRect() method (DG); 109 * 17-Jun-2008 : Apply legend shape, font and paint attributes (DG); 110 * 09-Mar-2009 : Added getAnnotations() method (DG); 111 * 27-Mar-2009 : Added new findDomainBounds() and findRangeBounds() methods to 112 * take account of hidden series (DG); 113 * 01-Apr-2009 : Moved defaultEntityRadius up to superclass (DG); 114 * 28-Apr-2009 : Updated getLegendItem() method to observe new 115 * 'treatLegendShapeAsLine' flag (DG); 116 * 24-Jun-2009 : Added support for annotation events - see patch 2809117 117 * by PK (DG); 118 * 01-Sep-2009 : Bug 2840132 - set renderer index when drawing 119 * annotations (DG); 120 * 06-Oct-2011 : Add utility methods to work with 1.4 API in GeneralPath (MK) 121 * 03-Jul-2013 : Use ParamChecks (DG); 122 * 123 */ 124 125 package org.jfree.chart.renderer.xy; 126 127 import java.awt.AlphaComposite; 128 import java.awt.Composite; 129 import java.awt.Font; 130 import java.awt.GradientPaint; 131 import java.awt.Graphics2D; 132 import java.awt.Paint; 133 import java.awt.Shape; 134 import java.awt.Stroke; 135 import java.awt.geom.Ellipse2D; 136 import java.awt.geom.GeneralPath; 137 import java.awt.geom.Line2D; 138 import java.awt.geom.Point2D; 139 import java.awt.geom.Rectangle2D; 140 import java.io.Serializable; 141 import java.util.ArrayList; 142 import java.util.Collection; 143 import java.util.Iterator; 144 import java.util.List; 145 146 import org.jfree.chart.LegendItem; 147 import org.jfree.chart.LegendItemCollection; 148 import org.jfree.chart.annotations.Annotation; 149 import org.jfree.chart.annotations.XYAnnotation; 150 import org.jfree.chart.axis.ValueAxis; 151 import org.jfree.chart.entity.EntityCollection; 152 import org.jfree.chart.entity.XYItemEntity; 153 import org.jfree.chart.event.AnnotationChangeEvent; 154 import org.jfree.chart.event.AnnotationChangeListener; 155 import org.jfree.chart.event.RendererChangeEvent; 156 import org.jfree.chart.labels.ItemLabelPosition; 157 import org.jfree.chart.labels.StandardXYSeriesLabelGenerator; 158 import org.jfree.chart.labels.XYItemLabelGenerator; 159 import org.jfree.chart.labels.XYSeriesLabelGenerator; 160 import org.jfree.chart.labels.XYToolTipGenerator; 161 import org.jfree.chart.plot.CrosshairState; 162 import org.jfree.chart.plot.DrawingSupplier; 163 import org.jfree.chart.plot.IntervalMarker; 164 import org.jfree.chart.plot.Marker; 165 import org.jfree.chart.plot.Plot; 166 import org.jfree.chart.plot.PlotOrientation; 167 import org.jfree.chart.plot.PlotRenderingInfo; 168 import org.jfree.chart.plot.ValueMarker; 169 import org.jfree.chart.plot.XYPlot; 170 import org.jfree.chart.renderer.AbstractRenderer; 171 import org.jfree.chart.urls.XYURLGenerator; 172 import org.jfree.chart.util.ParamChecks; 173 import org.jfree.data.Range; 174 import org.jfree.data.general.DatasetUtilities; 175 import org.jfree.data.xy.XYDataset; 176 import org.jfree.text.TextUtilities; 177 import org.jfree.ui.GradientPaintTransformer; 178 import org.jfree.ui.Layer; 179 import org.jfree.ui.LengthAdjustmentType; 180 import org.jfree.ui.RectangleAnchor; 181 import org.jfree.ui.RectangleInsets; 182 import org.jfree.util.ObjectList; 183 import org.jfree.util.ObjectUtilities; 184 import org.jfree.util.PublicCloneable; 185 186 /** 187 * A base class that can be used to create new {@link XYItemRenderer} 188 * implementations. 189 */ 190 public abstract class AbstractXYItemRenderer extends AbstractRenderer 191 implements XYItemRenderer, AnnotationChangeListener, 192 Cloneable, Serializable { 193 194 /** For serialization. */ 195 private static final long serialVersionUID = 8019124836026607990L; 196 197 /** The plot. */ 198 private XYPlot plot; 199 200 /** A list of item label generators (one per series). */ 201 private ObjectList itemLabelGeneratorList; 202 203 /** The base item label generator. */ 204 private XYItemLabelGenerator baseItemLabelGenerator; 205 206 /** A list of tool tip generators (one per series). */ 207 private ObjectList toolTipGeneratorList; 208 209 /** The base tool tip generator. */ 210 private XYToolTipGenerator baseToolTipGenerator; 211 212 /** The URL text generator. */ 213 private XYURLGenerator urlGenerator; 214 215 /** 216 * Annotations to be drawn in the background layer ('underneath' the data 217 * items). 218 */ 219 private List backgroundAnnotations; 220 221 /** 222 * Annotations to be drawn in the foreground layer ('on top' of the data 223 * items). 224 */ 225 private List foregroundAnnotations; 226 227 /** The legend item label generator. */ 228 private XYSeriesLabelGenerator legendItemLabelGenerator; 229 230 /** The legend item tool tip generator. */ 231 private XYSeriesLabelGenerator legendItemToolTipGenerator; 232 233 /** The legend item URL generator. */ 234 private XYSeriesLabelGenerator legendItemURLGenerator; 235 236 /** 237 * Creates a renderer where the tooltip generator and the URL generator are 238 * both <code>null</code>. 239 */ AbstractXYItemRenderer()240 protected AbstractXYItemRenderer() { 241 super(); 242 this.itemLabelGenerator = null; 243 this.itemLabelGeneratorList = new ObjectList(); 244 this.toolTipGenerator = null; 245 this.toolTipGeneratorList = new ObjectList(); 246 this.urlGenerator = null; 247 this.backgroundAnnotations = new java.util.ArrayList(); 248 this.foregroundAnnotations = new java.util.ArrayList(); 249 this.legendItemLabelGenerator = new StandardXYSeriesLabelGenerator( 250 "{0}"); 251 } 252 253 /** 254 * Returns the number of passes through the data that the renderer requires 255 * in order to draw the chart. Most charts will require a single pass, but 256 * some require two passes. 257 * 258 * @return The pass count. 259 */ 260 @Override getPassCount()261 public int getPassCount() { 262 return 1; 263 } 264 265 /** 266 * Returns the plot that the renderer is assigned to. 267 * 268 * @return The plot (possibly <code>null</code>). 269 */ 270 @Override getPlot()271 public XYPlot getPlot() { 272 return this.plot; 273 } 274 275 /** 276 * Sets the plot that the renderer is assigned to. 277 * 278 * @param plot the plot (<code>null</code> permitted). 279 */ 280 @Override setPlot(XYPlot plot)281 public void setPlot(XYPlot plot) { 282 this.plot = plot; 283 } 284 285 /** 286 * Initialises the renderer and returns a state object that should be 287 * passed to all subsequent calls to the drawItem() method. 288 * <P> 289 * This method will be called before the first item is rendered, giving the 290 * renderer an opportunity to initialise any state information it wants to 291 * maintain. The renderer can do nothing if it chooses. 292 * 293 * @param g2 the graphics device. 294 * @param dataArea the area inside the axes. 295 * @param plot the plot. 296 * @param data the data. 297 * @param info an optional info collection object to return data back to 298 * the caller. 299 * 300 * @return The renderer state (never <code>null</code>). 301 */ 302 @Override initialise(Graphics2D g2, Rectangle2D dataArea, XYPlot plot, XYDataset data, PlotRenderingInfo info)303 public XYItemRendererState initialise(Graphics2D g2, Rectangle2D dataArea, 304 XYPlot plot, XYDataset data, PlotRenderingInfo info) { 305 return new XYItemRendererState(info); 306 } 307 308 // ITEM LABEL GENERATOR 309 310 /** 311 * Returns the label generator for a data item. This implementation simply 312 * passes control to the {@link #getSeriesItemLabelGenerator(int)} method. 313 * If, for some reason, you want a different generator for individual 314 * items, you can override this method. 315 * 316 * @param series the series index (zero based). 317 * @param item the item index (zero based). 318 * 319 * @return The generator (possibly <code>null</code>). 320 */ 321 @Override getItemLabelGenerator(int series, int item)322 public XYItemLabelGenerator getItemLabelGenerator(int series, int item) { 323 // return the generator for ALL series, if there is one... 324 if (this.itemLabelGenerator != null) { 325 return this.itemLabelGenerator; 326 } 327 328 // otherwise look up the generator table 329 XYItemLabelGenerator generator 330 = (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series); 331 if (generator == null) { 332 generator = this.baseItemLabelGenerator; 333 } 334 return generator; 335 } 336 337 /** 338 * Returns the item label generator for a series. 339 * 340 * @param series the series index (zero based). 341 * 342 * @return The generator (possibly <code>null</code>). 343 */ 344 @Override getSeriesItemLabelGenerator(int series)345 public XYItemLabelGenerator getSeriesItemLabelGenerator(int series) { 346 return (XYItemLabelGenerator) this.itemLabelGeneratorList.get(series); 347 } 348 349 /** 350 * Sets the item label generator for a series and sends a 351 * {@link RendererChangeEvent} to all registered listeners. 352 * 353 * @param series the series index (zero based). 354 * @param generator the generator (<code>null</code> permitted). 355 */ 356 @Override setSeriesItemLabelGenerator(int series, XYItemLabelGenerator generator)357 public void setSeriesItemLabelGenerator(int series, 358 XYItemLabelGenerator generator) { 359 this.itemLabelGeneratorList.set(series, generator); 360 fireChangeEvent(); 361 } 362 363 /** 364 * Returns the base item label generator. 365 * 366 * @return The generator (possibly <code>null</code>). 367 */ 368 @Override getBaseItemLabelGenerator()369 public XYItemLabelGenerator getBaseItemLabelGenerator() { 370 return this.baseItemLabelGenerator; 371 } 372 373 /** 374 * Sets the base item label generator and sends a 375 * {@link RendererChangeEvent} to all registered listeners. 376 * 377 * @param generator the generator (<code>null</code> permitted). 378 */ 379 @Override setBaseItemLabelGenerator(XYItemLabelGenerator generator)380 public void setBaseItemLabelGenerator(XYItemLabelGenerator generator) { 381 this.baseItemLabelGenerator = generator; 382 fireChangeEvent(); 383 } 384 385 // TOOL TIP GENERATOR 386 387 /** 388 * Returns the tool tip generator for a data item. If, for some reason, 389 * you want a different generator for individual items, you can override 390 * this method. 391 * 392 * @param series the series index (zero based). 393 * @param item the item index (zero based). 394 * 395 * @return The generator (possibly <code>null</code>). 396 */ 397 @Override getToolTipGenerator(int series, int item)398 public XYToolTipGenerator getToolTipGenerator(int series, int item) { 399 // return the generator for ALL series, if there is one... 400 if (this.toolTipGenerator != null) { 401 return this.toolTipGenerator; 402 } 403 404 // otherwise look up the generator table 405 XYToolTipGenerator generator 406 = (XYToolTipGenerator) this.toolTipGeneratorList.get(series); 407 if (generator == null) { 408 generator = this.baseToolTipGenerator; 409 } 410 return generator; 411 } 412 413 /** 414 * Returns the tool tip generator for a series. 415 * 416 * @param series the series index (zero based). 417 * 418 * @return The generator (possibly <code>null</code>). 419 */ 420 @Override getSeriesToolTipGenerator(int series)421 public XYToolTipGenerator getSeriesToolTipGenerator(int series) { 422 return (XYToolTipGenerator) this.toolTipGeneratorList.get(series); 423 } 424 425 /** 426 * Sets the tool tip generator for a series and sends a 427 * {@link RendererChangeEvent} to all registered listeners. 428 * 429 * @param series the series index (zero based). 430 * @param generator the generator (<code>null</code> permitted). 431 */ 432 @Override setSeriesToolTipGenerator(int series, XYToolTipGenerator generator)433 public void setSeriesToolTipGenerator(int series, 434 XYToolTipGenerator generator) { 435 this.toolTipGeneratorList.set(series, generator); 436 fireChangeEvent(); 437 } 438 439 /** 440 * Returns the base tool tip generator. 441 * 442 * @return The generator (possibly <code>null</code>). 443 * 444 * @see #setBaseToolTipGenerator(XYToolTipGenerator) 445 */ 446 @Override getBaseToolTipGenerator()447 public XYToolTipGenerator getBaseToolTipGenerator() { 448 return this.baseToolTipGenerator; 449 } 450 451 /** 452 * Sets the base tool tip generator and sends a {@link RendererChangeEvent} 453 * to all registered listeners. 454 * 455 * @param generator the generator (<code>null</code> permitted). 456 * 457 * @see #getBaseToolTipGenerator() 458 */ 459 @Override setBaseToolTipGenerator(XYToolTipGenerator generator)460 public void setBaseToolTipGenerator(XYToolTipGenerator generator) { 461 this.baseToolTipGenerator = generator; 462 fireChangeEvent(); 463 } 464 465 // URL GENERATOR 466 467 /** 468 * Returns the URL generator for HTML image maps. 469 * 470 * @return The URL generator (possibly <code>null</code>). 471 */ 472 @Override getURLGenerator()473 public XYURLGenerator getURLGenerator() { 474 return this.urlGenerator; 475 } 476 477 /** 478 * Sets the URL generator for HTML image maps and sends a 479 * {@link RendererChangeEvent} to all registered listeners. 480 * 481 * @param urlGenerator the URL generator (<code>null</code> permitted). 482 */ 483 @Override setURLGenerator(XYURLGenerator urlGenerator)484 public void setURLGenerator(XYURLGenerator urlGenerator) { 485 this.urlGenerator = urlGenerator; 486 fireChangeEvent(); 487 } 488 489 /** 490 * Adds an annotation and sends a {@link RendererChangeEvent} to all 491 * registered listeners. The annotation is added to the foreground 492 * layer. 493 * 494 * @param annotation the annotation (<code>null</code> not permitted). 495 */ 496 @Override addAnnotation(XYAnnotation annotation)497 public void addAnnotation(XYAnnotation annotation) { 498 // defer argument checking 499 addAnnotation(annotation, Layer.FOREGROUND); 500 } 501 502 /** 503 * Adds an annotation to the specified layer and sends a 504 * {@link RendererChangeEvent} to all registered listeners. 505 * 506 * @param annotation the annotation (<code>null</code> not permitted). 507 * @param layer the layer (<code>null</code> not permitted). 508 */ 509 @Override addAnnotation(XYAnnotation annotation, Layer layer)510 public void addAnnotation(XYAnnotation annotation, Layer layer) { 511 ParamChecks.nullNotPermitted(annotation, "annotation"); 512 if (layer.equals(Layer.FOREGROUND)) { 513 this.foregroundAnnotations.add(annotation); 514 annotation.addChangeListener(this); 515 fireChangeEvent(); 516 } 517 else if (layer.equals(Layer.BACKGROUND)) { 518 this.backgroundAnnotations.add(annotation); 519 annotation.addChangeListener(this); 520 fireChangeEvent(); 521 } 522 else { 523 // should never get here 524 throw new RuntimeException("Unknown layer."); 525 } 526 } 527 /** 528 * Removes the specified annotation and sends a {@link RendererChangeEvent} 529 * to all registered listeners. 530 * 531 * @param annotation the annotation to remove (<code>null</code> not 532 * permitted). 533 * 534 * @return A boolean to indicate whether or not the annotation was 535 * successfully removed. 536 */ 537 @Override removeAnnotation(XYAnnotation annotation)538 public boolean removeAnnotation(XYAnnotation annotation) { 539 boolean removed = this.foregroundAnnotations.remove(annotation); 540 removed = removed & this.backgroundAnnotations.remove(annotation); 541 annotation.removeChangeListener(this); 542 fireChangeEvent(); 543 return removed; 544 } 545 546 /** 547 * Removes all annotations and sends a {@link RendererChangeEvent} 548 * to all registered listeners. 549 */ 550 @Override removeAnnotations()551 public void removeAnnotations() { 552 for(int i = 0; i < this.foregroundAnnotations.size(); i++){ 553 XYAnnotation annotation 554 = (XYAnnotation) this.foregroundAnnotations.get(i); 555 annotation.removeChangeListener(this); 556 } 557 for(int i = 0; i < this.backgroundAnnotations.size(); i++){ 558 XYAnnotation annotation 559 = (XYAnnotation) this.backgroundAnnotations.get(i); 560 annotation.removeChangeListener(this); 561 } 562 this.foregroundAnnotations.clear(); 563 this.backgroundAnnotations.clear(); 564 fireChangeEvent(); 565 } 566 567 568 /** 569 * Receives notification of a change to an {@link Annotation} added to 570 * this renderer. 571 * 572 * @param event information about the event (not used here). 573 * 574 * @since 1.0.14 575 */ 576 @Override annotationChanged(AnnotationChangeEvent event)577 public void annotationChanged(AnnotationChangeEvent event) { 578 fireChangeEvent(); 579 } 580 581 /** 582 * Returns a collection of the annotations that are assigned to the 583 * renderer. 584 * 585 * @return A collection of annotations (possibly empty but never 586 * <code>null</code>). 587 * 588 * @since 1.0.13 589 */ getAnnotations()590 public Collection getAnnotations() { 591 List result = new java.util.ArrayList(this.foregroundAnnotations); 592 result.addAll(this.backgroundAnnotations); 593 return result; 594 } 595 596 /** 597 * Returns the legend item label generator. 598 * 599 * @return The label generator (never <code>null</code>). 600 * 601 * @see #setLegendItemLabelGenerator(XYSeriesLabelGenerator) 602 */ 603 @Override getLegendItemLabelGenerator()604 public XYSeriesLabelGenerator getLegendItemLabelGenerator() { 605 return this.legendItemLabelGenerator; 606 } 607 608 /** 609 * Sets the legend item label generator and sends a 610 * {@link RendererChangeEvent} to all registered listeners. 611 * 612 * @param generator the generator (<code>null</code> not permitted). 613 * 614 * @see #getLegendItemLabelGenerator() 615 */ 616 @Override setLegendItemLabelGenerator(XYSeriesLabelGenerator generator)617 public void setLegendItemLabelGenerator(XYSeriesLabelGenerator generator) { 618 ParamChecks.nullNotPermitted(generator, "generator"); 619 this.legendItemLabelGenerator = generator; 620 fireChangeEvent(); 621 } 622 623 /** 624 * Returns the legend item tool tip generator. 625 * 626 * @return The tool tip generator (possibly <code>null</code>). 627 * 628 * @see #setLegendItemToolTipGenerator(XYSeriesLabelGenerator) 629 */ getLegendItemToolTipGenerator()630 public XYSeriesLabelGenerator getLegendItemToolTipGenerator() { 631 return this.legendItemToolTipGenerator; 632 } 633 634 /** 635 * Sets the legend item tool tip generator and sends a 636 * {@link RendererChangeEvent} to all registered listeners. 637 * 638 * @param generator the generator (<code>null</code> permitted). 639 * 640 * @see #getLegendItemToolTipGenerator() 641 */ setLegendItemToolTipGenerator( XYSeriesLabelGenerator generator)642 public void setLegendItemToolTipGenerator( 643 XYSeriesLabelGenerator generator) { 644 this.legendItemToolTipGenerator = generator; 645 fireChangeEvent(); 646 } 647 648 /** 649 * Returns the legend item URL generator. 650 * 651 * @return The URL generator (possibly <code>null</code>). 652 * 653 * @see #setLegendItemURLGenerator(XYSeriesLabelGenerator) 654 */ getLegendItemURLGenerator()655 public XYSeriesLabelGenerator getLegendItemURLGenerator() { 656 return this.legendItemURLGenerator; 657 } 658 659 /** 660 * Sets the legend item URL generator and sends a 661 * {@link RendererChangeEvent} to all registered listeners. 662 * 663 * @param generator the generator (<code>null</code> permitted). 664 * 665 * @see #getLegendItemURLGenerator() 666 */ setLegendItemURLGenerator(XYSeriesLabelGenerator generator)667 public void setLegendItemURLGenerator(XYSeriesLabelGenerator generator) { 668 this.legendItemURLGenerator = generator; 669 fireChangeEvent(); 670 } 671 672 /** 673 * Returns the lower and upper bounds (range) of the x-values in the 674 * specified dataset. 675 * 676 * @param dataset the dataset (<code>null</code> permitted). 677 * 678 * @return The range (<code>null</code> if the dataset is <code>null</code> 679 * or empty). 680 * 681 * @see #findRangeBounds(XYDataset) 682 */ 683 @Override findDomainBounds(XYDataset dataset)684 public Range findDomainBounds(XYDataset dataset) { 685 return findDomainBounds(dataset, false); 686 } 687 688 /** 689 * Returns the lower and upper bounds (range) of the x-values in the 690 * specified dataset. 691 * 692 * @param dataset the dataset (<code>null</code> permitted). 693 * @param includeInterval include the interval (if any) for the dataset? 694 * 695 * @return The range (<code>null</code> if the dataset is <code>null</code> 696 * or empty). 697 * 698 * @since 1.0.13 699 */ findDomainBounds(XYDataset dataset, boolean includeInterval)700 protected Range findDomainBounds(XYDataset dataset, 701 boolean includeInterval) { 702 if (dataset == null) { 703 return null; 704 } 705 if (getDataBoundsIncludesVisibleSeriesOnly()) { 706 List visibleSeriesKeys = new ArrayList(); 707 int seriesCount = dataset.getSeriesCount(); 708 for (int s = 0; s < seriesCount; s++) { 709 if (isSeriesVisible(s)) { 710 visibleSeriesKeys.add(dataset.getSeriesKey(s)); 711 } 712 } 713 return DatasetUtilities.findDomainBounds(dataset, 714 visibleSeriesKeys, includeInterval); 715 } 716 return DatasetUtilities.findDomainBounds(dataset, includeInterval); 717 } 718 719 /** 720 * Returns the range of values the renderer requires to display all the 721 * items from the specified dataset. 722 * 723 * @param dataset the dataset (<code>null</code> permitted). 724 * 725 * @return The range (<code>null</code> if the dataset is <code>null</code> 726 * or empty). 727 * 728 * @see #findDomainBounds(XYDataset) 729 */ 730 @Override findRangeBounds(XYDataset dataset)731 public Range findRangeBounds(XYDataset dataset) { 732 return findRangeBounds(dataset, false); 733 } 734 735 /** 736 * Returns the range of values the renderer requires to display all the 737 * items from the specified dataset. 738 * 739 * @param dataset the dataset (<code>null</code> permitted). 740 * @param includeInterval include the interval (if any) for the dataset? 741 * 742 * @return The range (<code>null</code> if the dataset is <code>null</code> 743 * or empty). 744 * 745 * @since 1.0.13 746 */ findRangeBounds(XYDataset dataset, boolean includeInterval)747 protected Range findRangeBounds(XYDataset dataset, 748 boolean includeInterval) { 749 if (dataset == null) { 750 return null; 751 } 752 if (getDataBoundsIncludesVisibleSeriesOnly()) { 753 List visibleSeriesKeys = new ArrayList(); 754 int seriesCount = dataset.getSeriesCount(); 755 for (int s = 0; s < seriesCount; s++) { 756 if (isSeriesVisible(s)) { 757 visibleSeriesKeys.add(dataset.getSeriesKey(s)); 758 } 759 } 760 // the bounds should be calculated using just the items within 761 // the current range of the x-axis...if there is one 762 Range xRange = null; 763 XYPlot p = getPlot(); 764 if (p != null) { 765 ValueAxis xAxis = null; 766 int index = p.getIndexOf(this); 767 if (index >= 0) { 768 xAxis = this.plot.getDomainAxisForDataset(index); 769 } 770 if (xAxis != null) { 771 xRange = xAxis.getRange(); 772 } 773 } 774 if (xRange == null) { 775 xRange = new Range(Double.NEGATIVE_INFINITY, 776 Double.POSITIVE_INFINITY); 777 } 778 return DatasetUtilities.findRangeBounds(dataset, 779 visibleSeriesKeys, xRange, includeInterval); 780 } 781 return DatasetUtilities.findRangeBounds(dataset, includeInterval); 782 } 783 784 /** 785 * Returns a (possibly empty) collection of legend items for the series 786 * that this renderer is responsible for drawing. 787 * 788 * @return The legend item collection (never <code>null</code>). 789 */ 790 @Override getLegendItems()791 public LegendItemCollection getLegendItems() { 792 if (this.plot == null) { 793 return new LegendItemCollection(); 794 } 795 LegendItemCollection result = new LegendItemCollection(); 796 int index = this.plot.getIndexOf(this); 797 XYDataset dataset = this.plot.getDataset(index); 798 if (dataset != null) { 799 int seriesCount = dataset.getSeriesCount(); 800 for (int i = 0; i < seriesCount; i++) { 801 if (isSeriesVisibleInLegend(i)) { 802 LegendItem item = getLegendItem(index, i); 803 if (item != null) { 804 result.add(item); 805 } 806 } 807 } 808 809 } 810 return result; 811 } 812 813 /** 814 * Returns a default legend item for the specified series. Subclasses 815 * should override this method to generate customised items. 816 * 817 * @param datasetIndex the dataset index (zero-based). 818 * @param series the series index (zero-based). 819 * 820 * @return A legend item for the series. 821 */ 822 @Override getLegendItem(int datasetIndex, int series)823 public LegendItem getLegendItem(int datasetIndex, int series) { 824 XYPlot xyplot = getPlot(); 825 if (xyplot == null) { 826 return null; 827 } 828 XYDataset dataset = xyplot.getDataset(datasetIndex); 829 if (dataset == null) { 830 return null; 831 } 832 String label = this.legendItemLabelGenerator.generateLabel(dataset, 833 series); 834 String description = label; 835 String toolTipText = null; 836 if (getLegendItemToolTipGenerator() != null) { 837 toolTipText = getLegendItemToolTipGenerator().generateLabel( 838 dataset, series); 839 } 840 String urlText = null; 841 if (getLegendItemURLGenerator() != null) { 842 urlText = getLegendItemURLGenerator().generateLabel(dataset, 843 series); 844 } 845 Shape shape = lookupLegendShape(series); 846 Paint paint = lookupSeriesPaint(series); 847 LegendItem item = new LegendItem(label, paint); 848 item.setToolTipText(toolTipText); 849 item.setURLText(urlText); 850 item.setLabelFont(lookupLegendTextFont(series)); 851 Paint labelPaint = lookupLegendTextPaint(series); 852 if (labelPaint != null) { 853 item.setLabelPaint(labelPaint); 854 } 855 item.setSeriesKey(dataset.getSeriesKey(series)); 856 item.setSeriesIndex(series); 857 item.setDataset(dataset); 858 item.setDatasetIndex(datasetIndex); 859 860 if (getTreatLegendShapeAsLine()) { 861 item.setLineVisible(true); 862 item.setLine(shape); 863 item.setLinePaint(paint); 864 item.setShapeVisible(false); 865 } 866 else { 867 Paint outlinePaint = lookupSeriesOutlinePaint(series); 868 Stroke outlineStroke = lookupSeriesOutlineStroke(series); 869 item.setOutlinePaint(outlinePaint); 870 item.setOutlineStroke(outlineStroke); 871 } 872 return item; 873 } 874 875 /** 876 * Fills a band between two values on the axis. This can be used to color 877 * bands between the grid lines. 878 * 879 * @param g2 the graphics device. 880 * @param plot the plot. 881 * @param axis the domain axis. 882 * @param dataArea the data area. 883 * @param start the start value. 884 * @param end the end value. 885 */ 886 @Override fillDomainGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double start, double end)887 public void fillDomainGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, 888 Rectangle2D dataArea, double start, double end) { 889 890 double x1 = axis.valueToJava2D(start, dataArea, 891 plot.getDomainAxisEdge()); 892 double x2 = axis.valueToJava2D(end, dataArea, 893 plot.getDomainAxisEdge()); 894 Rectangle2D band; 895 if (plot.getOrientation() == PlotOrientation.VERTICAL) { 896 band = new Rectangle2D.Double(Math.min(x1, x2), dataArea.getMinY(), 897 Math.abs(x2 - x1), dataArea.getWidth()); 898 } 899 else { 900 band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(x1, x2), 901 dataArea.getWidth(), Math.abs(x2 - x1)); 902 } 903 Paint paint = plot.getDomainTickBandPaint(); 904 905 if (paint != null) { 906 g2.setPaint(paint); 907 g2.fill(band); 908 } 909 910 } 911 912 /** 913 * Fills a band between two values on the range axis. This can be used to 914 * color bands between the grid lines. 915 * 916 * @param g2 the graphics device. 917 * @param plot the plot. 918 * @param axis the range axis. 919 * @param dataArea the data area. 920 * @param start the start value. 921 * @param end the end value. 922 */ 923 @Override fillRangeGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double start, double end)924 public void fillRangeGridBand(Graphics2D g2, XYPlot plot, ValueAxis axis, 925 Rectangle2D dataArea, double start, double end) { 926 927 double y1 = axis.valueToJava2D(start, dataArea, 928 plot.getRangeAxisEdge()); 929 double y2 = axis.valueToJava2D(end, dataArea, plot.getRangeAxisEdge()); 930 Rectangle2D band; 931 if (plot.getOrientation() == PlotOrientation.VERTICAL) { 932 band = new Rectangle2D.Double(dataArea.getMinX(), Math.min(y1, y2), 933 dataArea.getWidth(), Math.abs(y2 - y1)); 934 } 935 else { 936 band = new Rectangle2D.Double(Math.min(y1, y2), dataArea.getMinY(), 937 Math.abs(y2 - y1), dataArea.getHeight()); 938 } 939 Paint paint = plot.getRangeTickBandPaint(); 940 941 if (paint != null) { 942 g2.setPaint(paint); 943 g2.fill(band); 944 } 945 946 } 947 948 /** 949 * Draws a grid line against the range axis. 950 * 951 * @param g2 the graphics device. 952 * @param plot the plot. 953 * @param axis the value axis. 954 * @param dataArea the area for plotting data (not yet adjusted for any 955 * 3D effect). 956 * @param value the value at which the grid line should be drawn. 957 */ 958 @Override drawDomainGridLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value)959 public void drawDomainGridLine(Graphics2D g2, XYPlot plot, ValueAxis axis, 960 Rectangle2D dataArea, double value) { 961 962 Range range = axis.getRange(); 963 if (!range.contains(value)) { 964 return; 965 } 966 967 PlotOrientation orientation = plot.getOrientation(); 968 double v = axis.valueToJava2D(value, dataArea, 969 plot.getDomainAxisEdge()); 970 Line2D line = null; 971 if (orientation == PlotOrientation.HORIZONTAL) { 972 line = new Line2D.Double(dataArea.getMinX(), v, 973 dataArea.getMaxX(), v); 974 } 975 else if (orientation == PlotOrientation.VERTICAL) { 976 line = new Line2D.Double(v, dataArea.getMinY(), v, 977 dataArea.getMaxY()); 978 } 979 980 Paint paint = plot.getDomainGridlinePaint(); 981 Stroke stroke = plot.getDomainGridlineStroke(); 982 g2.setPaint(paint != null ? paint : Plot.DEFAULT_OUTLINE_PAINT); 983 g2.setStroke(stroke != null ? stroke : Plot.DEFAULT_OUTLINE_STROKE); 984 g2.draw(line); 985 986 } 987 988 /** 989 * Draws a line perpendicular to the domain axis. 990 * 991 * @param g2 the graphics device. 992 * @param plot the plot. 993 * @param axis the value axis. 994 * @param dataArea the area for plotting data (not yet adjusted for any 3D 995 * effect). 996 * @param value the value at which the grid line should be drawn. 997 * @param paint the paint (<code>null</code> not permitted). 998 * @param stroke the stroke (<code>null</code> not permitted). 999 * 1000 * @since 1.0.5 1001 */ drawDomainLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value, Paint paint, Stroke stroke)1002 public void drawDomainLine(Graphics2D g2, XYPlot plot, ValueAxis axis, 1003 Rectangle2D dataArea, double value, Paint paint, Stroke stroke) { 1004 1005 Range range = axis.getRange(); 1006 if (!range.contains(value)) { 1007 return; 1008 } 1009 1010 PlotOrientation orientation = plot.getOrientation(); 1011 Line2D line = null; 1012 double v = axis.valueToJava2D(value, dataArea, 1013 plot.getDomainAxisEdge()); 1014 if (orientation == PlotOrientation.HORIZONTAL) { 1015 line = new Line2D.Double(dataArea.getMinX(), v, dataArea.getMaxX(), 1016 v); 1017 } 1018 else if (orientation == PlotOrientation.VERTICAL) { 1019 line = new Line2D.Double(v, dataArea.getMinY(), v, 1020 dataArea.getMaxY()); 1021 } 1022 1023 g2.setPaint(paint); 1024 g2.setStroke(stroke); 1025 g2.draw(line); 1026 1027 } 1028 1029 /** 1030 * Draws a line perpendicular to the range axis. 1031 * 1032 * @param g2 the graphics device. 1033 * @param plot the plot. 1034 * @param axis the value axis. 1035 * @param dataArea the area for plotting data (not yet adjusted for any 3D 1036 * effect). 1037 * @param value the value at which the grid line should be drawn. 1038 * @param paint the paint. 1039 * @param stroke the stroke. 1040 */ 1041 @Override drawRangeLine(Graphics2D g2, XYPlot plot, ValueAxis axis, Rectangle2D dataArea, double value, Paint paint, Stroke stroke)1042 public void drawRangeLine(Graphics2D g2, XYPlot plot, ValueAxis axis, 1043 Rectangle2D dataArea, double value, Paint paint, Stroke stroke) { 1044 1045 Range range = axis.getRange(); 1046 if (!range.contains(value)) { 1047 return; 1048 } 1049 1050 PlotOrientation orientation = plot.getOrientation(); 1051 Line2D line = null; 1052 double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge()); 1053 if (orientation == PlotOrientation.HORIZONTAL) { 1054 line = new Line2D.Double(v, dataArea.getMinY(), v, 1055 dataArea.getMaxY()); 1056 } 1057 else if (orientation == PlotOrientation.VERTICAL) { 1058 line = new Line2D.Double(dataArea.getMinX(), v, 1059 dataArea.getMaxX(), v); 1060 } 1061 1062 g2.setPaint(paint); 1063 g2.setStroke(stroke); 1064 g2.draw(line); 1065 1066 } 1067 1068 /** 1069 * Draws a vertical line on the chart to represent a 'range marker'. 1070 * 1071 * @param g2 the graphics device. 1072 * @param plot the plot. 1073 * @param domainAxis the domain axis. 1074 * @param marker the marker line. 1075 * @param dataArea the axis data area. 1076 */ 1077 @Override drawDomainMarker(Graphics2D g2, XYPlot plot, ValueAxis domainAxis, Marker marker, Rectangle2D dataArea)1078 public void drawDomainMarker(Graphics2D g2, XYPlot plot, 1079 ValueAxis domainAxis, Marker marker, Rectangle2D dataArea) { 1080 1081 if (marker instanceof ValueMarker) { 1082 ValueMarker vm = (ValueMarker) marker; 1083 double value = vm.getValue(); 1084 Range range = domainAxis.getRange(); 1085 if (!range.contains(value)) { 1086 return; 1087 } 1088 1089 double v = domainAxis.valueToJava2D(value, dataArea, 1090 plot.getDomainAxisEdge()); 1091 1092 PlotOrientation orientation = plot.getOrientation(); 1093 Line2D line = null; 1094 if (orientation == PlotOrientation.HORIZONTAL) { 1095 line = new Line2D.Double(dataArea.getMinX(), v, 1096 dataArea.getMaxX(), v); 1097 } 1098 else if (orientation == PlotOrientation.VERTICAL) { 1099 line = new Line2D.Double(v, dataArea.getMinY(), v, 1100 dataArea.getMaxY()); 1101 } else { 1102 throw new IllegalStateException(); 1103 } 1104 1105 final Composite originalComposite = g2.getComposite(); 1106 g2.setComposite(AlphaComposite.getInstance( 1107 AlphaComposite.SRC_OVER, marker.getAlpha())); 1108 g2.setPaint(marker.getPaint()); 1109 g2.setStroke(marker.getStroke()); 1110 g2.draw(line); 1111 1112 String label = marker.getLabel(); 1113 RectangleAnchor anchor = marker.getLabelAnchor(); 1114 if (label != null) { 1115 Font labelFont = marker.getLabelFont(); 1116 g2.setFont(labelFont); 1117 g2.setPaint(marker.getLabelPaint()); 1118 Point2D coordinates = calculateDomainMarkerTextAnchorPoint( 1119 g2, orientation, dataArea, line.getBounds2D(), 1120 marker.getLabelOffset(), 1121 LengthAdjustmentType.EXPAND, anchor); 1122 TextUtilities.drawAlignedString(label, g2, 1123 (float) coordinates.getX(), (float) coordinates.getY(), 1124 marker.getLabelTextAnchor()); 1125 } 1126 g2.setComposite(originalComposite); 1127 } 1128 else if (marker instanceof IntervalMarker) { 1129 IntervalMarker im = (IntervalMarker) marker; 1130 double start = im.getStartValue(); 1131 double end = im.getEndValue(); 1132 Range range = domainAxis.getRange(); 1133 if (!(range.intersects(start, end))) { 1134 return; 1135 } 1136 1137 double start2d = domainAxis.valueToJava2D(start, dataArea, 1138 plot.getDomainAxisEdge()); 1139 double end2d = domainAxis.valueToJava2D(end, dataArea, 1140 plot.getDomainAxisEdge()); 1141 double low = Math.min(start2d, end2d); 1142 double high = Math.max(start2d, end2d); 1143 1144 PlotOrientation orientation = plot.getOrientation(); 1145 Rectangle2D rect = null; 1146 if (orientation == PlotOrientation.HORIZONTAL) { 1147 // clip top and bottom bounds to data area 1148 low = Math.max(low, dataArea.getMinY()); 1149 high = Math.min(high, dataArea.getMaxY()); 1150 rect = new Rectangle2D.Double(dataArea.getMinX(), 1151 low, dataArea.getWidth(), 1152 high - low); 1153 } 1154 else if (orientation == PlotOrientation.VERTICAL) { 1155 // clip left and right bounds to data area 1156 low = Math.max(low, dataArea.getMinX()); 1157 high = Math.min(high, dataArea.getMaxX()); 1158 rect = new Rectangle2D.Double(low, 1159 dataArea.getMinY(), high - low, 1160 dataArea.getHeight()); 1161 } 1162 1163 final Composite originalComposite = g2.getComposite(); 1164 g2.setComposite(AlphaComposite.getInstance( 1165 AlphaComposite.SRC_OVER, marker.getAlpha())); 1166 Paint p = marker.getPaint(); 1167 if (p instanceof GradientPaint) { 1168 GradientPaint gp = (GradientPaint) p; 1169 GradientPaintTransformer t = im.getGradientPaintTransformer(); 1170 if (t != null) { 1171 gp = t.transform(gp, rect); 1172 } 1173 g2.setPaint(gp); 1174 } 1175 else { 1176 g2.setPaint(p); 1177 } 1178 g2.fill(rect); 1179 1180 // now draw the outlines, if visible... 1181 if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) { 1182 if (orientation == PlotOrientation.VERTICAL) { 1183 Line2D line = new Line2D.Double(); 1184 double y0 = dataArea.getMinY(); 1185 double y1 = dataArea.getMaxY(); 1186 g2.setPaint(im.getOutlinePaint()); 1187 g2.setStroke(im.getOutlineStroke()); 1188 if (range.contains(start)) { 1189 line.setLine(start2d, y0, start2d, y1); 1190 g2.draw(line); 1191 } 1192 if (range.contains(end)) { 1193 line.setLine(end2d, y0, end2d, y1); 1194 g2.draw(line); 1195 } 1196 } 1197 else { // PlotOrientation.HORIZONTAL 1198 Line2D line = new Line2D.Double(); 1199 double x0 = dataArea.getMinX(); 1200 double x1 = dataArea.getMaxX(); 1201 g2.setPaint(im.getOutlinePaint()); 1202 g2.setStroke(im.getOutlineStroke()); 1203 if (range.contains(start)) { 1204 line.setLine(x0, start2d, x1, start2d); 1205 g2.draw(line); 1206 } 1207 if (range.contains(end)) { 1208 line.setLine(x0, end2d, x1, end2d); 1209 g2.draw(line); 1210 } 1211 } 1212 } 1213 1214 String label = marker.getLabel(); 1215 RectangleAnchor anchor = marker.getLabelAnchor(); 1216 if (label != null) { 1217 Font labelFont = marker.getLabelFont(); 1218 g2.setFont(labelFont); 1219 g2.setPaint(marker.getLabelPaint()); 1220 Point2D coordinates = calculateDomainMarkerTextAnchorPoint( 1221 g2, orientation, dataArea, rect, 1222 marker.getLabelOffset(), marker.getLabelOffsetType(), 1223 anchor); 1224 TextUtilities.drawAlignedString(label, g2, 1225 (float) coordinates.getX(), (float) coordinates.getY(), 1226 marker.getLabelTextAnchor()); 1227 } 1228 g2.setComposite(originalComposite); 1229 1230 } 1231 1232 } 1233 1234 /** 1235 * Calculates the (x, y) coordinates for drawing a marker label. 1236 * 1237 * @param g2 the graphics device. 1238 * @param orientation the plot orientation. 1239 * @param dataArea the data area. 1240 * @param markerArea the rectangle surrounding the marker area. 1241 * @param markerOffset the marker label offset. 1242 * @param labelOffsetType the label offset type. 1243 * @param anchor the label anchor. 1244 * 1245 * @return The coordinates for drawing the marker label. 1246 */ calculateDomainMarkerTextAnchorPoint(Graphics2D g2, PlotOrientation orientation, Rectangle2D dataArea, Rectangle2D markerArea, RectangleInsets markerOffset, LengthAdjustmentType labelOffsetType, RectangleAnchor anchor)1247 protected Point2D calculateDomainMarkerTextAnchorPoint(Graphics2D g2, 1248 PlotOrientation orientation, Rectangle2D dataArea, 1249 Rectangle2D markerArea, RectangleInsets markerOffset, 1250 LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) { 1251 1252 Rectangle2D anchorRect = null; 1253 if (orientation == PlotOrientation.HORIZONTAL) { 1254 anchorRect = markerOffset.createAdjustedRectangle(markerArea, 1255 LengthAdjustmentType.CONTRACT, labelOffsetType); 1256 } 1257 else if (orientation == PlotOrientation.VERTICAL) { 1258 anchorRect = markerOffset.createAdjustedRectangle(markerArea, 1259 labelOffsetType, LengthAdjustmentType.CONTRACT); 1260 } 1261 return RectangleAnchor.coordinates(anchorRect, anchor); 1262 1263 } 1264 1265 /** 1266 * Draws a horizontal line across the chart to represent a 'range marker'. 1267 * 1268 * @param g2 the graphics device. 1269 * @param plot the plot. 1270 * @param rangeAxis the range axis. 1271 * @param marker the marker line. 1272 * @param dataArea the axis data area. 1273 */ 1274 @Override drawRangeMarker(Graphics2D g2, XYPlot plot, ValueAxis rangeAxis, Marker marker, Rectangle2D dataArea)1275 public void drawRangeMarker(Graphics2D g2, XYPlot plot, ValueAxis rangeAxis, 1276 Marker marker, Rectangle2D dataArea) { 1277 1278 if (marker instanceof ValueMarker) { 1279 ValueMarker vm = (ValueMarker) marker; 1280 double value = vm.getValue(); 1281 Range range = rangeAxis.getRange(); 1282 if (!range.contains(value)) { 1283 return; 1284 } 1285 1286 double v = rangeAxis.valueToJava2D(value, dataArea, 1287 plot.getRangeAxisEdge()); 1288 PlotOrientation orientation = plot.getOrientation(); 1289 Line2D line = null; 1290 if (orientation == PlotOrientation.HORIZONTAL) { 1291 line = new Line2D.Double(v, dataArea.getMinY(), v, 1292 dataArea.getMaxY()); 1293 } 1294 else if (orientation == PlotOrientation.VERTICAL) { 1295 line = new Line2D.Double(dataArea.getMinX(), v, 1296 dataArea.getMaxX(), v); 1297 } 1298 else { 1299 throw new IllegalStateException("Unknown orientation."); 1300 } 1301 1302 final Composite originalComposite = g2.getComposite(); 1303 g2.setComposite(AlphaComposite.getInstance( 1304 AlphaComposite.SRC_OVER, marker.getAlpha())); 1305 g2.setPaint(marker.getPaint()); 1306 g2.setStroke(marker.getStroke()); 1307 g2.draw(line); 1308 1309 String label = marker.getLabel(); 1310 RectangleAnchor anchor = marker.getLabelAnchor(); 1311 if (label != null) { 1312 Font labelFont = marker.getLabelFont(); 1313 g2.setFont(labelFont); 1314 g2.setPaint(marker.getLabelPaint()); 1315 Point2D coordinates = calculateRangeMarkerTextAnchorPoint( 1316 g2, orientation, dataArea, line.getBounds2D(), 1317 marker.getLabelOffset(), 1318 LengthAdjustmentType.EXPAND, anchor); 1319 TextUtilities.drawAlignedString(label, g2, 1320 (float) coordinates.getX(), (float) coordinates.getY(), 1321 marker.getLabelTextAnchor()); 1322 } 1323 g2.setComposite(originalComposite); 1324 } 1325 else if (marker instanceof IntervalMarker) { 1326 IntervalMarker im = (IntervalMarker) marker; 1327 double start = im.getStartValue(); 1328 double end = im.getEndValue(); 1329 Range range = rangeAxis.getRange(); 1330 if (!(range.intersects(start, end))) { 1331 return; 1332 } 1333 1334 double start2d = rangeAxis.valueToJava2D(start, dataArea, 1335 plot.getRangeAxisEdge()); 1336 double end2d = rangeAxis.valueToJava2D(end, dataArea, 1337 plot.getRangeAxisEdge()); 1338 double low = Math.min(start2d, end2d); 1339 double high = Math.max(start2d, end2d); 1340 1341 PlotOrientation orientation = plot.getOrientation(); 1342 Rectangle2D rect = null; 1343 if (orientation == PlotOrientation.HORIZONTAL) { 1344 // clip left and right bounds to data area 1345 low = Math.max(low, dataArea.getMinX()); 1346 high = Math.min(high, dataArea.getMaxX()); 1347 rect = new Rectangle2D.Double(low, 1348 dataArea.getMinY(), high - low, 1349 dataArea.getHeight()); 1350 } 1351 else if (orientation == PlotOrientation.VERTICAL) { 1352 // clip top and bottom bounds to data area 1353 low = Math.max(low, dataArea.getMinY()); 1354 high = Math.min(high, dataArea.getMaxY()); 1355 rect = new Rectangle2D.Double(dataArea.getMinX(), 1356 low, dataArea.getWidth(), 1357 high - low); 1358 } 1359 1360 final Composite originalComposite = g2.getComposite(); 1361 g2.setComposite(AlphaComposite.getInstance( 1362 AlphaComposite.SRC_OVER, marker.getAlpha())); 1363 Paint p = marker.getPaint(); 1364 if (p instanceof GradientPaint) { 1365 GradientPaint gp = (GradientPaint) p; 1366 GradientPaintTransformer t = im.getGradientPaintTransformer(); 1367 if (t != null) { 1368 gp = t.transform(gp, rect); 1369 } 1370 g2.setPaint(gp); 1371 } 1372 else { 1373 g2.setPaint(p); 1374 } 1375 g2.fill(rect); 1376 1377 // now draw the outlines, if visible... 1378 if (im.getOutlinePaint() != null && im.getOutlineStroke() != null) { 1379 if (orientation == PlotOrientation.VERTICAL) { 1380 Line2D line = new Line2D.Double(); 1381 double x0 = dataArea.getMinX(); 1382 double x1 = dataArea.getMaxX(); 1383 g2.setPaint(im.getOutlinePaint()); 1384 g2.setStroke(im.getOutlineStroke()); 1385 if (range.contains(start)) { 1386 line.setLine(x0, start2d, x1, start2d); 1387 g2.draw(line); 1388 } 1389 if (range.contains(end)) { 1390 line.setLine(x0, end2d, x1, end2d); 1391 g2.draw(line); 1392 } 1393 } 1394 else { // PlotOrientation.HORIZONTAL 1395 Line2D line = new Line2D.Double(); 1396 double y0 = dataArea.getMinY(); 1397 double y1 = dataArea.getMaxY(); 1398 g2.setPaint(im.getOutlinePaint()); 1399 g2.setStroke(im.getOutlineStroke()); 1400 if (range.contains(start)) { 1401 line.setLine(start2d, y0, start2d, y1); 1402 g2.draw(line); 1403 } 1404 if (range.contains(end)) { 1405 line.setLine(end2d, y0, end2d, y1); 1406 g2.draw(line); 1407 } 1408 } 1409 } 1410 1411 String label = marker.getLabel(); 1412 RectangleAnchor anchor = marker.getLabelAnchor(); 1413 if (label != null) { 1414 Font labelFont = marker.getLabelFont(); 1415 g2.setFont(labelFont); 1416 g2.setPaint(marker.getLabelPaint()); 1417 Point2D coordinates = calculateRangeMarkerTextAnchorPoint( 1418 g2, orientation, dataArea, rect, 1419 marker.getLabelOffset(), marker.getLabelOffsetType(), 1420 anchor); 1421 TextUtilities.drawAlignedString(label, g2, 1422 (float) coordinates.getX(), (float) coordinates.getY(), 1423 marker.getLabelTextAnchor()); 1424 } 1425 g2.setComposite(originalComposite); 1426 } 1427 } 1428 1429 /** 1430 * Calculates the (x, y) coordinates for drawing a marker label. 1431 * 1432 * @param g2 the graphics device. 1433 * @param orientation the plot orientation. 1434 * @param dataArea the data area. 1435 * @param markerArea the marker area. 1436 * @param markerOffset the marker offset. 1437 * @param labelOffsetForRange ?? 1438 * @param anchor the label anchor. 1439 * 1440 * @return The coordinates for drawing the marker label. 1441 */ calculateRangeMarkerTextAnchorPoint(Graphics2D g2, PlotOrientation orientation, Rectangle2D dataArea, Rectangle2D markerArea, RectangleInsets markerOffset, LengthAdjustmentType labelOffsetForRange, RectangleAnchor anchor)1442 private Point2D calculateRangeMarkerTextAnchorPoint(Graphics2D g2, 1443 PlotOrientation orientation, Rectangle2D dataArea, 1444 Rectangle2D markerArea, RectangleInsets markerOffset, 1445 LengthAdjustmentType labelOffsetForRange, RectangleAnchor anchor) { 1446 1447 Rectangle2D anchorRect = null; 1448 if (orientation == PlotOrientation.HORIZONTAL) { 1449 anchorRect = markerOffset.createAdjustedRectangle(markerArea, 1450 labelOffsetForRange, LengthAdjustmentType.CONTRACT); 1451 } 1452 else if (orientation == PlotOrientation.VERTICAL) { 1453 anchorRect = markerOffset.createAdjustedRectangle(markerArea, 1454 LengthAdjustmentType.CONTRACT, labelOffsetForRange); 1455 } 1456 return RectangleAnchor.coordinates(anchorRect, anchor); 1457 1458 } 1459 1460 /** 1461 * Returns a clone of the renderer. 1462 * 1463 * @return A clone. 1464 * 1465 * @throws CloneNotSupportedException if the renderer does not support 1466 * cloning. 1467 */ 1468 @Override clone()1469 protected Object clone() throws CloneNotSupportedException { 1470 AbstractXYItemRenderer clone = (AbstractXYItemRenderer) super.clone(); 1471 // 'plot' : just retain reference, not a deep copy 1472 1473 if (this.itemLabelGenerator != null 1474 && this.itemLabelGenerator instanceof PublicCloneable) { 1475 PublicCloneable pc = (PublicCloneable) this.itemLabelGenerator; 1476 clone.itemLabelGenerator = (XYItemLabelGenerator) pc.clone(); 1477 } 1478 clone.itemLabelGeneratorList 1479 = (ObjectList) this.itemLabelGeneratorList.clone(); 1480 if (this.baseItemLabelGenerator != null 1481 && this.baseItemLabelGenerator instanceof PublicCloneable) { 1482 PublicCloneable pc = (PublicCloneable) this.baseItemLabelGenerator; 1483 clone.baseItemLabelGenerator = (XYItemLabelGenerator) pc.clone(); 1484 } 1485 1486 if (this.toolTipGenerator != null 1487 && this.toolTipGenerator instanceof PublicCloneable) { 1488 PublicCloneable pc = (PublicCloneable) this.toolTipGenerator; 1489 clone.toolTipGenerator = (XYToolTipGenerator) pc.clone(); 1490 } 1491 clone.toolTipGeneratorList 1492 = (ObjectList) this.toolTipGeneratorList.clone(); 1493 if (this.baseToolTipGenerator != null 1494 && this.baseToolTipGenerator instanceof PublicCloneable) { 1495 PublicCloneable pc = (PublicCloneable) this.baseToolTipGenerator; 1496 clone.baseToolTipGenerator = (XYToolTipGenerator) pc.clone(); 1497 } 1498 1499 if (this.legendItemLabelGenerator instanceof PublicCloneable) { 1500 clone.legendItemLabelGenerator = (XYSeriesLabelGenerator) 1501 ObjectUtilities.clone(this.legendItemLabelGenerator); 1502 } 1503 if (this.legendItemToolTipGenerator instanceof PublicCloneable) { 1504 clone.legendItemToolTipGenerator = (XYSeriesLabelGenerator) 1505 ObjectUtilities.clone(this.legendItemToolTipGenerator); 1506 } 1507 if (this.legendItemURLGenerator instanceof PublicCloneable) { 1508 clone.legendItemURLGenerator = (XYSeriesLabelGenerator) 1509 ObjectUtilities.clone(this.legendItemURLGenerator); 1510 } 1511 1512 clone.foregroundAnnotations = (List) ObjectUtilities.deepClone( 1513 this.foregroundAnnotations); 1514 clone.backgroundAnnotations = (List) ObjectUtilities.deepClone( 1515 this.backgroundAnnotations); 1516 1517 return clone; 1518 } 1519 1520 /** 1521 * Tests this renderer for equality with another object. 1522 * 1523 * @param obj the object (<code>null</code> permitted). 1524 * 1525 * @return <code>true</code> or <code>false</code>. 1526 */ 1527 @Override equals(Object obj)1528 public boolean equals(Object obj) { 1529 if (obj == this) { 1530 return true; 1531 } 1532 if (!(obj instanceof AbstractXYItemRenderer)) { 1533 return false; 1534 } 1535 AbstractXYItemRenderer that = (AbstractXYItemRenderer) obj; 1536 if (!ObjectUtilities.equal(this.itemLabelGenerator, 1537 that.itemLabelGenerator)) { 1538 return false; 1539 } 1540 if (!this.itemLabelGeneratorList.equals(that.itemLabelGeneratorList)) { 1541 return false; 1542 } 1543 if (!ObjectUtilities.equal(this.baseItemLabelGenerator, 1544 that.baseItemLabelGenerator)) { 1545 return false; 1546 } 1547 if (!ObjectUtilities.equal(this.toolTipGenerator, 1548 that.toolTipGenerator)) { 1549 return false; 1550 } 1551 if (!this.toolTipGeneratorList.equals(that.toolTipGeneratorList)) { 1552 return false; 1553 } 1554 if (!ObjectUtilities.equal(this.baseToolTipGenerator, 1555 that.baseToolTipGenerator)) { 1556 return false; 1557 } 1558 if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) { 1559 return false; 1560 } 1561 if (!this.foregroundAnnotations.equals(that.foregroundAnnotations)) { 1562 return false; 1563 } 1564 if (!this.backgroundAnnotations.equals(that.backgroundAnnotations)) { 1565 return false; 1566 } 1567 if (!ObjectUtilities.equal(this.legendItemLabelGenerator, 1568 that.legendItemLabelGenerator)) { 1569 return false; 1570 } 1571 if (!ObjectUtilities.equal(this.legendItemToolTipGenerator, 1572 that.legendItemToolTipGenerator)) { 1573 return false; 1574 } 1575 if (!ObjectUtilities.equal(this.legendItemURLGenerator, 1576 that.legendItemURLGenerator)) { 1577 return false; 1578 } 1579 return super.equals(obj); 1580 } 1581 1582 /** 1583 * Returns the drawing supplier from the plot. 1584 * 1585 * @return The drawing supplier (possibly <code>null</code>). 1586 */ 1587 @Override getDrawingSupplier()1588 public DrawingSupplier getDrawingSupplier() { 1589 DrawingSupplier result = null; 1590 XYPlot p = getPlot(); 1591 if (p != null) { 1592 result = p.getDrawingSupplier(); 1593 } 1594 return result; 1595 } 1596 1597 /** 1598 * Considers the current (x, y) coordinate and updates the crosshair point 1599 * if it meets the criteria (usually means the (x, y) coordinate is the 1600 * closest to the anchor point so far). 1601 * 1602 * @param crosshairState the crosshair state (<code>null</code> permitted, 1603 * but the method does nothing in that case). 1604 * @param x the x-value (in data space). 1605 * @param y the y-value (in data space). 1606 * @param domainAxisIndex the index of the domain axis for the point. 1607 * @param rangeAxisIndex the index of the range axis for the point. 1608 * @param transX the x-value translated to Java2D space. 1609 * @param transY the y-value translated to Java2D space. 1610 * @param orientation the plot orientation (<code>null</code> not 1611 * permitted). 1612 * 1613 * @since 1.0.4 1614 */ updateCrosshairValues(CrosshairState crosshairState, double x, double y, int domainAxisIndex, int rangeAxisIndex, double transX, double transY, PlotOrientation orientation)1615 protected void updateCrosshairValues(CrosshairState crosshairState, 1616 double x, double y, int domainAxisIndex, int rangeAxisIndex, 1617 double transX, double transY, PlotOrientation orientation) { 1618 1619 ParamChecks.nullNotPermitted(orientation, "orientation"); 1620 if (crosshairState != null) { 1621 // do we need to update the crosshair values? 1622 if (this.plot.isDomainCrosshairLockedOnData()) { 1623 if (this.plot.isRangeCrosshairLockedOnData()) { 1624 // both axes 1625 crosshairState.updateCrosshairPoint(x, y, domainAxisIndex, 1626 rangeAxisIndex, transX, transY, orientation); 1627 } 1628 else { 1629 // just the domain axis... 1630 crosshairState.updateCrosshairX(x, domainAxisIndex); 1631 } 1632 } 1633 else { 1634 if (this.plot.isRangeCrosshairLockedOnData()) { 1635 // just the range axis... 1636 crosshairState.updateCrosshairY(y, rangeAxisIndex); 1637 } 1638 } 1639 } 1640 1641 } 1642 1643 /** 1644 * Draws an item label. 1645 * 1646 * @param g2 the graphics device. 1647 * @param orientation the orientation. 1648 * @param dataset the dataset. 1649 * @param series the series index (zero-based). 1650 * @param item the item index (zero-based). 1651 * @param x the x coordinate (in Java2D space). 1652 * @param y the y coordinate (in Java2D space). 1653 * @param negative indicates a negative value (which affects the item 1654 * label position). 1655 */ drawItemLabel(Graphics2D g2, PlotOrientation orientation, XYDataset dataset, int series, int item, double x, double y, boolean negative)1656 protected void drawItemLabel(Graphics2D g2, PlotOrientation orientation, 1657 XYDataset dataset, int series, int item, double x, double y, 1658 boolean negative) { 1659 1660 XYItemLabelGenerator generator = getItemLabelGenerator(series, item); 1661 if (generator != null) { 1662 Font labelFont = getItemLabelFont(series, item); 1663 Paint paint = getItemLabelPaint(series, item); 1664 g2.setFont(labelFont); 1665 g2.setPaint(paint); 1666 String label = generator.generateLabel(dataset, series, item); 1667 1668 // get the label position.. 1669 ItemLabelPosition position; 1670 if (!negative) { 1671 position = getPositiveItemLabelPosition(series, item); 1672 } 1673 else { 1674 position = getNegativeItemLabelPosition(series, item); 1675 } 1676 1677 // work out the label anchor point... 1678 Point2D anchorPoint = calculateLabelAnchorPoint( 1679 position.getItemLabelAnchor(), x, y, orientation); 1680 TextUtilities.drawRotatedString(label, g2, 1681 (float) anchorPoint.getX(), (float) anchorPoint.getY(), 1682 position.getTextAnchor(), position.getAngle(), 1683 position.getRotationAnchor()); 1684 } 1685 1686 } 1687 1688 /** 1689 * Draws all the annotations for the specified layer. 1690 * 1691 * @param g2 the graphics device. 1692 * @param dataArea the data area. 1693 * @param domainAxis the domain axis. 1694 * @param rangeAxis the range axis. 1695 * @param layer the layer. 1696 * @param info the plot rendering info. 1697 */ 1698 @Override drawAnnotations(Graphics2D g2, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, Layer layer, PlotRenderingInfo info)1699 public void drawAnnotations(Graphics2D g2, Rectangle2D dataArea, 1700 ValueAxis domainAxis, ValueAxis rangeAxis, Layer layer, 1701 PlotRenderingInfo info) { 1702 1703 Iterator iterator = null; 1704 if (layer.equals(Layer.FOREGROUND)) { 1705 iterator = this.foregroundAnnotations.iterator(); 1706 } 1707 else if (layer.equals(Layer.BACKGROUND)) { 1708 iterator = this.backgroundAnnotations.iterator(); 1709 } 1710 else { 1711 // should not get here 1712 throw new RuntimeException("Unknown layer."); 1713 } 1714 while (iterator.hasNext()) { 1715 XYAnnotation annotation = (XYAnnotation) iterator.next(); 1716 int index = this.plot.getIndexOf(this); 1717 annotation.draw(g2, this.plot, dataArea, domainAxis, rangeAxis, 1718 index, info); 1719 } 1720 1721 } 1722 1723 /** 1724 * Adds an entity to the collection. 1725 * 1726 * @param entities the entity collection being populated. 1727 * @param area the entity area (if <code>null</code> a default will be 1728 * used). 1729 * @param dataset the dataset. 1730 * @param series the series. 1731 * @param item the item. 1732 * @param entityX the entity's center x-coordinate in user space (only 1733 * used if <code>area</code> is <code>null</code>). 1734 * @param entityY the entity's center y-coordinate in user space (only 1735 * used if <code>area</code> is <code>null</code>). 1736 */ addEntity(EntityCollection entities, Shape area, XYDataset dataset, int series, int item, double entityX, double entityY)1737 protected void addEntity(EntityCollection entities, Shape area, 1738 XYDataset dataset, int series, int item, 1739 double entityX, double entityY) { 1740 if (!getItemCreateEntity(series, item)) { 1741 return; 1742 } 1743 Shape hotspot = area; 1744 if (hotspot == null) { 1745 double r = getDefaultEntityRadius(); 1746 double w = r * 2; 1747 if (getPlot().getOrientation() == PlotOrientation.VERTICAL) { 1748 hotspot = new Ellipse2D.Double(entityX - r, entityY - r, w, w); 1749 } 1750 else { 1751 hotspot = new Ellipse2D.Double(entityY - r, entityX - r, w, w); 1752 } 1753 } 1754 String tip = null; 1755 XYToolTipGenerator generator = getToolTipGenerator(series, item); 1756 if (generator != null) { 1757 tip = generator.generateToolTip(dataset, series, item); 1758 } 1759 String url = null; 1760 if (getURLGenerator() != null) { 1761 url = getURLGenerator().generateURL(dataset, series, item); 1762 } 1763 XYItemEntity entity = new XYItemEntity(hotspot, dataset, series, item, 1764 tip, url); 1765 entities.add(entity); 1766 } 1767 1768 /** 1769 * Returns <code>true</code> if the specified point (x, y) falls within or 1770 * on the boundary of the specified rectangle. 1771 * 1772 * @param rect the rectangle (<code>null</code> not permitted). 1773 * @param x the x-coordinate. 1774 * @param y the y-coordinate. 1775 * 1776 * @return A boolean. 1777 * 1778 * @since 1.0.10 1779 */ isPointInRect(Rectangle2D rect, double x, double y)1780 public static boolean isPointInRect(Rectangle2D rect, double x, double y) { 1781 // TODO: For JFreeChart 1.2.0, this method should go in the 1782 // ShapeUtilities class 1783 return (x >= rect.getMinX() && x <= rect.getMaxX() 1784 && y >= rect.getMinY() && y <= rect.getMaxY()); 1785 } 1786 1787 /** 1788 * Utility method delegating to {@link GeneralPath#moveTo} taking double as 1789 * parameters. 1790 * 1791 * @param hotspot the region under construction (<code>null</code> not 1792 * permitted); 1793 * @param x the x coordinate; 1794 * @param y the y coordinate; 1795 * 1796 * @since 1.0.14 1797 */ moveTo(GeneralPath hotspot, double x, double y)1798 protected static void moveTo(GeneralPath hotspot, double x, double y) { 1799 hotspot.moveTo((float) x, (float) y); 1800 } 1801 1802 /** 1803 * Utility method delegating to {@link GeneralPath#lineTo} taking double as 1804 * parameters. 1805 * 1806 * @param hotspot the region under construction (<code>null</code> not 1807 * permitted); 1808 * @param x the x coordinate; 1809 * @param y the y coordinate; 1810 * 1811 * @since 1.0.14 1812 */ lineTo(GeneralPath hotspot, double x, double y)1813 protected static void lineTo(GeneralPath hotspot, double x, double y) { 1814 hotspot.lineTo((float) x, (float) y); 1815 } 1816 1817 // === DEPRECATED CODE === 1818 1819 /** 1820 * The item label generator for ALL series. 1821 * 1822 * @deprecated This field is redundant, use itemLabelGeneratorList and 1823 * baseItemLabelGenerator instead. Deprecated as of version 1.0.6. 1824 */ 1825 private XYItemLabelGenerator itemLabelGenerator; 1826 1827 /** 1828 * The tool tip generator for ALL series. 1829 * 1830 * @deprecated This field is redundant, use tooltipGeneratorList and 1831 * baseToolTipGenerator instead. Deprecated as of version 1.0.6. 1832 */ 1833 private XYToolTipGenerator toolTipGenerator; 1834 1835 /** 1836 * Returns the item label generator override. 1837 * 1838 * @return The generator (possibly <code>null</code>). 1839 * 1840 * @since 1.0.5 1841 * 1842 * @see #setItemLabelGenerator(XYItemLabelGenerator) 1843 * 1844 * @deprecated As of version 1.0.6, this override setting should not be 1845 * used. You can use the base setting instead 1846 * ({@link #getBaseItemLabelGenerator()}). 1847 */ getItemLabelGenerator()1848 public XYItemLabelGenerator getItemLabelGenerator() { 1849 return this.itemLabelGenerator; 1850 } 1851 1852 /** 1853 * Sets the item label generator for ALL series and sends a 1854 * {@link RendererChangeEvent} to all registered listeners. 1855 * 1856 * @param generator the generator (<code>null</code> permitted). 1857 * 1858 * @see #getItemLabelGenerator() 1859 * 1860 * @deprecated As of version 1.0.6, this override setting should not be 1861 * used. You can use the base setting instead 1862 * ({@link #setBaseItemLabelGenerator(XYItemLabelGenerator)}). 1863 */ 1864 @Override setItemLabelGenerator(XYItemLabelGenerator generator)1865 public void setItemLabelGenerator(XYItemLabelGenerator generator) { 1866 this.itemLabelGenerator = generator; 1867 fireChangeEvent(); 1868 } 1869 1870 /** 1871 * Returns the override tool tip generator. 1872 * 1873 * @return The tool tip generator (possible <code>null</code>). 1874 * 1875 * @since 1.0.5 1876 * 1877 * @see #setToolTipGenerator(XYToolTipGenerator) 1878 * 1879 * @deprecated As of version 1.0.6, this override setting should not be 1880 * used. You can use the base setting instead 1881 * ({@link #getBaseToolTipGenerator()}). 1882 */ getToolTipGenerator()1883 public XYToolTipGenerator getToolTipGenerator() { 1884 return this.toolTipGenerator; 1885 } 1886 1887 /** 1888 * Sets the tool tip generator for ALL series and sends a 1889 * {@link RendererChangeEvent} to all registered listeners. 1890 * 1891 * @param generator the generator (<code>null</code> permitted). 1892 * 1893 * @see #getToolTipGenerator() 1894 * 1895 * @deprecated As of version 1.0.6, this override setting should not be 1896 * used. You can use the base setting instead 1897 * ({@link #setBaseToolTipGenerator(XYToolTipGenerator)}). 1898 */ 1899 @Override setToolTipGenerator(XYToolTipGenerator generator)1900 public void setToolTipGenerator(XYToolTipGenerator generator) { 1901 this.toolTipGenerator = generator; 1902 fireChangeEvent(); 1903 } 1904 1905 /** 1906 * Considers the current (x, y) coordinate and updates the crosshair point 1907 * if it meets the criteria (usually means the (x, y) coordinate is the 1908 * closest to the anchor point so far). 1909 * 1910 * @param crosshairState the crosshair state (<code>null</code> permitted, 1911 * but the method does nothing in that case). 1912 * @param x the x-value (in data space). 1913 * @param y the y-value (in data space). 1914 * @param transX the x-value translated to Java2D space. 1915 * @param transY the y-value translated to Java2D space. 1916 * @param orientation the plot orientation (<code>null</code> not 1917 * permitted). 1918 * 1919 * @deprecated Use {@link #updateCrosshairValues(CrosshairState, double, 1920 * double, int, int, double, double, PlotOrientation)} -- see bug 1921 * report 1086307. 1922 */ updateCrosshairValues(CrosshairState crosshairState, double x, double y, double transX, double transY, PlotOrientation orientation)1923 protected void updateCrosshairValues(CrosshairState crosshairState, 1924 double x, double y, double transX, double transY, 1925 PlotOrientation orientation) { 1926 updateCrosshairValues(crosshairState, x, y, 0, 0, transX, transY, 1927 orientation); 1928 } 1929 1930 1931 } 1932