Source Code Cross Referenced for AbstractCategoryItemRenderer.java in  » Chart » jfreechart » org » jfree » chart » renderer » category » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Chart » jfreechart » org.jfree.chart.renderer.category 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ===========================================================
0002:         * JFreeChart : a free chart library for the Java(tm) platform
0003:         * ===========================================================
0004:         *
0005:         * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
0006:         *
0007:         * Project Info:  http://www.jfree.org/jfreechart/index.html
0008:         *
0009:         * This library is free software; you can redistribute it and/or modify it
0010:         * under the terms of the GNU Lesser General Public License as published by
0011:         * the Free Software Foundation; either version 2.1 of the License, or
0012:         * (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but
0015:         * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0016:         * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
0017:         * License for more details.
0018:         *
0019:         * You should have received a copy of the GNU Lesser General Public
0020:         * License along with this library; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
0022:         * USA.
0023:         *
0024:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
0025:         * in the United States and other countries.]
0026:         *
0027:         * ---------------------------------
0028:         * AbstractCategoryItemRenderer.java
0029:         * ---------------------------------
0030:         * (C) Copyright 2002-2007, by Object Refinery Limited.
0031:         *
0032:         * Original Author:  David Gilbert (for Object Refinery Limited);
0033:         * Contributor(s):   Richard Atkinson;
0034:         *
0035:         * $Id: AbstractCategoryItemRenderer.java,v 1.17.2.23 2007/06/01 15:12:14 mungady Exp $
0036:         *
0037:         * Changes:
0038:         * --------
0039:         * 29-May-2002 : Version 1 (DG);
0040:         * 06-Jun-2002 : Added accessor methods for the tool tip generator (DG);
0041:         * 11-Jun-2002 : Made constructors protected (DG);
0042:         * 26-Jun-2002 : Added axis to initialise method (DG);
0043:         * 05-Aug-2002 : Added urlGenerator member variable plus accessors (RA);
0044:         * 22-Aug-2002 : Added categoriesPaint attribute, based on code submitted by
0045:         *               Janet Banks.  This can be used when there is only one series,
0046:         *               and you want each category item to have a different color (DG);
0047:         * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
0048:         * 29-Oct-2002 : Fixed bug where background image for plot was not being
0049:         *               drawn (DG);
0050:         * 05-Nov-2002 : Replaced references to CategoryDataset with TableDataset (DG);
0051:         * 26-Nov 2002 : Replaced the isStacked() method with getRangeType() (DG);
0052:         * 09-Jan-2003 : Renamed grid-line methods (DG);
0053:         * 17-Jan-2003 : Moved plot classes into separate package (DG);
0054:         * 25-Mar-2003 : Implemented Serializable (DG);
0055:         * 12-May-2003 : Modified to take into account the plot orientation (DG);
0056:         * 12-Aug-2003 : Very minor javadoc corrections (DB)
0057:         * 13-Aug-2003 : Implemented Cloneable (DG);
0058:         * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
0059:         * 05-Nov-2003 : Fixed marker rendering bug (833623) (DG);
0060:         * 21-Jan-2004 : Update for renamed method in ValueAxis (DG);
0061:         * 11-Feb-2004 : Modified labelling for markers (DG);
0062:         * 12-Feb-2004 : Updated clone() method (DG);
0063:         * 15-Apr-2004 : Created a new CategoryToolTipGenerator interface (DG);
0064:         * 05-May-2004 : Fixed bug (948310) where interval markers extend outside axis
0065:         *               range (DG);
0066:         * 14-Jun-2004 : Fixed bug in drawRangeMarker() method - now uses 'paint' and
0067:         *               'stroke' rather than 'outlinePaint' and 'outlineStroke' (DG);
0068:         * 15-Jun-2004 : Interval markers can now use GradientPaint (DG);
0069:         * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities
0070:         *               --> TextUtilities (DG);
0071:         * 01-Oct-2004 : Fixed bug 1029697, problem with label alignment in
0072:         *               drawRangeMarker() method (DG);
0073:         * 07-Jan-2005 : Renamed getRangeExtent() --> findRangeBounds() (DG);
0074:         * 21-Jan-2005 : Modified return type of calculateRangeMarkerTextAnchorPoint()
0075:         *               method (DG);
0076:         * 08-Mar-2005 : Fixed positioning of marker labels (DG);
0077:         * 20-Apr-2005 : Added legend label, tooltip and URL generators (DG);
0078:         * 01-Jun-2005 : Handle one dimension of the marker label adjustment
0079:         *               automatically (DG);
0080:         * 09-Jun-2005 : Added utility method for adding an item entity (DG);
0081:         * ------------- JFREECHART 1.0.x ---------------------------------------------
0082:         * 01-Mar-2006 : Updated getLegendItems() to check seriesVisibleInLegend
0083:         *               flags (DG);
0084:         * 20-Jul-2006 : Set dataset and series indices in LegendItem (DG);
0085:         * 23-Oct-2006 : Draw outlines for interval markers (DG);
0086:         * 24-Oct-2006 : Respect alpha setting in markers, as suggested by Sergei
0087:         *               Ivanov in patch 1567843 (DG);
0088:         * 30-Nov-2006 : Added a check for series visibility in the getLegendItem()
0089:         *               method (DG);
0090:         * 07-Dec-2006 : Fix for equals() method (DG);
0091:         * 22-Feb-2007 : Added createState() method (DG);
0092:         * 01-Mar-2007 : Fixed interval marker drawing (patch 1670686 thanks to 
0093:         *               Sergei Ivanov) (DG);
0094:         * 20-Apr-2007 : Updated getLegendItem() for renderer change, and deprecated
0095:         *               itemLabelGenerator, toolTipGenerator and itemURLGenerator
0096:         *               override fields (DG);
0097:         * 18-May-2007 : Set dataset and seriesKey for LegendItem (DG);
0098:         *
0099:         */
0100:
0101:        package org.jfree.chart.renderer.category;
0102:
0103:        import java.awt.AlphaComposite;
0104:        import java.awt.Composite;
0105:        import java.awt.Font;
0106:        import java.awt.GradientPaint;
0107:        import java.awt.Graphics2D;
0108:        import java.awt.Paint;
0109:        import java.awt.Shape;
0110:        import java.awt.Stroke;
0111:        import java.awt.geom.Line2D;
0112:        import java.awt.geom.Point2D;
0113:        import java.awt.geom.Rectangle2D;
0114:        import java.io.Serializable;
0115:
0116:        import org.jfree.chart.LegendItem;
0117:        import org.jfree.chart.LegendItemCollection;
0118:        import org.jfree.chart.axis.CategoryAxis;
0119:        import org.jfree.chart.axis.ValueAxis;
0120:        import org.jfree.chart.entity.CategoryItemEntity;
0121:        import org.jfree.chart.entity.EntityCollection;
0122:        import org.jfree.chart.event.RendererChangeEvent;
0123:        import org.jfree.chart.labels.CategoryItemLabelGenerator;
0124:        import org.jfree.chart.labels.CategorySeriesLabelGenerator;
0125:        import org.jfree.chart.labels.CategoryToolTipGenerator;
0126:        import org.jfree.chart.labels.ItemLabelPosition;
0127:        import org.jfree.chart.labels.StandardCategorySeriesLabelGenerator;
0128:        import org.jfree.chart.plot.CategoryMarker;
0129:        import org.jfree.chart.plot.CategoryPlot;
0130:        import org.jfree.chart.plot.DrawingSupplier;
0131:        import org.jfree.chart.plot.IntervalMarker;
0132:        import org.jfree.chart.plot.Marker;
0133:        import org.jfree.chart.plot.PlotOrientation;
0134:        import org.jfree.chart.plot.PlotRenderingInfo;
0135:        import org.jfree.chart.plot.ValueMarker;
0136:        import org.jfree.chart.renderer.AbstractRenderer;
0137:        import org.jfree.chart.urls.CategoryURLGenerator;
0138:        import org.jfree.data.Range;
0139:        import org.jfree.data.category.CategoryDataset;
0140:        import org.jfree.data.general.DatasetUtilities;
0141:        import org.jfree.text.TextUtilities;
0142:        import org.jfree.ui.GradientPaintTransformer;
0143:        import org.jfree.ui.LengthAdjustmentType;
0144:        import org.jfree.ui.RectangleAnchor;
0145:        import org.jfree.ui.RectangleInsets;
0146:        import org.jfree.util.ObjectList;
0147:        import org.jfree.util.ObjectUtilities;
0148:        import org.jfree.util.PublicCloneable;
0149:
0150:        /**
0151:         * An abstract base class that you can use to implement a new
0152:         * {@link CategoryItemRenderer}.  When you create a new
0153:         * {@link CategoryItemRenderer} you are not required to extend this class,
0154:         * but it makes the job easier.
0155:         */
0156:        public abstract class AbstractCategoryItemRenderer extends
0157:                AbstractRenderer implements  CategoryItemRenderer, Cloneable,
0158:                PublicCloneable, Serializable {
0159:
0160:            /** For serialization. */
0161:            private static final long serialVersionUID = 1247553218442497391L;
0162:
0163:            /** The plot that the renderer is assigned to. */
0164:            private CategoryPlot plot;
0165:
0166:            /** 
0167:             * The item label generator for ALL series. 
0168:             * 
0169:             * @deprecated This field is redundant and deprecated as of version 1.0.6.
0170:             */
0171:            private CategoryItemLabelGenerator itemLabelGenerator;
0172:
0173:            /** A list of item label generators (one per series). */
0174:            private ObjectList itemLabelGeneratorList;
0175:
0176:            /** The base item label generator. */
0177:            private CategoryItemLabelGenerator baseItemLabelGenerator;
0178:
0179:            /** 
0180:             * The tool tip generator for ALL series. 
0181:             * 
0182:             * @deprecated This field is redundant and deprecated as of version 1.0.6.
0183:             */
0184:            private CategoryToolTipGenerator toolTipGenerator;
0185:
0186:            /** A list of tool tip generators (one per series). */
0187:            private ObjectList toolTipGeneratorList;
0188:
0189:            /** The base tool tip generator. */
0190:            private CategoryToolTipGenerator baseToolTipGenerator;
0191:
0192:            /** 
0193:             * The URL generator. 
0194:             * 
0195:             * @deprecated This field is redundant and deprecated as of version 1.0.6.
0196:             */
0197:            private CategoryURLGenerator itemURLGenerator;
0198:
0199:            /** A list of item label generators (one per series). */
0200:            private ObjectList itemURLGeneratorList;
0201:
0202:            /** The base item label generator. */
0203:            private CategoryURLGenerator baseItemURLGenerator;
0204:
0205:            /** The legend item label generator. */
0206:            private CategorySeriesLabelGenerator legendItemLabelGenerator;
0207:
0208:            /** The legend item tool tip generator. */
0209:            private CategorySeriesLabelGenerator legendItemToolTipGenerator;
0210:
0211:            /** The legend item URL generator. */
0212:            private CategorySeriesLabelGenerator legendItemURLGenerator;
0213:
0214:            /** The number of rows in the dataset (temporary record). */
0215:            private transient int rowCount;
0216:
0217:            /** The number of columns in the dataset (temporary record). */
0218:            private transient int columnCount;
0219:
0220:            /**
0221:             * Creates a new renderer with no tool tip generator and no URL generator.
0222:             * The defaults (no tool tip or URL generators) have been chosen to
0223:             * minimise the processing required to generate a default chart.  If you
0224:             * require tool tips or URLs, then you can easily add the required
0225:             * generators.
0226:             */
0227:            protected AbstractCategoryItemRenderer() {
0228:                this .itemLabelGenerator = null;
0229:                this .itemLabelGeneratorList = new ObjectList();
0230:                this .toolTipGenerator = null;
0231:                this .toolTipGeneratorList = new ObjectList();
0232:                this .itemURLGenerator = null;
0233:                this .itemURLGeneratorList = new ObjectList();
0234:                this .legendItemLabelGenerator = new StandardCategorySeriesLabelGenerator();
0235:            }
0236:
0237:            /**
0238:             * Returns the number of passes through the dataset required by the
0239:             * renderer.  This method returns <code>1</code>, subclasses should
0240:             * override if they need more passes.
0241:             *
0242:             * @return The pass count.
0243:             */
0244:            public int getPassCount() {
0245:                return 1;
0246:            }
0247:
0248:            /**
0249:             * Returns the plot that the renderer has been assigned to (where
0250:             * <code>null</code> indicates that the renderer is not currently assigned
0251:             * to a plot).
0252:             *
0253:             * @return The plot (possibly <code>null</code>).
0254:             *
0255:             * @see #setPlot(CategoryPlot)
0256:             */
0257:            public CategoryPlot getPlot() {
0258:                return this .plot;
0259:            }
0260:
0261:            /**
0262:             * Sets the plot that the renderer has been assigned to.  This method is
0263:             * usually called by the {@link CategoryPlot}, in normal usage you
0264:             * shouldn't need to call this method directly.
0265:             *
0266:             * @param plot  the plot (<code>null</code> not permitted).
0267:             *
0268:             * @see #getPlot()
0269:             */
0270:            public void setPlot(CategoryPlot plot) {
0271:                if (plot == null) {
0272:                    throw new IllegalArgumentException("Null 'plot' argument.");
0273:                }
0274:                this .plot = plot;
0275:            }
0276:
0277:            // ITEM LABEL GENERATOR
0278:
0279:            /**
0280:             * Returns the item label generator for a data item.  This implementation
0281:             * simply passes control to the {@link #getSeriesItemLabelGenerator(int)}
0282:             * method.  If, for some reason, you want a different generator for
0283:             * individual items, you can override this method.
0284:             *
0285:             * @param row  the row index (zero based).
0286:             * @param column  the column index (zero based).
0287:             *
0288:             * @return The generator (possibly <code>null</code>).
0289:             */
0290:            public CategoryItemLabelGenerator getItemLabelGenerator(int row,
0291:                    int column) {
0292:                return getSeriesItemLabelGenerator(row);
0293:            }
0294:
0295:            /**
0296:             * Returns the item label generator for a series.
0297:             *
0298:             * @param series  the series index (zero based).
0299:             *
0300:             * @return The generator (possibly <code>null</code>).
0301:             *
0302:             * @see #setSeriesItemLabelGenerator(int, CategoryItemLabelGenerator)
0303:             */
0304:            public CategoryItemLabelGenerator getSeriesItemLabelGenerator(
0305:                    int series) {
0306:
0307:                // return the generator for ALL series, if there is one...
0308:                if (this .itemLabelGenerator != null) {
0309:                    return this .itemLabelGenerator;
0310:                }
0311:
0312:                // otherwise look up the generator table
0313:                CategoryItemLabelGenerator generator = (CategoryItemLabelGenerator) this .itemLabelGeneratorList
0314:                        .get(series);
0315:                if (generator == null) {
0316:                    generator = this .baseItemLabelGenerator;
0317:                }
0318:                return generator;
0319:
0320:            }
0321:
0322:            /**
0323:             * Sets the item label generator for ALL series and sends a
0324:             * {@link RendererChangeEvent} to all registered listeners.
0325:             *
0326:             * @param generator  the generator (<code>null</code> permitted).
0327:             * 
0328:             * @deprecated This method should no longer be used (as of version 1.0.6). 
0329:             *     It is sufficient to rely on {@link #setSeriesItemLabelGenerator(int, 
0330:             *     CategoryItemLabelGenerator)} and 
0331:             *     {@link #setBaseItemLabelGenerator(CategoryItemLabelGenerator)}.
0332:             */
0333:            public void setItemLabelGenerator(
0334:                    CategoryItemLabelGenerator generator) {
0335:                this .itemLabelGenerator = generator;
0336:                notifyListeners(new RendererChangeEvent(this ));
0337:            }
0338:
0339:            /**
0340:             * Sets the item label generator for a series and sends a
0341:             * {@link RendererChangeEvent} to all registered listeners.
0342:             *
0343:             * @param series  the series index (zero based).
0344:             * @param generator  the generator (<code>null</code> permitted).
0345:             *
0346:             * @see #getSeriesItemLabelGenerator(int)
0347:             */
0348:            public void setSeriesItemLabelGenerator(int series,
0349:                    CategoryItemLabelGenerator generator) {
0350:                this .itemLabelGeneratorList.set(series, generator);
0351:                notifyListeners(new RendererChangeEvent(this ));
0352:            }
0353:
0354:            /**
0355:             * Returns the base item label generator.
0356:             *
0357:             * @return The generator (possibly <code>null</code>).
0358:             *
0359:             * @see #setBaseItemLabelGenerator(CategoryItemLabelGenerator)
0360:             */
0361:            public CategoryItemLabelGenerator getBaseItemLabelGenerator() {
0362:                return this .baseItemLabelGenerator;
0363:            }
0364:
0365:            /**
0366:             * Sets the base item label generator and sends a
0367:             * {@link RendererChangeEvent} to all registered listeners.
0368:             *
0369:             * @param generator  the generator (<code>null</code> permitted).
0370:             *
0371:             * @see #getBaseItemLabelGenerator()
0372:             */
0373:            public void setBaseItemLabelGenerator(
0374:                    CategoryItemLabelGenerator generator) {
0375:                this .baseItemLabelGenerator = generator;
0376:                notifyListeners(new RendererChangeEvent(this ));
0377:            }
0378:
0379:            // TOOL TIP GENERATOR
0380:
0381:            /**
0382:             * Returns the tool tip generator that should be used for the specified
0383:             * item.  This method looks up the generator using the "three-layer"
0384:             * approach outlined in the general description of this interface.  You
0385:             * can override this method if you want to return a different generator per
0386:             * item.
0387:             *
0388:             * @param row  the row index (zero-based).
0389:             * @param column  the column index (zero-based).
0390:             *
0391:             * @return The generator (possibly <code>null</code>).
0392:             */
0393:            public CategoryToolTipGenerator getToolTipGenerator(int row,
0394:                    int column) {
0395:
0396:                CategoryToolTipGenerator result = null;
0397:                if (this .toolTipGenerator != null) {
0398:                    result = this .toolTipGenerator;
0399:                } else {
0400:                    result = getSeriesToolTipGenerator(row);
0401:                    if (result == null) {
0402:                        result = this .baseToolTipGenerator;
0403:                    }
0404:                }
0405:                return result;
0406:            }
0407:
0408:            /**
0409:             * Returns the tool tip generator that will be used for ALL items in the
0410:             * dataset (the "layer 0" generator).
0411:             *
0412:             * @return A tool tip generator (possibly <code>null</code>).
0413:             *
0414:             * @see #setToolTipGenerator(CategoryToolTipGenerator)
0415:             * 
0416:             * @deprecated This method should no longer be used (as of version 1.0.6). 
0417:             *     It is sufficient to rely on {@link #getSeriesToolTipGenerator(int)} 
0418:             *     and {@link #getBaseToolTipGenerator()}.
0419:             */
0420:            public CategoryToolTipGenerator getToolTipGenerator() {
0421:                return this .toolTipGenerator;
0422:            }
0423:
0424:            /**
0425:             * Sets the tool tip generator for ALL series and sends a
0426:             * {@link org.jfree.chart.event.RendererChangeEvent} to all registered
0427:             * listeners.
0428:             *
0429:             * @param generator  the generator (<code>null</code> permitted).
0430:             *
0431:             * @see #getToolTipGenerator()
0432:             * 
0433:             * @deprecated This method should no longer be used (as of version 1.0.6). 
0434:             *     It is sufficient to rely on {@link #setSeriesToolTipGenerator(int, 
0435:             *     CategoryToolTipGenerator)} and 
0436:             *     {@link #setBaseToolTipGenerator(CategoryToolTipGenerator)}.
0437:             */
0438:            public void setToolTipGenerator(CategoryToolTipGenerator generator) {
0439:                this .toolTipGenerator = generator;
0440:                notifyListeners(new RendererChangeEvent(this ));
0441:            }
0442:
0443:            /**
0444:             * Returns the tool tip generator for the specified series (a "layer 1"
0445:             * generator).
0446:             *
0447:             * @param series  the series index (zero-based).
0448:             *
0449:             * @return The tool tip generator (possibly <code>null</code>).
0450:             *
0451:             * @see #setSeriesToolTipGenerator(int, CategoryToolTipGenerator)
0452:             */
0453:            public CategoryToolTipGenerator getSeriesToolTipGenerator(int series) {
0454:                return (CategoryToolTipGenerator) this .toolTipGeneratorList
0455:                        .get(series);
0456:            }
0457:
0458:            /**
0459:             * Sets the tool tip generator for a series and sends a
0460:             * {@link org.jfree.chart.event.RendererChangeEvent} to all registered
0461:             * listeners.
0462:             *
0463:             * @param series  the series index (zero-based).
0464:             * @param generator  the generator (<code>null</code> permitted).
0465:             *
0466:             * @see #getSeriesToolTipGenerator(int)
0467:             */
0468:            public void setSeriesToolTipGenerator(int series,
0469:                    CategoryToolTipGenerator generator) {
0470:                this .toolTipGeneratorList.set(series, generator);
0471:                notifyListeners(new RendererChangeEvent(this ));
0472:            }
0473:
0474:            /**
0475:             * Returns the base tool tip generator (the "layer 2" generator).
0476:             *
0477:             * @return The tool tip generator (possibly <code>null</code>).
0478:             *
0479:             * @see #setBaseToolTipGenerator(CategoryToolTipGenerator)
0480:             */
0481:            public CategoryToolTipGenerator getBaseToolTipGenerator() {
0482:                return this .baseToolTipGenerator;
0483:            }
0484:
0485:            /**
0486:             * Sets the base tool tip generator and sends a {@link RendererChangeEvent}
0487:             * to all registered listeners.
0488:             *
0489:             * @param generator  the generator (<code>null</code> permitted).
0490:             *
0491:             * @see #getBaseToolTipGenerator()
0492:             */
0493:            public void setBaseToolTipGenerator(
0494:                    CategoryToolTipGenerator generator) {
0495:                this .baseToolTipGenerator = generator;
0496:                notifyListeners(new RendererChangeEvent(this ));
0497:            }
0498:
0499:            // URL GENERATOR
0500:
0501:            /**
0502:             * Returns the URL generator for a data item.  This method just calls the
0503:             * getSeriesItemURLGenerator method, but you can override this behaviour if
0504:             * you want to.
0505:             *
0506:             * @param row  the row index (zero based).
0507:             * @param column  the column index (zero based).
0508:             *
0509:             * @return The URL generator.
0510:             */
0511:            public CategoryURLGenerator getItemURLGenerator(int row, int column) {
0512:                return getSeriesItemURLGenerator(row);
0513:            }
0514:
0515:            /**
0516:             * Returns the URL generator for a series.
0517:             *
0518:             * @param series  the series index (zero based).
0519:             *
0520:             * @return The URL generator for the series.
0521:             *
0522:             * @see #setSeriesItemURLGenerator(int, CategoryURLGenerator)
0523:             */
0524:            public CategoryURLGenerator getSeriesItemURLGenerator(int series) {
0525:
0526:                // return the generator for ALL series, if there is one...
0527:                if (this .itemURLGenerator != null) {
0528:                    return this .itemURLGenerator;
0529:                }
0530:
0531:                // otherwise look up the generator table
0532:                CategoryURLGenerator generator = (CategoryURLGenerator) this .itemURLGeneratorList
0533:                        .get(series);
0534:                if (generator == null) {
0535:                    generator = this .baseItemURLGenerator;
0536:                }
0537:                return generator;
0538:
0539:            }
0540:
0541:            /**
0542:             * Sets the item URL generator for ALL series.
0543:             *
0544:             * @param generator  the generator.
0545:             * 
0546:             * @deprecated This method should no longer be used (as of version 1.0.6). 
0547:             *     It is sufficient to rely on {@link #setSeriesItemURLGenerator(int, 
0548:             *     CategoryURLGenerator)} and 
0549:             *     {@link #setBaseItemURLGenerator(CategoryURLGenerator)}.
0550:             */
0551:            public void setItemURLGenerator(CategoryURLGenerator generator) {
0552:                this .itemURLGenerator = generator;
0553:                notifyListeners(new RendererChangeEvent(this ));
0554:            }
0555:
0556:            /**
0557:             * Sets the URL generator for a series.
0558:             *
0559:             * @param series  the series index (zero based).
0560:             * @param generator  the generator.
0561:             *
0562:             * @see #getSeriesItemURLGenerator(int)
0563:             */
0564:            public void setSeriesItemURLGenerator(int series,
0565:                    CategoryURLGenerator generator) {
0566:                this .itemURLGeneratorList.set(series, generator);
0567:                notifyListeners(new RendererChangeEvent(this ));
0568:            }
0569:
0570:            /**
0571:             * Returns the base item URL generator.
0572:             *
0573:             * @return The item URL generator.
0574:             *
0575:             * @see #setBaseItemURLGenerator(CategoryURLGenerator)
0576:             */
0577:            public CategoryURLGenerator getBaseItemURLGenerator() {
0578:                return this .baseItemURLGenerator;
0579:            }
0580:
0581:            /**
0582:             * Sets the base item URL generator.
0583:             *
0584:             * @param generator  the item URL generator.
0585:             *
0586:             * @see #getBaseItemURLGenerator()
0587:             */
0588:            public void setBaseItemURLGenerator(CategoryURLGenerator generator) {
0589:                this .baseItemURLGenerator = generator;
0590:                notifyListeners(new RendererChangeEvent(this ));
0591:            }
0592:
0593:            /**
0594:             * Returns the number of rows in the dataset.  This value is updated in the
0595:             * {@link AbstractCategoryItemRenderer#initialise} method.
0596:             *
0597:             * @return The row count.
0598:             */
0599:            public int getRowCount() {
0600:                return this .rowCount;
0601:            }
0602:
0603:            /**
0604:             * Returns the number of columns in the dataset.  This value is updated in
0605:             * the {@link AbstractCategoryItemRenderer#initialise} method.
0606:             *
0607:             * @return The column count.
0608:             */
0609:            public int getColumnCount() {
0610:                return this .columnCount;
0611:            }
0612:
0613:            /**
0614:             * Creates a new state instance---this method is called from the
0615:             * {@link #initialise(Graphics2D, Rectangle2D, CategoryPlot, int,
0616:             * PlotRenderingInfo)} method.  Subclasses can override this method if
0617:             * they need to use a subclass of {@link CategoryItemRendererState}.
0618:             *
0619:             * @param info  collects plot rendering info (<code>null</code> permitted).
0620:             *
0621:             * @return The new state instance (never <code>null</code>).
0622:             *
0623:             * @since 1.0.5
0624:             */
0625:            protected CategoryItemRendererState createState(
0626:                    PlotRenderingInfo info) {
0627:                return new CategoryItemRendererState(info);
0628:            }
0629:
0630:            /**
0631:             * Initialises the renderer and returns a state object that will be used
0632:             * for the remainder of the drawing process for a single chart.  The state
0633:             * object allows for the fact that the renderer may be used simultaneously
0634:             * by multiple threads (each thread will work with a separate state object).
0635:             *
0636:             * @param g2  the graphics device.
0637:             * @param dataArea  the data area.
0638:             * @param plot  the plot.
0639:             * @param rendererIndex  the renderer index.
0640:             * @param info  an object for returning information about the structure of
0641:             *              the plot (<code>null</code> permitted).
0642:             *
0643:             * @return The renderer state.
0644:             */
0645:            public CategoryItemRendererState initialise(Graphics2D g2,
0646:                    Rectangle2D dataArea, CategoryPlot plot, int rendererIndex,
0647:                    PlotRenderingInfo info) {
0648:
0649:                setPlot(plot);
0650:                CategoryDataset data = plot.getDataset(rendererIndex);
0651:                if (data != null) {
0652:                    this .rowCount = data.getRowCount();
0653:                    this .columnCount = data.getColumnCount();
0654:                } else {
0655:                    this .rowCount = 0;
0656:                    this .columnCount = 0;
0657:                }
0658:                return createState(info);
0659:
0660:            }
0661:
0662:            /**
0663:             * Returns the range of values the renderer requires to display all the
0664:             * items from the specified dataset.
0665:             *
0666:             * @param dataset  the dataset (<code>null</code> permitted).
0667:             *
0668:             * @return The range (or <code>null</code> if the dataset is
0669:             *         <code>null</code> or empty).
0670:             */
0671:            public Range findRangeBounds(CategoryDataset dataset) {
0672:                return DatasetUtilities.findRangeBounds(dataset);
0673:            }
0674:
0675:            /**
0676:             * Draws a background for the data area.  The default implementation just
0677:             * gets the plot to draw the background, but some renderers will override 
0678:             * this behaviour.
0679:             *
0680:             * @param g2  the graphics device.
0681:             * @param plot  the plot.
0682:             * @param dataArea  the data area.
0683:             */
0684:            public void drawBackground(Graphics2D g2, CategoryPlot plot,
0685:                    Rectangle2D dataArea) {
0686:
0687:                plot.drawBackground(g2, dataArea);
0688:
0689:            }
0690:
0691:            /**
0692:             * Draws an outline for the data area.  The default implementation just
0693:             * gets the plot to draw the outline, but some renderers will override this
0694:             * behaviour.
0695:             *
0696:             * @param g2  the graphics device.
0697:             * @param plot  the plot.
0698:             * @param dataArea  the data area.
0699:             */
0700:            public void drawOutline(Graphics2D g2, CategoryPlot plot,
0701:                    Rectangle2D dataArea) {
0702:
0703:                plot.drawOutline(g2, dataArea);
0704:
0705:            }
0706:
0707:            /**
0708:             * Draws a grid line against the domain axis.
0709:             * <P>
0710:             * Note that this default implementation assumes that the horizontal axis
0711:             * is the domain axis. If this is not the case, you will need to override
0712:             * this method.
0713:             *
0714:             * @param g2  the graphics device.
0715:             * @param plot  the plot.
0716:             * @param dataArea  the area for plotting data (not yet adjusted for any
0717:             *                  3D effect).
0718:             * @param value  the Java2D value at which the grid line should be drawn.
0719:             *
0720:             * @see #drawRangeGridline(Graphics2D, CategoryPlot, ValueAxis,
0721:             *     Rectangle2D, double)
0722:             */
0723:            public void drawDomainGridline(Graphics2D g2, CategoryPlot plot,
0724:                    Rectangle2D dataArea, double value) {
0725:
0726:                Line2D line = null;
0727:                PlotOrientation orientation = plot.getOrientation();
0728:
0729:                if (orientation == PlotOrientation.HORIZONTAL) {
0730:                    line = new Line2D.Double(dataArea.getMinX(), value,
0731:                            dataArea.getMaxX(), value);
0732:                } else if (orientation == PlotOrientation.VERTICAL) {
0733:                    line = new Line2D.Double(value, dataArea.getMinY(), value,
0734:                            dataArea.getMaxY());
0735:                }
0736:
0737:                Paint paint = plot.getDomainGridlinePaint();
0738:                if (paint == null) {
0739:                    paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT;
0740:                }
0741:                g2.setPaint(paint);
0742:
0743:                Stroke stroke = plot.getDomainGridlineStroke();
0744:                if (stroke == null) {
0745:                    stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE;
0746:                }
0747:                g2.setStroke(stroke);
0748:
0749:                g2.draw(line);
0750:
0751:            }
0752:
0753:            /**
0754:             * Draws a grid line against the range axis.
0755:             *
0756:             * @param g2  the graphics device.
0757:             * @param plot  the plot.
0758:             * @param axis  the value axis.
0759:             * @param dataArea  the area for plotting data (not yet adjusted for any
0760:             *                  3D effect).
0761:             * @param value  the value at which the grid line should be drawn.
0762:             *
0763:             * @see #drawDomainGridline(Graphics2D, CategoryPlot, Rectangle2D, double)
0764:             *
0765:             */
0766:            public void drawRangeGridline(Graphics2D g2, CategoryPlot plot,
0767:                    ValueAxis axis, Rectangle2D dataArea, double value) {
0768:
0769:                Range range = axis.getRange();
0770:                if (!range.contains(value)) {
0771:                    return;
0772:                }
0773:
0774:                PlotOrientation orientation = plot.getOrientation();
0775:                double v = axis.valueToJava2D(value, dataArea, plot
0776:                        .getRangeAxisEdge());
0777:                Line2D line = null;
0778:                if (orientation == PlotOrientation.HORIZONTAL) {
0779:                    line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea
0780:                            .getMaxY());
0781:                } else if (orientation == PlotOrientation.VERTICAL) {
0782:                    line = new Line2D.Double(dataArea.getMinX(), v, dataArea
0783:                            .getMaxX(), v);
0784:                }
0785:
0786:                Paint paint = plot.getRangeGridlinePaint();
0787:                if (paint == null) {
0788:                    paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT;
0789:                }
0790:                g2.setPaint(paint);
0791:
0792:                Stroke stroke = plot.getRangeGridlineStroke();
0793:                if (stroke == null) {
0794:                    stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE;
0795:                }
0796:                g2.setStroke(stroke);
0797:
0798:                g2.draw(line);
0799:
0800:            }
0801:
0802:            /**
0803:             * Draws a marker for the domain axis.
0804:             *
0805:             * @param g2  the graphics device (not <code>null</code>).
0806:             * @param plot  the plot (not <code>null</code>).
0807:             * @param axis  the range axis (not <code>null</code>).
0808:             * @param marker  the marker to be drawn (not <code>null</code>).
0809:             * @param dataArea  the area inside the axes (not <code>null</code>).
0810:             *
0811:             * @see #drawRangeMarker(Graphics2D, CategoryPlot, ValueAxis, Marker,
0812:             *     Rectangle2D)
0813:             */
0814:            public void drawDomainMarker(Graphics2D g2, CategoryPlot plot,
0815:                    CategoryAxis axis, CategoryMarker marker,
0816:                    Rectangle2D dataArea) {
0817:
0818:                Comparable category = marker.getKey();
0819:                CategoryDataset dataset = plot
0820:                        .getDataset(plot.getIndexOf(this ));
0821:                int columnIndex = dataset.getColumnIndex(category);
0822:                if (columnIndex < 0) {
0823:                    return;
0824:                }
0825:
0826:                final Composite savedComposite = g2.getComposite();
0827:                g2.setComposite(AlphaComposite.getInstance(
0828:                        AlphaComposite.SRC_OVER, marker.getAlpha()));
0829:
0830:                PlotOrientation orientation = plot.getOrientation();
0831:                Rectangle2D bounds = null;
0832:                if (marker.getDrawAsLine()) {
0833:                    double v = axis.getCategoryMiddle(columnIndex, dataset
0834:                            .getColumnCount(), dataArea, plot
0835:                            .getDomainAxisEdge());
0836:                    Line2D line = null;
0837:                    if (orientation == PlotOrientation.HORIZONTAL) {
0838:                        line = new Line2D.Double(dataArea.getMinX(), v,
0839:                                dataArea.getMaxX(), v);
0840:                    } else if (orientation == PlotOrientation.VERTICAL) {
0841:                        line = new Line2D.Double(v, dataArea.getMinY(), v,
0842:                                dataArea.getMaxY());
0843:                    }
0844:                    g2.setPaint(marker.getPaint());
0845:                    g2.setStroke(marker.getStroke());
0846:                    g2.draw(line);
0847:                    bounds = line.getBounds2D();
0848:                } else {
0849:                    double v0 = axis.getCategoryStart(columnIndex, dataset
0850:                            .getColumnCount(), dataArea, plot
0851:                            .getDomainAxisEdge());
0852:                    double v1 = axis.getCategoryEnd(columnIndex, dataset
0853:                            .getColumnCount(), dataArea, plot
0854:                            .getDomainAxisEdge());
0855:                    Rectangle2D area = null;
0856:                    if (orientation == PlotOrientation.HORIZONTAL) {
0857:                        area = new Rectangle2D.Double(dataArea.getMinX(), v0,
0858:                                dataArea.getWidth(), (v1 - v0));
0859:                    } else if (orientation == PlotOrientation.VERTICAL) {
0860:                        area = new Rectangle2D.Double(v0, dataArea.getMinY(),
0861:                                (v1 - v0), dataArea.getHeight());
0862:                    }
0863:                    g2.setPaint(marker.getPaint());
0864:                    g2.fill(area);
0865:                    bounds = area;
0866:                }
0867:
0868:                String label = marker.getLabel();
0869:                RectangleAnchor anchor = marker.getLabelAnchor();
0870:                if (label != null) {
0871:                    Font labelFont = marker.getLabelFont();
0872:                    g2.setFont(labelFont);
0873:                    g2.setPaint(marker.getLabelPaint());
0874:                    Point2D coordinates = calculateDomainMarkerTextAnchorPoint(
0875:                            g2, orientation, dataArea, bounds, marker
0876:                                    .getLabelOffset(), marker
0877:                                    .getLabelOffsetType(), anchor);
0878:                    TextUtilities.drawAlignedString(label, g2,
0879:                            (float) coordinates.getX(), (float) coordinates
0880:                                    .getY(), marker.getLabelTextAnchor());
0881:                }
0882:                g2.setComposite(savedComposite);
0883:            }
0884:
0885:            /**
0886:             * Draws a marker for the range axis.
0887:             *
0888:             * @param g2  the graphics device (not <code>null</code>).
0889:             * @param plot  the plot (not <code>null</code>).
0890:             * @param axis  the range axis (not <code>null</code>).
0891:             * @param marker  the marker to be drawn (not <code>null</code>).
0892:             * @param dataArea  the area inside the axes (not <code>null</code>).
0893:             *
0894:             * @see #drawDomainMarker(Graphics2D, CategoryPlot, CategoryAxis,
0895:             *     CategoryMarker, Rectangle2D)
0896:             */
0897:            public void drawRangeMarker(Graphics2D g2, CategoryPlot plot,
0898:                    ValueAxis axis, Marker marker, Rectangle2D dataArea) {
0899:
0900:                if (marker instanceof  ValueMarker) {
0901:                    ValueMarker vm = (ValueMarker) marker;
0902:                    double value = vm.getValue();
0903:                    Range range = axis.getRange();
0904:
0905:                    if (!range.contains(value)) {
0906:                        return;
0907:                    }
0908:
0909:                    final Composite savedComposite = g2.getComposite();
0910:                    g2.setComposite(AlphaComposite.getInstance(
0911:                            AlphaComposite.SRC_OVER, marker.getAlpha()));
0912:
0913:                    PlotOrientation orientation = plot.getOrientation();
0914:                    double v = axis.valueToJava2D(value, dataArea, plot
0915:                            .getRangeAxisEdge());
0916:                    Line2D line = null;
0917:                    if (orientation == PlotOrientation.HORIZONTAL) {
0918:                        line = new Line2D.Double(v, dataArea.getMinY(), v,
0919:                                dataArea.getMaxY());
0920:                    } else if (orientation == PlotOrientation.VERTICAL) {
0921:                        line = new Line2D.Double(dataArea.getMinX(), v,
0922:                                dataArea.getMaxX(), v);
0923:                    }
0924:
0925:                    g2.setPaint(marker.getPaint());
0926:                    g2.setStroke(marker.getStroke());
0927:                    g2.draw(line);
0928:
0929:                    String label = marker.getLabel();
0930:                    RectangleAnchor anchor = marker.getLabelAnchor();
0931:                    if (label != null) {
0932:                        Font labelFont = marker.getLabelFont();
0933:                        g2.setFont(labelFont);
0934:                        g2.setPaint(marker.getLabelPaint());
0935:                        Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
0936:                                g2, orientation, dataArea, line.getBounds2D(),
0937:                                marker.getLabelOffset(),
0938:                                LengthAdjustmentType.EXPAND, anchor);
0939:                        TextUtilities.drawAlignedString(label, g2,
0940:                                (float) coordinates.getX(), (float) coordinates
0941:                                        .getY(), marker.getLabelTextAnchor());
0942:                    }
0943:                    g2.setComposite(savedComposite);
0944:                } else if (marker instanceof  IntervalMarker) {
0945:                    IntervalMarker im = (IntervalMarker) marker;
0946:                    double start = im.getStartValue();
0947:                    double end = im.getEndValue();
0948:                    Range range = axis.getRange();
0949:                    if (!(range.intersects(start, end))) {
0950:                        return;
0951:                    }
0952:
0953:                    final Composite savedComposite = g2.getComposite();
0954:                    g2.setComposite(AlphaComposite.getInstance(
0955:                            AlphaComposite.SRC_OVER, marker.getAlpha()));
0956:
0957:                    double start2d = axis.valueToJava2D(start, dataArea, plot
0958:                            .getRangeAxisEdge());
0959:                    double end2d = axis.valueToJava2D(end, dataArea, plot
0960:                            .getRangeAxisEdge());
0961:                    double low = Math.min(start2d, end2d);
0962:                    double high = Math.max(start2d, end2d);
0963:
0964:                    PlotOrientation orientation = plot.getOrientation();
0965:                    Rectangle2D rect = null;
0966:                    if (orientation == PlotOrientation.HORIZONTAL) {
0967:                        // clip left and right bounds to data area
0968:                        low = Math.max(low, dataArea.getMinX());
0969:                        high = Math.min(high, dataArea.getMaxX());
0970:                        rect = new Rectangle2D.Double(low, dataArea.getMinY(),
0971:                                high - low, dataArea.getHeight());
0972:                    } else if (orientation == PlotOrientation.VERTICAL) {
0973:                        // clip top and bottom bounds to data area
0974:                        low = Math.max(low, dataArea.getMinY());
0975:                        high = Math.min(high, dataArea.getMaxY());
0976:                        rect = new Rectangle2D.Double(dataArea.getMinX(), low,
0977:                                dataArea.getWidth(), high - low);
0978:                    }
0979:                    Paint p = marker.getPaint();
0980:                    if (p instanceof  GradientPaint) {
0981:                        GradientPaint gp = (GradientPaint) p;
0982:                        GradientPaintTransformer t = im
0983:                                .getGradientPaintTransformer();
0984:                        if (t != null) {
0985:                            gp = t.transform(gp, rect);
0986:                        }
0987:                        g2.setPaint(gp);
0988:                    } else {
0989:                        g2.setPaint(p);
0990:                    }
0991:                    g2.fill(rect);
0992:
0993:                    // now draw the outlines, if visible...
0994:                    if (im.getOutlinePaint() != null
0995:                            && im.getOutlineStroke() != null) {
0996:                        if (orientation == PlotOrientation.VERTICAL) {
0997:                            Line2D line = new Line2D.Double();
0998:                            double x0 = dataArea.getMinX();
0999:                            double x1 = dataArea.getMaxX();
1000:                            g2.setPaint(im.getOutlinePaint());
1001:                            g2.setStroke(im.getOutlineStroke());
1002:                            if (range.contains(start)) {
1003:                                line.setLine(x0, start2d, x1, start2d);
1004:                                g2.draw(line);
1005:                            }
1006:                            if (range.contains(end)) {
1007:                                line.setLine(x0, end2d, x1, end2d);
1008:                                g2.draw(line);
1009:                            }
1010:                        } else { // PlotOrientation.HORIZONTAL
1011:                            Line2D line = new Line2D.Double();
1012:                            double y0 = dataArea.getMinY();
1013:                            double y1 = dataArea.getMaxY();
1014:                            g2.setPaint(im.getOutlinePaint());
1015:                            g2.setStroke(im.getOutlineStroke());
1016:                            if (range.contains(start)) {
1017:                                line.setLine(start2d, y0, start2d, y1);
1018:                                g2.draw(line);
1019:                            }
1020:                            if (range.contains(end)) {
1021:                                line.setLine(end2d, y0, end2d, y1);
1022:                                g2.draw(line);
1023:                            }
1024:                        }
1025:                    }
1026:
1027:                    String label = marker.getLabel();
1028:                    RectangleAnchor anchor = marker.getLabelAnchor();
1029:                    if (label != null) {
1030:                        Font labelFont = marker.getLabelFont();
1031:                        g2.setFont(labelFont);
1032:                        g2.setPaint(marker.getLabelPaint());
1033:                        Point2D coordinates = calculateRangeMarkerTextAnchorPoint(
1034:                                g2, orientation, dataArea, rect, marker
1035:                                        .getLabelOffset(), marker
1036:                                        .getLabelOffsetType(), anchor);
1037:                        TextUtilities.drawAlignedString(label, g2,
1038:                                (float) coordinates.getX(), (float) coordinates
1039:                                        .getY(), marker.getLabelTextAnchor());
1040:                    }
1041:                    g2.setComposite(savedComposite);
1042:                }
1043:            }
1044:
1045:            /**
1046:             * Calculates the (x, y) coordinates for drawing the label for a marker on
1047:             * the range axis.
1048:             *
1049:             * @param g2  the graphics device.
1050:             * @param orientation  the plot orientation.
1051:             * @param dataArea  the data area.
1052:             * @param markerArea  the rectangle surrounding the marker.
1053:             * @param markerOffset  the marker offset.
1054:             * @param labelOffsetType  the label offset type.
1055:             * @param anchor  the label anchor.
1056:             *
1057:             * @return The coordinates for drawing the marker label.
1058:             */
1059:            protected Point2D calculateDomainMarkerTextAnchorPoint(
1060:                    Graphics2D g2, PlotOrientation orientation,
1061:                    Rectangle2D dataArea, Rectangle2D markerArea,
1062:                    RectangleInsets markerOffset,
1063:                    LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) {
1064:
1065:                Rectangle2D anchorRect = null;
1066:                if (orientation == PlotOrientation.HORIZONTAL) {
1067:                    anchorRect = markerOffset.createAdjustedRectangle(
1068:                            markerArea, LengthAdjustmentType.CONTRACT,
1069:                            labelOffsetType);
1070:                } else if (orientation == PlotOrientation.VERTICAL) {
1071:                    anchorRect = markerOffset.createAdjustedRectangle(
1072:                            markerArea, labelOffsetType,
1073:                            LengthAdjustmentType.CONTRACT);
1074:                }
1075:                return RectangleAnchor.coordinates(anchorRect, anchor);
1076:
1077:            }
1078:
1079:            /**
1080:             * Calculates the (x, y) coordinates for drawing a marker label.
1081:             *
1082:             * @param g2  the graphics device.
1083:             * @param orientation  the plot orientation.
1084:             * @param dataArea  the data area.
1085:             * @param markerArea  the rectangle surrounding the marker.
1086:             * @param markerOffset  the marker offset.
1087:             * @param labelOffsetType  the label offset type.
1088:             * @param anchor  the label anchor.
1089:             *
1090:             * @return The coordinates for drawing the marker label.
1091:             */
1092:            protected Point2D calculateRangeMarkerTextAnchorPoint(
1093:                    Graphics2D g2, PlotOrientation orientation,
1094:                    Rectangle2D dataArea, Rectangle2D markerArea,
1095:                    RectangleInsets markerOffset,
1096:                    LengthAdjustmentType labelOffsetType, RectangleAnchor anchor) {
1097:
1098:                Rectangle2D anchorRect = null;
1099:                if (orientation == PlotOrientation.HORIZONTAL) {
1100:                    anchorRect = markerOffset.createAdjustedRectangle(
1101:                            markerArea, labelOffsetType,
1102:                            LengthAdjustmentType.CONTRACT);
1103:                } else if (orientation == PlotOrientation.VERTICAL) {
1104:                    anchorRect = markerOffset.createAdjustedRectangle(
1105:                            markerArea, LengthAdjustmentType.CONTRACT,
1106:                            labelOffsetType);
1107:                }
1108:                return RectangleAnchor.coordinates(anchorRect, anchor);
1109:
1110:            }
1111:
1112:            /**
1113:             * Returns a legend item for a series.  This default implementation will
1114:             * return <code>null</code> if {@link #isSeriesVisible(int)} or 
1115:             * {@link #isSeriesVisibleInLegend(int)} returns <code>false</code>.
1116:             *
1117:             * @param datasetIndex  the dataset index (zero-based).
1118:             * @param series  the series index (zero-based).
1119:             *
1120:             * @return The legend item (possibly <code>null</code>).
1121:             *
1122:             * @see #getLegendItems()
1123:             */
1124:            public LegendItem getLegendItem(int datasetIndex, int series) {
1125:
1126:                CategoryPlot p = getPlot();
1127:                if (p == null) {
1128:                    return null;
1129:                }
1130:
1131:                // check that a legend item needs to be displayed...
1132:                if (!isSeriesVisible(series)
1133:                        || !isSeriesVisibleInLegend(series)) {
1134:                    return null;
1135:                }
1136:
1137:                CategoryDataset dataset = p.getDataset(datasetIndex);
1138:                String label = this .legendItemLabelGenerator.generateLabel(
1139:                        dataset, series);
1140:                String description = label;
1141:                String toolTipText = null;
1142:                if (this .legendItemToolTipGenerator != null) {
1143:                    toolTipText = this .legendItemToolTipGenerator
1144:                            .generateLabel(dataset, series);
1145:                }
1146:                String urlText = null;
1147:                if (this .legendItemURLGenerator != null) {
1148:                    urlText = this .legendItemURLGenerator.generateLabel(
1149:                            dataset, series);
1150:                }
1151:                Shape shape = lookupSeriesShape(series);
1152:                Paint paint = lookupSeriesPaint(series);
1153:                Paint outlinePaint = lookupSeriesOutlinePaint(series);
1154:                Stroke outlineStroke = lookupSeriesOutlineStroke(series);
1155:
1156:                LegendItem item = new LegendItem(label, description,
1157:                        toolTipText, urlText, shape, paint, outlineStroke,
1158:                        outlinePaint);
1159:                item.setSeriesKey(dataset.getRowKey(series));
1160:                item.setSeriesIndex(series);
1161:                item.setDataset(dataset);
1162:                item.setDatasetIndex(datasetIndex);
1163:                return item;
1164:            }
1165:
1166:            /**
1167:             * Tests this renderer for equality with another object.
1168:             *
1169:             * @param obj  the object.
1170:             *
1171:             * @return <code>true</code> or <code>false</code>.
1172:             */
1173:            public boolean equals(Object obj) {
1174:
1175:                if (obj == this ) {
1176:                    return true;
1177:                }
1178:                if (!(obj instanceof  AbstractCategoryItemRenderer)) {
1179:                    return false;
1180:                }
1181:                AbstractCategoryItemRenderer that = (AbstractCategoryItemRenderer) obj;
1182:
1183:                if (!ObjectUtilities.equal(this .itemLabelGenerator,
1184:                        that.itemLabelGenerator)) {
1185:                    return false;
1186:                }
1187:                if (!ObjectUtilities.equal(this .itemLabelGeneratorList,
1188:                        that.itemLabelGeneratorList)) {
1189:                    return false;
1190:                }
1191:                if (!ObjectUtilities.equal(this .baseItemLabelGenerator,
1192:                        that.baseItemLabelGenerator)) {
1193:                    return false;
1194:                }
1195:                if (!ObjectUtilities.equal(this .toolTipGenerator,
1196:                        that.toolTipGenerator)) {
1197:                    return false;
1198:                }
1199:                if (!ObjectUtilities.equal(this .toolTipGeneratorList,
1200:                        that.toolTipGeneratorList)) {
1201:                    return false;
1202:                }
1203:                if (!ObjectUtilities.equal(this .baseToolTipGenerator,
1204:                        that.baseToolTipGenerator)) {
1205:                    return false;
1206:                }
1207:                if (!ObjectUtilities.equal(this .itemURLGenerator,
1208:                        that.itemURLGenerator)) {
1209:                    return false;
1210:                }
1211:                if (!ObjectUtilities.equal(this .itemURLGeneratorList,
1212:                        that.itemURLGeneratorList)) {
1213:                    return false;
1214:                }
1215:                if (!ObjectUtilities.equal(this .baseItemURLGenerator,
1216:                        that.baseItemURLGenerator)) {
1217:                    return false;
1218:                }
1219:                if (!ObjectUtilities.equal(this .legendItemLabelGenerator,
1220:                        that.legendItemLabelGenerator)) {
1221:                    return false;
1222:                }
1223:                if (!ObjectUtilities.equal(this .legendItemToolTipGenerator,
1224:                        that.legendItemToolTipGenerator)) {
1225:                    return false;
1226:                }
1227:                if (!ObjectUtilities.equal(this .legendItemURLGenerator,
1228:                        that.legendItemURLGenerator)) {
1229:                    return false;
1230:                }
1231:                return super .equals(obj);
1232:            }
1233:
1234:            /**
1235:             * Returns a hash code for the renderer.
1236:             *
1237:             * @return The hash code.
1238:             */
1239:            public int hashCode() {
1240:                int result = super .hashCode();
1241:                return result;
1242:            }
1243:
1244:            /**
1245:             * Returns the drawing supplier from the plot.
1246:             *
1247:             * @return The drawing supplier (possibly <code>null</code>).
1248:             */
1249:            public DrawingSupplier getDrawingSupplier() {
1250:                DrawingSupplier result = null;
1251:                CategoryPlot cp = getPlot();
1252:                if (cp != null) {
1253:                    result = cp.getDrawingSupplier();
1254:                }
1255:                return result;
1256:            }
1257:
1258:            /**
1259:             * Draws an item label.
1260:             *
1261:             * @param g2  the graphics device.
1262:             * @param orientation  the orientation.
1263:             * @param dataset  the dataset.
1264:             * @param row  the row.
1265:             * @param column  the column.
1266:             * @param x  the x coordinate (in Java2D space).
1267:             * @param y  the y coordinate (in Java2D space).
1268:             * @param negative  indicates a negative value (which affects the item
1269:             *                  label position).
1270:             */
1271:            protected void drawItemLabel(Graphics2D g2,
1272:                    PlotOrientation orientation, CategoryDataset dataset,
1273:                    int row, int column, double x, double y, boolean negative) {
1274:
1275:                CategoryItemLabelGenerator generator = getItemLabelGenerator(
1276:                        row, column);
1277:                if (generator != null) {
1278:                    Font labelFont = getItemLabelFont(row, column);
1279:                    Paint paint = getItemLabelPaint(row, column);
1280:                    g2.setFont(labelFont);
1281:                    g2.setPaint(paint);
1282:                    String label = generator
1283:                            .generateLabel(dataset, row, column);
1284:                    ItemLabelPosition position = null;
1285:                    if (!negative) {
1286:                        position = getPositiveItemLabelPosition(row, column);
1287:                    } else {
1288:                        position = getNegativeItemLabelPosition(row, column);
1289:                    }
1290:                    Point2D anchorPoint = calculateLabelAnchorPoint(position
1291:                            .getItemLabelAnchor(), x, y, orientation);
1292:                    TextUtilities.drawRotatedString(label, g2,
1293:                            (float) anchorPoint.getX(), (float) anchorPoint
1294:                                    .getY(), position.getTextAnchor(), position
1295:                                    .getAngle(), position.getRotationAnchor());
1296:                }
1297:
1298:            }
1299:
1300:            /**
1301:             * Returns an independent copy of the renderer.  The <code>plot</code>
1302:             * reference is shallow copied.
1303:             *
1304:             * @return A clone.
1305:             *
1306:             * @throws CloneNotSupportedException  can be thrown if one of the objects
1307:             *         belonging to the renderer does not support cloning (for example,
1308:             *         an item label generator).
1309:             */
1310:            public Object clone() throws CloneNotSupportedException {
1311:
1312:                AbstractCategoryItemRenderer clone = (AbstractCategoryItemRenderer) super 
1313:                        .clone();
1314:
1315:                if (this .itemLabelGenerator != null) {
1316:                    if (this .itemLabelGenerator instanceof  PublicCloneable) {
1317:                        PublicCloneable pc = (PublicCloneable) this .itemLabelGenerator;
1318:                        clone.itemLabelGenerator = (CategoryItemLabelGenerator) pc
1319:                                .clone();
1320:                    } else {
1321:                        throw new CloneNotSupportedException(
1322:                                "ItemLabelGenerator not cloneable.");
1323:                    }
1324:                }
1325:
1326:                if (this .itemLabelGeneratorList != null) {
1327:                    clone.itemLabelGeneratorList = (ObjectList) this .itemLabelGeneratorList
1328:                            .clone();
1329:                }
1330:
1331:                if (this .baseItemLabelGenerator != null) {
1332:                    if (this .baseItemLabelGenerator instanceof  PublicCloneable) {
1333:                        PublicCloneable pc = (PublicCloneable) this .baseItemLabelGenerator;
1334:                        clone.baseItemLabelGenerator = (CategoryItemLabelGenerator) pc
1335:                                .clone();
1336:                    } else {
1337:                        throw new CloneNotSupportedException(
1338:                                "ItemLabelGenerator not cloneable.");
1339:                    }
1340:                }
1341:
1342:                if (this .toolTipGenerator != null) {
1343:                    if (this .toolTipGenerator instanceof  PublicCloneable) {
1344:                        PublicCloneable pc = (PublicCloneable) this .toolTipGenerator;
1345:                        clone.toolTipGenerator = (CategoryToolTipGenerator) pc
1346:                                .clone();
1347:                    } else {
1348:                        throw new CloneNotSupportedException(
1349:                                "Tool tip generator not cloneable.");
1350:                    }
1351:                }
1352:
1353:                if (this .toolTipGeneratorList != null) {
1354:                    clone.toolTipGeneratorList = (ObjectList) this .toolTipGeneratorList
1355:                            .clone();
1356:                }
1357:
1358:                if (this .baseToolTipGenerator != null) {
1359:                    if (this .baseToolTipGenerator instanceof  PublicCloneable) {
1360:                        PublicCloneable pc = (PublicCloneable) this .baseToolTipGenerator;
1361:                        clone.baseToolTipGenerator = (CategoryToolTipGenerator) pc
1362:                                .clone();
1363:                    } else {
1364:                        throw new CloneNotSupportedException(
1365:                                "Base tool tip generator not cloneable.");
1366:                    }
1367:                }
1368:
1369:                if (this .itemURLGenerator != null) {
1370:                    if (this .itemURLGenerator instanceof  PublicCloneable) {
1371:                        PublicCloneable pc = (PublicCloneable) this .itemURLGenerator;
1372:                        clone.itemURLGenerator = (CategoryURLGenerator) pc
1373:                                .clone();
1374:                    } else {
1375:                        throw new CloneNotSupportedException(
1376:                                "Item URL generator not cloneable.");
1377:                    }
1378:                }
1379:
1380:                if (this .itemURLGeneratorList != null) {
1381:                    clone.itemURLGeneratorList = (ObjectList) this .itemURLGeneratorList
1382:                            .clone();
1383:                }
1384:
1385:                if (this .baseItemURLGenerator != null) {
1386:                    if (this .baseItemURLGenerator instanceof  PublicCloneable) {
1387:                        PublicCloneable pc = (PublicCloneable) this .baseItemURLGenerator;
1388:                        clone.baseItemURLGenerator = (CategoryURLGenerator) pc
1389:                                .clone();
1390:                    } else {
1391:                        throw new CloneNotSupportedException(
1392:                                "Base item URL generator not cloneable.");
1393:                    }
1394:                }
1395:
1396:                if (this .legendItemLabelGenerator instanceof  PublicCloneable) {
1397:                    clone.legendItemLabelGenerator = (CategorySeriesLabelGenerator) ObjectUtilities
1398:                            .clone(this .legendItemLabelGenerator);
1399:                }
1400:                if (this .legendItemToolTipGenerator instanceof  PublicCloneable) {
1401:                    clone.legendItemToolTipGenerator = (CategorySeriesLabelGenerator) ObjectUtilities
1402:                            .clone(this .legendItemToolTipGenerator);
1403:                }
1404:                if (this .legendItemURLGenerator instanceof  PublicCloneable) {
1405:                    clone.legendItemURLGenerator = (CategorySeriesLabelGenerator) ObjectUtilities
1406:                            .clone(this .legendItemURLGenerator);
1407:                }
1408:                return clone;
1409:            }
1410:
1411:            /**
1412:             * Returns a domain axis for a plot.
1413:             *
1414:             * @param plot  the plot.
1415:             * @param index  the axis index.
1416:             *
1417:             * @return A domain axis.
1418:             */
1419:            protected CategoryAxis getDomainAxis(CategoryPlot plot, int index) {
1420:                CategoryAxis result = plot.getDomainAxis(index);
1421:                if (result == null) {
1422:                    result = plot.getDomainAxis();
1423:                }
1424:                return result;
1425:            }
1426:
1427:            /**
1428:             * Returns a range axis for a plot.
1429:             *
1430:             * @param plot  the plot.
1431:             * @param index  the axis index.
1432:             *
1433:             * @return A range axis.
1434:             */
1435:            protected ValueAxis getRangeAxis(CategoryPlot plot, int index) {
1436:                ValueAxis result = plot.getRangeAxis(index);
1437:                if (result == null) {
1438:                    result = plot.getRangeAxis();
1439:                }
1440:                return result;
1441:            }
1442:
1443:            /**
1444:             * Returns a (possibly empty) collection of legend items for the series
1445:             * that this renderer is responsible for drawing.
1446:             *
1447:             * @return The legend item collection (never <code>null</code>).
1448:             *
1449:             * @see #getLegendItem(int, int)
1450:             */
1451:            public LegendItemCollection getLegendItems() {
1452:                if (this .plot == null) {
1453:                    return new LegendItemCollection();
1454:                }
1455:                LegendItemCollection result = new LegendItemCollection();
1456:                int index = this .plot.getIndexOf(this );
1457:                CategoryDataset dataset = this .plot.getDataset(index);
1458:                if (dataset != null) {
1459:                    int seriesCount = dataset.getRowCount();
1460:                    for (int i = 0; i < seriesCount; i++) {
1461:                        if (isSeriesVisibleInLegend(i)) {
1462:                            LegendItem item = getLegendItem(index, i);
1463:                            if (item != null) {
1464:                                result.add(item);
1465:                            }
1466:                        }
1467:                    }
1468:
1469:                }
1470:                return result;
1471:            }
1472:
1473:            /**
1474:             * Returns the legend item label generator.
1475:             *
1476:             * @return The label generator (never <code>null</code>).
1477:             *
1478:             * @see #setLegendItemLabelGenerator(CategorySeriesLabelGenerator)
1479:             */
1480:            public CategorySeriesLabelGenerator getLegendItemLabelGenerator() {
1481:                return this .legendItemLabelGenerator;
1482:            }
1483:
1484:            /**
1485:             * Sets the legend item label generator and sends a
1486:             * {@link RendererChangeEvent} to all registered listeners.
1487:             *
1488:             * @param generator  the generator (<code>null</code> not permitted).
1489:             *
1490:             * @see #getLegendItemLabelGenerator()
1491:             */
1492:            public void setLegendItemLabelGenerator(
1493:                    CategorySeriesLabelGenerator generator) {
1494:                if (generator == null) {
1495:                    throw new IllegalArgumentException(
1496:                            "Null 'generator' argument.");
1497:                }
1498:                this .legendItemLabelGenerator = generator;
1499:                notifyListeners(new RendererChangeEvent(this ));
1500:            }
1501:
1502:            /**
1503:             * Returns the legend item tool tip generator.
1504:             *
1505:             * @return The tool tip generator (possibly <code>null</code>).
1506:             *
1507:             * @see #setLegendItemToolTipGenerator(CategorySeriesLabelGenerator)
1508:             */
1509:            public CategorySeriesLabelGenerator getLegendItemToolTipGenerator() {
1510:                return this .legendItemToolTipGenerator;
1511:            }
1512:
1513:            /**
1514:             * Sets the legend item tool tip generator and sends a
1515:             * {@link RendererChangeEvent} to all registered listeners.
1516:             *
1517:             * @param generator  the generator (<code>null</code> permitted).
1518:             *
1519:             * @see #setLegendItemToolTipGenerator(CategorySeriesLabelGenerator)
1520:             */
1521:            public void setLegendItemToolTipGenerator(
1522:                    CategorySeriesLabelGenerator generator) {
1523:                this .legendItemToolTipGenerator = generator;
1524:                notifyListeners(new RendererChangeEvent(this ));
1525:            }
1526:
1527:            /**
1528:             * Returns the legend item URL generator.
1529:             *
1530:             * @return The URL generator (possibly <code>null</code>).
1531:             *
1532:             * @see #setLegendItemURLGenerator(CategorySeriesLabelGenerator)
1533:             */
1534:            public CategorySeriesLabelGenerator getLegendItemURLGenerator() {
1535:                return this .legendItemURLGenerator;
1536:            }
1537:
1538:            /**
1539:             * Sets the legend item URL generator and sends a
1540:             * {@link RendererChangeEvent} to all registered listeners.
1541:             *
1542:             * @param generator  the generator (<code>null</code> permitted).
1543:             *
1544:             * @see #getLegendItemURLGenerator()
1545:             */
1546:            public void setLegendItemURLGenerator(
1547:                    CategorySeriesLabelGenerator generator) {
1548:                this .legendItemURLGenerator = generator;
1549:                notifyListeners(new RendererChangeEvent(this ));
1550:            }
1551:
1552:            /**
1553:             * Adds an entity with the specified hotspot.
1554:             *
1555:             * @param entities  the entity collection.
1556:             * @param dataset  the dataset.
1557:             * @param row  the row index.
1558:             * @param column  the column index.
1559:             * @param hotspot  the hotspot.
1560:             */
1561:            protected void addItemEntity(EntityCollection entities,
1562:                    CategoryDataset dataset, int row, int column, Shape hotspot) {
1563:
1564:                String tip = null;
1565:                CategoryToolTipGenerator tipster = getToolTipGenerator(row,
1566:                        column);
1567:                if (tipster != null) {
1568:                    tip = tipster.generateToolTip(dataset, row, column);
1569:                }
1570:                String url = null;
1571:                CategoryURLGenerator urlster = getItemURLGenerator(row, column);
1572:                if (urlster != null) {
1573:                    url = urlster.generateURL(dataset, row, column);
1574:                }
1575:                CategoryItemEntity entity = new CategoryItemEntity(hotspot,
1576:                        tip, url, dataset, dataset.getRowKey(row), dataset
1577:                                .getColumnKey(column));
1578:                entities.add(entity);
1579:
1580:            }
1581:
1582:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.