Source Code Cross Referenced for PiePlot.java in  » Chart » jfreechart » org » jfree » chart » plot » 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.plot 
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:         * PiePlot.java
0029:         * ------------
0030:         * (C) Copyright 2000-2007, by Andrzej Porebski and Contributors.
0031:         *
0032:         * Original Author:  Andrzej Porebski;
0033:         * Contributor(s):   David Gilbert (for Object Refinery Limited);
0034:         *                   Martin Cordova (percentages in labels);
0035:         *                   Richard Atkinson (URL support for image maps);
0036:         *                   Christian W. Zuckschwerdt;
0037:         *                   Arnaud Lelievre;
0038:         *                   Andreas Schroeder (very minor);
0039:         *
0040:         * $Id: PiePlot.java,v 1.17.2.25 2007/06/14 15:04:21 mungady Exp $
0041:         *
0042:         * Changes (from 21-Jun-2001)
0043:         * --------------------------
0044:         * 21-Jun-2001 : Removed redundant JFreeChart parameter from constructors (DG);
0045:         * 18-Sep-2001 : Updated header (DG);
0046:         * 15-Oct-2001 : Data source classes moved to com.jrefinery.data.* (DG);
0047:         * 19-Oct-2001 : Moved series paint and stroke methods from JFreeChart.java to 
0048:         *               Plot.java (DG);
0049:         * 22-Oct-2001 : Renamed DataSource.java --> Dataset.java etc. (DG);
0050:         * 13-Nov-2001 : Modified plot subclasses so that null axes are possible for 
0051:         *               pie plot (DG);
0052:         * 17-Nov-2001 : Added PieDataset interface and amended this class accordingly,
0053:         *               and completed removal of BlankAxis class as it is no longer 
0054:         *               required (DG);
0055:         * 19-Nov-2001 : Changed 'drawCircle' property to 'circular' property (DG);
0056:         * 21-Nov-2001 : Added options for exploding pie sections and filled out range 
0057:         *               of properties (DG);
0058:         *               Added option for percentages in chart labels, based on code
0059:         *               by Martin Cordova (DG);
0060:         * 30-Nov-2001 : Changed default font from "Arial" --> "SansSerif" (DG);
0061:         * 12-Dec-2001 : Removed unnecessary 'throws' clause in constructor (DG);
0062:         * 13-Dec-2001 : Added tooltips (DG);
0063:         * 16-Jan-2002 : Renamed tooltips class (DG);
0064:         * 22-Jan-2002 : Fixed bug correlating legend labels with pie data (DG);
0065:         * 05-Feb-2002 : Added alpha-transparency to plot class, and updated 
0066:         *               constructors accordingly (DG);
0067:         * 06-Feb-2002 : Added optional background image and alpha-transparency to Plot
0068:         *               and subclasses.  Clipped drawing within plot area (DG);
0069:         * 26-Mar-2002 : Added an empty zoom method (DG);
0070:         * 18-Apr-2002 : PieDataset is no longer sorted (oldman);
0071:         * 23-Apr-2002 : Moved dataset from JFreeChart to Plot.  Added 
0072:         *               getLegendItemLabels() method (DG);
0073:         * 19-Jun-2002 : Added attributes to control starting angle and direction 
0074:         *               (default is now clockwise) (DG);
0075:         * 25-Jun-2002 : Removed redundant imports (DG);
0076:         * 02-Jul-2002 : Fixed sign of percentage bug introduced in 0.9.2 (DG);
0077:         * 16-Jul-2002 : Added check for null dataset in getLegendItemLabels() (DG);
0078:         * 30-Jul-2002 : Moved summation code to DatasetUtilities (DG);
0079:         * 05-Aug-2002 : Added URL support for image maps - new member variable for
0080:         *               urlGenerator, modified constructor and minor change to the 
0081:         *               draw method (RA);
0082:         * 18-Sep-2002 : Modified the percent label creation and added setters for the
0083:         *               formatters (AS);
0084:         * 24-Sep-2002 : Added getLegendItems() method (DG);
0085:         * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
0086:         * 09-Oct-2002 : Added check for null entity collection (DG);
0087:         * 30-Oct-2002 : Changed PieDataset interface (DG);
0088:         * 18-Nov-2002 : Changed CategoryDataset to TableDataset (DG);
0089:         * 02-Jan-2003 : Fixed "no data" message (DG);
0090:         * 23-Jan-2003 : Modified to extract data from rows OR columns in 
0091:         *               CategoryDataset (DG);
0092:         * 14-Feb-2003 : Fixed label drawing so that foreground alpha does not apply 
0093:         *               (bug id 685536) (DG);
0094:         * 07-Mar-2003 : Modified to pass pieIndex on to PieSectionEntity and tooltip 
0095:         *               and URL generators (DG);
0096:         * 21-Mar-2003 : Added a minimum angle for drawing arcs 
0097:         *               (see bug id 620031) (DG);
0098:         * 24-Apr-2003 : Switched around PieDataset and KeyedValuesDataset (DG);
0099:         * 02-Jun-2003 : Fixed bug 721733 (DG);
0100:         * 30-Jul-2003 : Modified entity constructor (CZ);
0101:         * 19-Aug-2003 : Implemented Cloneable (DG);
0102:         * 29-Aug-2003 : Fixed bug 796936 (null pointer on setOutlinePaint()) (DG);
0103:         * 08-Sep-2003 : Added internationalization via use of properties 
0104:         *               resourceBundle (RFE 690236) (AL);
0105:         * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
0106:         * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
0107:         * 05-Nov-2003 : Fixed missing legend bug (DG);
0108:         * 10-Nov-2003 : Re-added the DatasetChangeListener to constructors (CZ);
0109:         * 29-Jan-2004 : Fixed clipping bug in draw() method (DG);
0110:         * 11-Mar-2004 : Major overhaul to improve labelling (DG);
0111:         * 31-Mar-2004 : Made an adjustment for the plot area when the label generator 
0112:         *               is null.  Fixed null pointer exception when the label 
0113:         *               generator returns null for a label (DG);
0114:         * 06-Apr-2004 : Added getter, setter, serialization and draw support for 
0115:         *               labelBackgroundPaint (AS);
0116:         * 08-Apr-2004 : Added flag to control whether null values are ignored or 
0117:         *               not (DG);
0118:         * 15-Apr-2004 : Fixed some minor warnings from Eclipse (DG);
0119:         * 26-Apr-2004 : Added attributes for label outline and shadow (DG);
0120:         * 04-Oct-2004 : Renamed ShapeUtils --> ShapeUtilities (DG);
0121:         * 04-Nov-2004 : Fixed null pointer exception with new LegendTitle class (DG);
0122:         * 09-Nov-2004 : Added user definable legend item shape (DG);
0123:         * 25-Nov-2004 : Added new legend label generator (DG);
0124:         * 20-Apr-2005 : Added a tool tip generator for legend labels (DG);
0125:         * 26-Apr-2005 : Removed LOGGER (DG);
0126:         * 05-May-2005 : Updated draw() method parameters (DG);
0127:         * 10-May-2005 : Added flag to control visibility of label linking lines, plus
0128:         *               another flag to control the handling of zero values (DG);
0129:         * 08-Jun-2005 : Fixed bug in getLegendItems() method (not respecting flags
0130:         *               for ignoring null and zero values), and fixed equals() method 
0131:         *               to handle GradientPaint (DG);
0132:         * 15-Jul-2005 : Added sectionOutlinesVisible attribute (DG);
0133:         * ------------- JFREECHART 1.0.x ---------------------------------------------
0134:         * 09-Jan-2006 : Fixed bug 1400442, inconsistent treatment of null and zero
0135:         *               values in dataset (DG);
0136:         * 28-Feb-2006 : Fixed bug 1440415, bad distribution of pie section 
0137:         *               labels (DG);
0138:         * 27-Sep-2006 : Initialised baseSectionPaint correctly, added lookup methods
0139:         *               for section paint, outline paint and outline stroke (DG);
0140:         * 27-Sep-2006 : Refactored paint and stroke methods to use keys rather than
0141:         *               section indices (DG);
0142:         * 03-Oct-2006 : Replaced call to JRE 1.5 method (DG);
0143:         * 23-Nov-2006 : Added support for URLs for the legend items (DG);
0144:         * 24-Nov-2006 : Cloning fixes (DG);
0145:         * 17-Apr-2007 : Check for null label in legend items (DG);
0146:         * 19-Apr-2007 : Deprecated override settings (DG);
0147:         * 18-May-2007 : Set dataset for LegendItem (DG);
0148:         * 14-Jun-2007 : Added label distributor attribute (DG);
0149:         *          
0150:         */
0151:
0152:        package org.jfree.chart.plot;
0153:
0154:        import java.awt.AlphaComposite;
0155:        import java.awt.BasicStroke;
0156:        import java.awt.Color;
0157:        import java.awt.Composite;
0158:        import java.awt.Font;
0159:        import java.awt.Graphics2D;
0160:        import java.awt.Paint;
0161:        import java.awt.Shape;
0162:        import java.awt.Stroke;
0163:        import java.awt.geom.Arc2D;
0164:        import java.awt.geom.Line2D;
0165:        import java.awt.geom.Point2D;
0166:        import java.awt.geom.Rectangle2D;
0167:        import java.io.IOException;
0168:        import java.io.ObjectInputStream;
0169:        import java.io.ObjectOutputStream;
0170:        import java.io.Serializable;
0171:        import java.util.Iterator;
0172:        import java.util.List;
0173:        import java.util.Map;
0174:        import java.util.ResourceBundle;
0175:        import java.util.TreeMap;
0176:
0177:        import org.jfree.chart.LegendItem;
0178:        import org.jfree.chart.LegendItemCollection;
0179:        import org.jfree.chart.PaintMap;
0180:        import org.jfree.chart.StrokeMap;
0181:        import org.jfree.chart.entity.EntityCollection;
0182:        import org.jfree.chart.entity.PieSectionEntity;
0183:        import org.jfree.chart.event.PlotChangeEvent;
0184:        import org.jfree.chart.labels.PieSectionLabelGenerator;
0185:        import org.jfree.chart.labels.PieToolTipGenerator;
0186:        import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
0187:        import org.jfree.chart.urls.PieURLGenerator;
0188:        import org.jfree.data.DefaultKeyedValues;
0189:        import org.jfree.data.KeyedValues;
0190:        import org.jfree.data.general.DatasetChangeEvent;
0191:        import org.jfree.data.general.DatasetUtilities;
0192:        import org.jfree.data.general.PieDataset;
0193:        import org.jfree.io.SerialUtilities;
0194:        import org.jfree.text.G2TextMeasurer;
0195:        import org.jfree.text.TextBlock;
0196:        import org.jfree.text.TextBox;
0197:        import org.jfree.text.TextUtilities;
0198:        import org.jfree.ui.RectangleAnchor;
0199:        import org.jfree.ui.RectangleInsets;
0200:        import org.jfree.util.ObjectUtilities;
0201:        import org.jfree.util.PaintUtilities;
0202:        import org.jfree.util.PublicCloneable;
0203:        import org.jfree.util.Rotation;
0204:        import org.jfree.util.ShapeUtilities;
0205:
0206:        /**
0207:         * A plot that displays data in the form of a pie chart, using data from any 
0208:         * class that implements the {@link PieDataset} interface.
0209:         * <P>
0210:         * Special notes:
0211:         * <ol>
0212:         * <li>the default starting point is 12 o'clock and the pie sections proceed
0213:         * in a clockwise direction, but these settings can be changed;</li>
0214:         * <li>negative values in the dataset are ignored;</li>
0215:         * <li>there are utility methods for creating a {@link PieDataset} from a
0216:         * {@link org.jfree.data.category.CategoryDataset};</li>
0217:         * </ol>
0218:         *
0219:         * @see Plot
0220:         * @see PieDataset
0221:         */
0222:        public class PiePlot extends Plot implements  Cloneable, Serializable {
0223:
0224:            /** For serialization. */
0225:            private static final long serialVersionUID = -795612466005590431L;
0226:
0227:            /** The default interior gap. */
0228:            public static final double DEFAULT_INTERIOR_GAP = 0.25;
0229:
0230:            /** The maximum interior gap (currently 40%). */
0231:            public static final double MAX_INTERIOR_GAP = 0.40;
0232:
0233:            /** The default starting angle for the pie chart. */
0234:            public static final double DEFAULT_START_ANGLE = 90.0;
0235:
0236:            /** The default section label font. */
0237:            public static final Font DEFAULT_LABEL_FONT = new Font("SansSerif",
0238:                    Font.PLAIN, 10);
0239:
0240:            /** The default section label paint. */
0241:            public static final Paint DEFAULT_LABEL_PAINT = Color.black;
0242:
0243:            /** The default section label background paint. */
0244:            public static final Paint DEFAULT_LABEL_BACKGROUND_PAINT = new Color(
0245:                    255, 255, 192);
0246:
0247:            /** The default section label outline paint. */
0248:            public static final Paint DEFAULT_LABEL_OUTLINE_PAINT = Color.black;
0249:
0250:            /** The default section label outline stroke. */
0251:            public static final Stroke DEFAULT_LABEL_OUTLINE_STROKE = new BasicStroke(
0252:                    0.5f);
0253:
0254:            /** The default section label shadow paint. */
0255:            public static final Paint DEFAULT_LABEL_SHADOW_PAINT = Color.lightGray;
0256:
0257:            /** The default minimum arc angle to draw. */
0258:            public static final double DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW = 0.00001;
0259:
0260:            /** The dataset for the pie chart. */
0261:            private PieDataset dataset;
0262:
0263:            /** The pie index (used by the {@link MultiplePiePlot} class). */
0264:            private int pieIndex;
0265:
0266:            /** 
0267:             * The amount of space left around the outside of the pie plot, expressed 
0268:             * as a percentage. 
0269:             */
0270:            private double interiorGap;
0271:
0272:            /** Flag determining whether to draw an ellipse or a perfect circle. */
0273:            private boolean circular;
0274:
0275:            /** The starting angle. */
0276:            private double startAngle;
0277:
0278:            /** The direction for the pie segments. */
0279:            private Rotation direction;
0280:
0281:            /** 
0282:             * The paint for ALL sections (overrides list).
0283:             * 
0284:             * @deprecated This field is redundant, it is sufficient to use 
0285:             *     sectionPaintMap and baseSectionPaint.  Deprecated as of version 
0286:             *     1.0.6.
0287:             */
0288:            private transient Paint sectionPaint;
0289:
0290:            /** The section paint map. */
0291:            private PaintMap sectionPaintMap;
0292:
0293:            /** The base section paint (fallback). */
0294:            private transient Paint baseSectionPaint;
0295:
0296:            /** 
0297:             * A flag that controls whether or not an outline is drawn for each
0298:             * section in the plot.
0299:             */
0300:            private boolean sectionOutlinesVisible;
0301:
0302:            /** 
0303:             * The outline paint for ALL sections (overrides list). 
0304:             * 
0305:             * @deprecated This field is redundant, it is sufficient to use 
0306:             *     sectionOutlinePaintMap and baseSectionOutlinePaint.  Deprecated as 
0307:             *     of version 1.0.6.
0308:             */
0309:            private transient Paint sectionOutlinePaint;
0310:
0311:            /** The section outline paint map. */
0312:            private PaintMap sectionOutlinePaintMap;
0313:
0314:            /** The base section outline paint (fallback). */
0315:            private transient Paint baseSectionOutlinePaint;
0316:
0317:            /** 
0318:             * The outline stroke for ALL sections (overrides list). 
0319:             * 
0320:             * @deprecated This field is redundant, it is sufficient to use 
0321:             *     sectionOutlineStrokeMap and baseSectionOutlineStroke.  Deprecated as 
0322:             *     of version 1.0.6.
0323:             */
0324:            private transient Stroke sectionOutlineStroke;
0325:
0326:            /** The section outline stroke map. */
0327:            private StrokeMap sectionOutlineStrokeMap;
0328:
0329:            /** The base section outline stroke (fallback). */
0330:            private transient Stroke baseSectionOutlineStroke;
0331:
0332:            /** The shadow paint. */
0333:            private transient Paint shadowPaint = Color.gray;
0334:
0335:            /** The x-offset for the shadow effect. */
0336:            private double shadowXOffset = 4.0f;
0337:
0338:            /** The y-offset for the shadow effect. */
0339:            private double shadowYOffset = 4.0f;
0340:
0341:            /** The percentage amount to explode each pie section. */
0342:            private Map explodePercentages;
0343:
0344:            /** The section label generator. */
0345:            private PieSectionLabelGenerator labelGenerator;
0346:
0347:            /** The font used to display the section labels. */
0348:            private Font labelFont;
0349:
0350:            /** The color used to draw the section labels. */
0351:            private transient Paint labelPaint;
0352:
0353:            /** The color used to draw the background of the section labels. */
0354:            private transient Paint labelBackgroundPaint;
0355:
0356:            /** 
0357:             * The paint used to draw the outline of the section labels 
0358:             * (<code>null</code> permitted). 
0359:             */
0360:            private transient Paint labelOutlinePaint;
0361:
0362:            /** 
0363:             * The stroke used to draw the outline of the section labels 
0364:             * (<code>null</code> permitted). 
0365:             */
0366:            private transient Stroke labelOutlineStroke;
0367:
0368:            /** 
0369:             * The paint used to draw the shadow for the section labels 
0370:             * (<code>null</code> permitted). 
0371:             */
0372:            private transient Paint labelShadowPaint;
0373:
0374:            /** The maximum label width as a percentage of the plot width. */
0375:            private double maximumLabelWidth = 0.20;
0376:
0377:            /** 
0378:             * The gap between the labels and the plot as a percentage of the plot 
0379:             * width. 
0380:             */
0381:            private double labelGap = 0.05;
0382:
0383:            /** A flag that controls whether or not the label links are drawn. */
0384:            private boolean labelLinksVisible;
0385:
0386:            /** The link margin. */
0387:            private double labelLinkMargin = 0.05;
0388:
0389:            /** The paint used for the label linking lines. */
0390:            private transient Paint labelLinkPaint = Color.black;
0391:
0392:            /** The stroke used for the label linking lines. */
0393:            private transient Stroke labelLinkStroke = new BasicStroke(0.5f);
0394:
0395:            /** 
0396:             * The pie section label distributor.
0397:             * 
0398:             * @since 1.0.6
0399:             */
0400:            private AbstractPieLabelDistributor labelDistributor;
0401:
0402:            /** The tooltip generator. */
0403:            private PieToolTipGenerator toolTipGenerator;
0404:
0405:            /** The URL generator. */
0406:            private PieURLGenerator urlGenerator;
0407:
0408:            /** The legend label generator. */
0409:            private PieSectionLabelGenerator legendLabelGenerator;
0410:
0411:            /** A tool tip generator for the legend. */
0412:            private PieSectionLabelGenerator legendLabelToolTipGenerator;
0413:
0414:            /** 
0415:             * A URL generator for the legend items (optional).  
0416:             *
0417:             * @since 1.0.4. 
0418:             */
0419:            private PieURLGenerator legendLabelURLGenerator;
0420:
0421:            /** 
0422:             * A flag that controls whether <code>null</code> values are ignored.  
0423:             */
0424:            private boolean ignoreNullValues;
0425:
0426:            /**
0427:             * A flag that controls whether zero values are ignored.
0428:             */
0429:            private boolean ignoreZeroValues;
0430:
0431:            /** The legend item shape. */
0432:            private transient Shape legendItemShape;
0433:
0434:            /**
0435:             * The smallest arc angle that will get drawn (this is to avoid a bug in 
0436:             * various Java implementations that causes the JVM to crash).  See this 
0437:             * link for details:
0438:             *
0439:             * http://www.jfree.org/phpBB2/viewtopic.php?t=2707
0440:             *
0441:             * ...and this bug report in the Java Bug Parade:
0442:             *
0443:             * http://developer.java.sun.com/developer/bugParade/bugs/4836495.html
0444:             */
0445:            private double minimumArcAngleToDraw;
0446:
0447:            /** The resourceBundle for the localization. */
0448:            protected static ResourceBundle localizationResources = ResourceBundle
0449:                    .getBundle("org.jfree.chart.plot.LocalizationBundle");
0450:
0451:            /**
0452:             * Creates a new plot.  The dataset is initially set to <code>null</code>.
0453:             */
0454:            public PiePlot() {
0455:                this (null);
0456:            }
0457:
0458:            /**
0459:             * Creates a plot that will draw a pie chart for the specified dataset.
0460:             *
0461:             * @param dataset  the dataset (<code>null</code> permitted).
0462:             */
0463:            public PiePlot(PieDataset dataset) {
0464:                super ();
0465:                this .dataset = dataset;
0466:                if (dataset != null) {
0467:                    dataset.addChangeListener(this );
0468:                }
0469:                this .pieIndex = 0;
0470:
0471:                this .interiorGap = DEFAULT_INTERIOR_GAP;
0472:                this .circular = true;
0473:                this .startAngle = DEFAULT_START_ANGLE;
0474:                this .direction = Rotation.CLOCKWISE;
0475:                this .minimumArcAngleToDraw = DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW;
0476:
0477:                this .sectionPaint = null;
0478:                this .sectionPaintMap = new PaintMap();
0479:                this .baseSectionPaint = Color.gray;
0480:
0481:                this .sectionOutlinesVisible = true;
0482:                this .sectionOutlinePaint = null;
0483:                this .sectionOutlinePaintMap = new PaintMap();
0484:                this .baseSectionOutlinePaint = DEFAULT_OUTLINE_PAINT;
0485:
0486:                this .sectionOutlineStroke = null;
0487:                this .sectionOutlineStrokeMap = new StrokeMap();
0488:                this .baseSectionOutlineStroke = DEFAULT_OUTLINE_STROKE;
0489:
0490:                this .explodePercentages = new TreeMap();
0491:
0492:                this .labelGenerator = new StandardPieSectionLabelGenerator();
0493:                this .labelFont = DEFAULT_LABEL_FONT;
0494:                this .labelPaint = DEFAULT_LABEL_PAINT;
0495:                this .labelBackgroundPaint = DEFAULT_LABEL_BACKGROUND_PAINT;
0496:                this .labelOutlinePaint = DEFAULT_LABEL_OUTLINE_PAINT;
0497:                this .labelOutlineStroke = DEFAULT_LABEL_OUTLINE_STROKE;
0498:                this .labelShadowPaint = DEFAULT_LABEL_SHADOW_PAINT;
0499:                this .labelLinksVisible = true;
0500:                this .labelDistributor = new PieLabelDistributor(0);
0501:
0502:                this .toolTipGenerator = null;
0503:                this .urlGenerator = null;
0504:                this .legendLabelGenerator = new StandardPieSectionLabelGenerator();
0505:                this .legendLabelToolTipGenerator = null;
0506:                this .legendLabelURLGenerator = null;
0507:                this .legendItemShape = Plot.DEFAULT_LEGEND_ITEM_CIRCLE;
0508:
0509:                this .ignoreNullValues = false;
0510:                this .ignoreZeroValues = false;
0511:            }
0512:
0513:            /**
0514:             * Returns the dataset.
0515:             *
0516:             * @return The dataset (possibly <code>null</code>).
0517:             * 
0518:             * @see #setDataset(PieDataset)
0519:             */
0520:            public PieDataset getDataset() {
0521:                return this .dataset;
0522:            }
0523:
0524:            /**
0525:             * Sets the dataset and sends a {@link DatasetChangeEvent} to 'this'.
0526:             *
0527:             * @param dataset  the dataset (<code>null</code> permitted).
0528:             * 
0529:             * @see #getDataset()
0530:             */
0531:            public void setDataset(PieDataset dataset) {
0532:                // if there is an existing dataset, remove the plot from the list of 
0533:                // change listeners...
0534:                PieDataset existing = this .dataset;
0535:                if (existing != null) {
0536:                    existing.removeChangeListener(this );
0537:                }
0538:
0539:                // set the new dataset, and register the chart as a change listener...
0540:                this .dataset = dataset;
0541:                if (dataset != null) {
0542:                    setDatasetGroup(dataset.getGroup());
0543:                    dataset.addChangeListener(this );
0544:                }
0545:
0546:                // send a dataset change event to self...
0547:                DatasetChangeEvent event = new DatasetChangeEvent(this , dataset);
0548:                datasetChanged(event);
0549:            }
0550:
0551:            /**
0552:             * Returns the pie index (this is used by the {@link MultiplePiePlot} class
0553:             * to track subplots).
0554:             * 
0555:             * @return The pie index.
0556:             * 
0557:             * @see #setPieIndex(int)
0558:             */
0559:            public int getPieIndex() {
0560:                return this .pieIndex;
0561:            }
0562:
0563:            /**
0564:             * Sets the pie index (this is used by the {@link MultiplePiePlot} class to 
0565:             * track subplots).
0566:             * 
0567:             * @param index  the index.
0568:             * 
0569:             * @see #getPieIndex()
0570:             */
0571:            public void setPieIndex(int index) {
0572:                this .pieIndex = index;
0573:            }
0574:
0575:            /**
0576:             * Returns the start angle for the first pie section.  This is measured in 
0577:             * degrees starting from 3 o'clock and measuring anti-clockwise.
0578:             *
0579:             * @return The start angle.
0580:             * 
0581:             * @see #setStartAngle(double)
0582:             */
0583:            public double getStartAngle() {
0584:                return this .startAngle;
0585:            }
0586:
0587:            /**
0588:             * Sets the starting angle and sends a {@link PlotChangeEvent} to all 
0589:             * registered listeners.  The initial default value is 90 degrees, which 
0590:             * corresponds to 12 o'clock.  A value of zero corresponds to 3 o'clock...
0591:             * this is the encoding used by Java's Arc2D class.
0592:             *
0593:             * @param angle  the angle (in degrees).
0594:             * 
0595:             * @see #getStartAngle()
0596:             */
0597:            public void setStartAngle(double angle) {
0598:                this .startAngle = angle;
0599:                notifyListeners(new PlotChangeEvent(this ));
0600:            }
0601:
0602:            /**
0603:             * Returns the direction in which the pie sections are drawn (clockwise or 
0604:             * anti-clockwise).
0605:             *
0606:             * @return The direction (never <code>null</code>).
0607:             * 
0608:             * @see #setDirection(Rotation)
0609:             */
0610:            public Rotation getDirection() {
0611:                return this .direction;
0612:            }
0613:
0614:            /**
0615:             * Sets the direction in which the pie sections are drawn and sends a 
0616:             * {@link PlotChangeEvent} to all registered listeners.
0617:             *
0618:             * @param direction  the direction (<code>null</code> not permitted).
0619:             * 
0620:             * @see #getDirection()
0621:             */
0622:            public void setDirection(Rotation direction) {
0623:                if (direction == null) {
0624:                    throw new IllegalArgumentException(
0625:                            "Null 'direction' argument.");
0626:                }
0627:                this .direction = direction;
0628:                notifyListeners(new PlotChangeEvent(this ));
0629:
0630:            }
0631:
0632:            /**
0633:             * Returns the interior gap, measured as a percentage of the available 
0634:             * drawing space.
0635:             *
0636:             * @return The gap (as a percentage of the available drawing space).
0637:             * 
0638:             * @see #setInteriorGap(double)
0639:             */
0640:            public double getInteriorGap() {
0641:                return this .interiorGap;
0642:            }
0643:
0644:            /**
0645:             * Sets the interior gap and sends a {@link PlotChangeEvent} to all 
0646:             * registered listeners.  This controls the space between the edges of the 
0647:             * pie plot and the plot area itself (the region where the section labels 
0648:             * appear).
0649:             *
0650:             * @param percent  the gap (as a percentage of the available drawing space).
0651:             * 
0652:             * @see #getInteriorGap()
0653:             */
0654:            public void setInteriorGap(double percent) {
0655:
0656:                // check arguments...
0657:                if ((percent < 0.0) || (percent > MAX_INTERIOR_GAP)) {
0658:                    throw new IllegalArgumentException("Invalid 'percent' ("
0659:                            + percent + ") argument.");
0660:                }
0661:
0662:                // make the change...
0663:                if (this .interiorGap != percent) {
0664:                    this .interiorGap = percent;
0665:                    notifyListeners(new PlotChangeEvent(this ));
0666:                }
0667:
0668:            }
0669:
0670:            /**
0671:             * Returns a flag indicating whether the pie chart is circular, or
0672:             * stretched into an elliptical shape.
0673:             *
0674:             * @return A flag indicating whether the pie chart is circular.
0675:             * 
0676:             * @see #setCircular(boolean)
0677:             */
0678:            public boolean isCircular() {
0679:                return this .circular;
0680:            }
0681:
0682:            /**
0683:             * A flag indicating whether the pie chart is circular, or stretched into
0684:             * an elliptical shape.
0685:             *
0686:             * @param flag  the new value.
0687:             * 
0688:             * @see #isCircular()
0689:             */
0690:            public void setCircular(boolean flag) {
0691:                setCircular(flag, true);
0692:            }
0693:
0694:            /**
0695:             * Sets the circular attribute and, if requested, sends a 
0696:             * {@link PlotChangeEvent} to all registered listeners.
0697:             *
0698:             * @param circular  the new value of the flag.
0699:             * @param notify  notify listeners?
0700:             * 
0701:             * @see #isCircular()
0702:             */
0703:            public void setCircular(boolean circular, boolean notify) {
0704:                this .circular = circular;
0705:                if (notify) {
0706:                    notifyListeners(new PlotChangeEvent(this ));
0707:                }
0708:            }
0709:
0710:            /**
0711:             * Returns the flag that controls whether <code>null</code> values in the 
0712:             * dataset are ignored.  
0713:             * 
0714:             * @return A boolean.
0715:             * 
0716:             * @see #setIgnoreNullValues(boolean)
0717:             */
0718:            public boolean getIgnoreNullValues() {
0719:                return this .ignoreNullValues;
0720:            }
0721:
0722:            /**
0723:             * Sets a flag that controls whether <code>null</code> values are ignored, 
0724:             * and sends a {@link PlotChangeEvent} to all registered listeners.  At 
0725:             * present, this only affects whether or not the key is presented in the 
0726:             * legend.
0727:             * 
0728:             * @param flag  the flag.
0729:             * 
0730:             * @see #getIgnoreNullValues()
0731:             * @see #setIgnoreZeroValues(boolean)
0732:             */
0733:            public void setIgnoreNullValues(boolean flag) {
0734:                this .ignoreNullValues = flag;
0735:                notifyListeners(new PlotChangeEvent(this ));
0736:            }
0737:
0738:            /**
0739:             * Returns the flag that controls whether zero values in the 
0740:             * dataset are ignored.  
0741:             * 
0742:             * @return A boolean.
0743:             * 
0744:             * @see #setIgnoreZeroValues(boolean)
0745:             */
0746:            public boolean getIgnoreZeroValues() {
0747:                return this .ignoreZeroValues;
0748:            }
0749:
0750:            /**
0751:             * Sets a flag that controls whether zero values are ignored, 
0752:             * and sends a {@link PlotChangeEvent} to all registered listeners.  This 
0753:             * only affects whether or not a label appears for the non-visible
0754:             * pie section.
0755:             * 
0756:             * @param flag  the flag.
0757:             * 
0758:             * @see #getIgnoreZeroValues()
0759:             * @see #setIgnoreNullValues(boolean)
0760:             */
0761:            public void setIgnoreZeroValues(boolean flag) {
0762:                this .ignoreZeroValues = flag;
0763:                notifyListeners(new PlotChangeEvent(this ));
0764:            }
0765:
0766:            //// SECTION PAINT ////////////////////////////////////////////////////////
0767:
0768:            /**
0769:             * Returns the paint for the specified section.  This is equivalent to
0770:             * <code>lookupSectionPaint(section, false)</code>.
0771:             * 
0772:             * @param key  the section key.
0773:             * 
0774:             * @return The paint for the specified section.
0775:             * 
0776:             * @since 1.0.3
0777:             * 
0778:             * @see #lookupSectionPaint(Comparable, boolean)
0779:             */
0780:            protected Paint lookupSectionPaint(Comparable key) {
0781:                return lookupSectionPaint(key, false);
0782:            }
0783:
0784:            /**
0785:             * Returns the paint for the specified section.  The lookup involves these
0786:             * steps:
0787:             * <ul>
0788:             * <li>if {@link #getSectionPaint()} is non-<code>null</code>, return 
0789:             *         it;</li>
0790:             * <li>if {@link #getSectionPaint(int)} is non-<code>null</code> return 
0791:             *         it;</li>
0792:             * <li>if {@link #getSectionPaint(int)} is <code>null</code> but 
0793:             *         <code>autoPopulate</code> is <code>true</code>, attempt to fetch
0794:             *         a new paint from the drawing supplier 
0795:             *         ({@link #getDrawingSupplier()});
0796:             * <li>if all else fails, return {@link #getBaseSectionPaint()}.
0797:             * </ul> 
0798:             * 
0799:             * @param key  the section key.
0800:             * @param autoPopulate  a flag that controls whether the drawing supplier 
0801:             *     is used to auto-populate the section paint settings.
0802:             *     
0803:             * @return The paint.
0804:             * 
0805:             * @since 1.0.3
0806:             */
0807:            protected Paint lookupSectionPaint(Comparable key,
0808:                    boolean autoPopulate) {
0809:
0810:                // is there an override?
0811:                Paint result = getSectionPaint();
0812:                if (result != null) {
0813:                    return result;
0814:                }
0815:
0816:                // if not, check if there is a paint defined for the specified key
0817:                result = this .sectionPaintMap.getPaint(key);
0818:                if (result != null) {
0819:                    return result;
0820:                }
0821:
0822:                // nothing defined - do we autoPopulate?
0823:                if (autoPopulate) {
0824:                    DrawingSupplier ds = getDrawingSupplier();
0825:                    if (ds != null) {
0826:                        result = ds.getNextPaint();
0827:                        this .sectionPaintMap.put(key, result);
0828:                    } else {
0829:                        result = this .baseSectionPaint;
0830:                    }
0831:                } else {
0832:                    result = this .baseSectionPaint;
0833:                }
0834:                return result;
0835:            }
0836:
0837:            /**
0838:             * Returns the paint for ALL sections in the plot.
0839:             *
0840:             * @return The paint (possibly <code>null</code>).
0841:             * 
0842:             * @see #setSectionPaint(Paint)
0843:             * 
0844:             * @deprecated Use {@link #getSectionPaint(Comparable)} and 
0845:             *     {@link #getBaseSectionPaint()}.  Deprecated as of version 1.0.6.
0846:             */
0847:            public Paint getSectionPaint() {
0848:                return this .sectionPaint;
0849:            }
0850:
0851:            /**
0852:             * Sets the paint for ALL sections in the plot.  If this is set to
0853:             * </code>null</code>, then a list of paints is used instead (to allow
0854:             * different colors to be used for each section).
0855:             *
0856:             * @param paint  the paint (<code>null</code> permitted).
0857:             * 
0858:             * @see #getSectionPaint()
0859:             * 
0860:             * @deprecated Use {@link #setSectionPaint(Comparable, Paint)} and 
0861:             *     {@link #setBaseSectionPaint(Paint)}.  Deprecated as of version 1.0.6.
0862:             */
0863:            public void setSectionPaint(Paint paint) {
0864:                this .sectionPaint = paint;
0865:                notifyListeners(new PlotChangeEvent(this ));
0866:            }
0867:
0868:            /**
0869:             * Returns a key for the specified section.  If there is no such section 
0870:             * in the dataset, we generate a key.  This is to provide some backward
0871:             * compatibility for the (now deprecated) methods that get/set attributes 
0872:             * based on section indices.  The preferred way of doing this now is to
0873:             * link the attributes directly to the section key (there are new methods
0874:             * for this, starting from version 1.0.3).  
0875:             * 
0876:             * @param section  the section index.
0877:             * 
0878:             * @return The key.
0879:             *
0880:             * @since 1.0.3
0881:             */
0882:            protected Comparable getSectionKey(int section) {
0883:                Comparable key = null;
0884:                if (this .dataset != null) {
0885:                    if (section >= 0 && section < this .dataset.getItemCount()) {
0886:                        key = this .dataset.getKey(section);
0887:                    }
0888:                }
0889:                if (key == null) {
0890:                    key = new Integer(section);
0891:                }
0892:                return key;
0893:            }
0894:
0895:            /**
0896:             * Returns the paint associated with the specified key, or 
0897:             * <code>null</code> if there is no paint associated with the key.
0898:             * 
0899:             * @param key  the key (<code>null</code> not permitted).
0900:             * 
0901:             * @return The paint associated with the specified key, or 
0902:             *     <code>null</code>.
0903:             *     
0904:             * @throws IllegalArgumentException if <code>key</code> is 
0905:             *     <code>null</code>.
0906:             * 
0907:             * @see #setSectionPaint(Comparable, Paint)
0908:             * 
0909:             * @since 1.0.3
0910:             */
0911:            public Paint getSectionPaint(Comparable key) {
0912:                // null argument check delegated...
0913:                return this .sectionPaintMap.getPaint(key);
0914:            }
0915:
0916:            /**
0917:             * Sets the paint associated with the specified key, and sends a 
0918:             * {@link PlotChangeEvent} to all registered listeners.
0919:             * 
0920:             * @param key  the key (<code>null</code> not permitted).
0921:             * @param paint  the paint.
0922:             * 
0923:             * @throws IllegalArgumentException if <code>key</code> is 
0924:             *     <code>null</code>.
0925:             *     
0926:             * @see #getSectionPaint(Comparable)
0927:             * 
0928:             * @since 1.0.3
0929:             */
0930:            public void setSectionPaint(Comparable key, Paint paint) {
0931:                // null argument check delegated...
0932:                this .sectionPaintMap.put(key, paint);
0933:                notifyListeners(new PlotChangeEvent(this ));
0934:            }
0935:
0936:            /**
0937:             * Returns the base section paint.  This is used when no other paint is 
0938:             * defined, which is rare.  The default value is <code>Color.gray</code>.
0939:             * 
0940:             * @return The paint (never <code>null</code>).
0941:             * 
0942:             * @see #setBaseSectionPaint(Paint)
0943:             */
0944:            public Paint getBaseSectionPaint() {
0945:                return this .baseSectionPaint;
0946:            }
0947:
0948:            /**
0949:             * Sets the base section paint and sends a {@link PlotChangeEvent} to all
0950:             * registered listeners.
0951:             * 
0952:             * @param paint  the paint (<code>null</code> not permitted).
0953:             * 
0954:             * @see #getBaseSectionPaint()
0955:             */
0956:            public void setBaseSectionPaint(Paint paint) {
0957:                if (paint == null) {
0958:                    throw new IllegalArgumentException("Null 'paint' argument.");
0959:                }
0960:                this .baseSectionPaint = paint;
0961:                notifyListeners(new PlotChangeEvent(this ));
0962:            }
0963:
0964:            //// SECTION OUTLINE PAINT ////////////////////////////////////////////////
0965:
0966:            /**
0967:             * Returns the flag that controls whether or not the outline is drawn for
0968:             * each pie section.
0969:             * 
0970:             * @return The flag that controls whether or not the outline is drawn for
0971:             *         each pie section.
0972:             *         
0973:             * @see #setSectionOutlinesVisible(boolean)
0974:             */
0975:            public boolean getSectionOutlinesVisible() {
0976:                return this .sectionOutlinesVisible;
0977:            }
0978:
0979:            /**
0980:             * Sets the flag that controls whether or not the outline is drawn for 
0981:             * each pie section, and sends a {@link PlotChangeEvent} to all registered
0982:             * listeners.
0983:             * 
0984:             * @param visible  the flag.
0985:             * 
0986:             * @see #getSectionOutlinesVisible()
0987:             */
0988:            public void setSectionOutlinesVisible(boolean visible) {
0989:                this .sectionOutlinesVisible = visible;
0990:                notifyListeners(new PlotChangeEvent(this ));
0991:            }
0992:
0993:            /**
0994:             * Returns the outline paint for the specified section.  This is equivalent 
0995:             * to <code>lookupSectionPaint(section, false)</code>.
0996:             * 
0997:             * @param key  the section key.
0998:             * 
0999:             * @return The paint for the specified section.
1000:             * 
1001:             * @since 1.0.3
1002:             * 
1003:             * @see #lookupSectionOutlinePaint(Comparable, boolean)
1004:             */
1005:            protected Paint lookupSectionOutlinePaint(Comparable key) {
1006:                return lookupSectionOutlinePaint(key, false);
1007:            }
1008:
1009:            /**
1010:             * Returns the outline paint for the specified section.  The lookup 
1011:             * involves these steps:
1012:             * <ul>
1013:             * <li>if {@link #getSectionOutlinePaint()} is non-<code>null</code>, 
1014:             *         return it;</li>
1015:             * <li>otherwise, if {@link #getSectionOutlinePaint(int)} is 
1016:             *         non-<code>null</code> return it;</li>
1017:             * <li>if {@link #getSectionOutlinePaint(int)} is <code>null</code> but 
1018:             *         <code>autoPopulate</code> is <code>true</code>, attempt to fetch
1019:             *         a new outline paint from the drawing supplier 
1020:             *         ({@link #getDrawingSupplier()});
1021:             * <li>if all else fails, return {@link #getBaseSectionOutlinePaint()}.
1022:             * </ul> 
1023:             * 
1024:             * @param key  the section key.
1025:             * @param autoPopulate  a flag that controls whether the drawing supplier 
1026:             *     is used to auto-populate the section outline paint settings.
1027:             *     
1028:             * @return The paint.
1029:             * 
1030:             * @since 1.0.3
1031:             */
1032:            protected Paint lookupSectionOutlinePaint(Comparable key,
1033:                    boolean autoPopulate) {
1034:
1035:                // is there an override?
1036:                Paint result = getSectionOutlinePaint();
1037:                if (result != null) {
1038:                    return result;
1039:                }
1040:
1041:                // if not, check if there is a paint defined for the specified key
1042:                result = this .sectionOutlinePaintMap.getPaint(key);
1043:                if (result != null) {
1044:                    return result;
1045:                }
1046:
1047:                // nothing defined - do we autoPopulate?
1048:                if (autoPopulate) {
1049:                    DrawingSupplier ds = getDrawingSupplier();
1050:                    if (ds != null) {
1051:                        result = ds.getNextOutlinePaint();
1052:                        this .sectionOutlinePaintMap.put(key, result);
1053:                    } else {
1054:                        result = this .baseSectionOutlinePaint;
1055:                    }
1056:                } else {
1057:                    result = this .baseSectionOutlinePaint;
1058:                }
1059:                return result;
1060:            }
1061:
1062:            /**
1063:             * Returns the outline paint for ALL sections in the plot.
1064:             *
1065:             * @return The paint (possibly <code>null</code>).
1066:             * 
1067:             * @see #setSectionOutlinePaint(Paint)
1068:             * 
1069:             * @deprecated Use {@link #getSectionOutlinePaint(Comparable)} and 
1070:             *     {@link #getBaseSectionOutlinePaint()}.  Deprecated as of version 
1071:             *     1.0.6.
1072:             */
1073:            public Paint getSectionOutlinePaint() {
1074:                return this .sectionOutlinePaint;
1075:            }
1076:
1077:            /**
1078:             * Sets the outline paint for ALL sections in the plot.  If this is set to
1079:             * </code>null</code>, then a list of paints is used instead (to allow
1080:             * different colors to be used for each section).
1081:             *
1082:             * @param paint  the paint (<code>null</code> permitted).
1083:             * 
1084:             * @see #getSectionOutlinePaint()
1085:             * 
1086:             * @deprecated Use {@link #setSectionOutlinePaint(Comparable, Paint)} and 
1087:             *     {@link #setBaseSectionOutlinePaint(Paint)}.  Deprecated as of 
1088:             *     version 1.0.6.
1089:             */
1090:            public void setSectionOutlinePaint(Paint paint) {
1091:                this .sectionOutlinePaint = paint;
1092:                notifyListeners(new PlotChangeEvent(this ));
1093:            }
1094:
1095:            /**
1096:             * Returns the outline paint associated with the specified key, or 
1097:             * <code>null</code> if there is no paint associated with the key.
1098:             * 
1099:             * @param key  the key (<code>null</code> not permitted).
1100:             * 
1101:             * @return The paint associated with the specified key, or 
1102:             *     <code>null</code>.
1103:             *     
1104:             * @throws IllegalArgumentException if <code>key</code> is 
1105:             *     <code>null</code>.
1106:             * 
1107:             * @see #setSectionOutlinePaint(Comparable, Paint)
1108:             * 
1109:             * @since 1.0.3
1110:             */
1111:            public Paint getSectionOutlinePaint(Comparable key) {
1112:                // null argument check delegated...
1113:                return this .sectionOutlinePaintMap.getPaint(key);
1114:            }
1115:
1116:            /**
1117:             * Sets the outline paint associated with the specified key, and sends a 
1118:             * {@link PlotChangeEvent} to all registered listeners.
1119:             * 
1120:             * @param key  the key (<code>null</code> not permitted).
1121:             * @param paint  the paint.
1122:             * 
1123:             * @throws IllegalArgumentException if <code>key</code> is 
1124:             *     <code>null</code>.
1125:             *     
1126:             * @see #getSectionOutlinePaint(Comparable)
1127:             * 
1128:             * @since 1.0.3
1129:             */
1130:            public void setSectionOutlinePaint(Comparable key, Paint paint) {
1131:                // null argument check delegated...
1132:                this .sectionOutlinePaintMap.put(key, paint);
1133:                notifyListeners(new PlotChangeEvent(this ));
1134:            }
1135:
1136:            /**
1137:             * Returns the base section paint.  This is used when no other paint is 
1138:             * available.
1139:             * 
1140:             * @return The paint (never <code>null</code>).
1141:             * 
1142:             * @see #setBaseSectionOutlinePaint(Paint)
1143:             */
1144:            public Paint getBaseSectionOutlinePaint() {
1145:                return this .baseSectionOutlinePaint;
1146:            }
1147:
1148:            /**
1149:             * Sets the base section paint.
1150:             * 
1151:             * @param paint  the paint (<code>null</code> not permitted).
1152:             * 
1153:             * @see #getBaseSectionOutlinePaint()
1154:             */
1155:            public void setBaseSectionOutlinePaint(Paint paint) {
1156:                if (paint == null) {
1157:                    throw new IllegalArgumentException("Null 'paint' argument.");
1158:                }
1159:                this .baseSectionOutlinePaint = paint;
1160:                notifyListeners(new PlotChangeEvent(this ));
1161:            }
1162:
1163:            //// SECTION OUTLINE STROKE ///////////////////////////////////////////////
1164:
1165:            /**
1166:             * Returns the outline stroke for the specified section.  This is equivalent 
1167:             * to <code>lookupSectionOutlineStroke(section, false)</code>.
1168:             * 
1169:             * @param key  the section key.
1170:             * 
1171:             * @return The stroke for the specified section.
1172:             * 
1173:             * @since 1.0.3
1174:             * 
1175:             * @see #lookupSectionOutlineStroke(Comparable, boolean)
1176:             */
1177:            protected Stroke lookupSectionOutlineStroke(Comparable key) {
1178:                return lookupSectionOutlineStroke(key, false);
1179:            }
1180:
1181:            /**
1182:             * Returns the outline stroke for the specified section.  The lookup 
1183:             * involves these steps:
1184:             * <ul>
1185:             * <li>if {@link #getSectionOutlineStroke()} is non-<code>null</code>, 
1186:             *         return it;</li>
1187:             * <li>otherwise, if {@link #getSectionOutlineStroke(int)} is 
1188:             *         non-<code>null</code> return it;</li>
1189:             * <li>if {@link #getSectionOutlineStroke(int)} is <code>null</code> but 
1190:             *         <code>autoPopulate</code> is <code>true</code>, attempt to fetch
1191:             *         a new outline stroke from the drawing supplier 
1192:             *         ({@link #getDrawingSupplier()});
1193:             * <li>if all else fails, return {@link #getBaseSectionOutlineStroke()}.
1194:             * </ul> 
1195:             * 
1196:             * @param key  the section key.
1197:             * @param autoPopulate  a flag that controls whether the drawing supplier 
1198:             *     is used to auto-populate the section outline stroke settings.
1199:             *     
1200:             * @return The stroke.
1201:             * 
1202:             * @since 1.0.3
1203:             */
1204:            protected Stroke lookupSectionOutlineStroke(Comparable key,
1205:                    boolean autoPopulate) {
1206:
1207:                // is there an override?
1208:                Stroke result = getSectionOutlineStroke();
1209:                if (result != null) {
1210:                    return result;
1211:                }
1212:
1213:                // if not, check if there is a stroke defined for the specified key
1214:                result = this .sectionOutlineStrokeMap.getStroke(key);
1215:                if (result != null) {
1216:                    return result;
1217:                }
1218:
1219:                // nothing defined - do we autoPopulate?
1220:                if (autoPopulate) {
1221:                    DrawingSupplier ds = getDrawingSupplier();
1222:                    if (ds != null) {
1223:                        result = ds.getNextOutlineStroke();
1224:                        this .sectionOutlineStrokeMap.put(key, result);
1225:                    } else {
1226:                        result = this .baseSectionOutlineStroke;
1227:                    }
1228:                } else {
1229:                    result = this .baseSectionOutlineStroke;
1230:                }
1231:                return result;
1232:            }
1233:
1234:            /**
1235:             * Returns the outline stroke for ALL sections in the plot.
1236:             *
1237:             * @return The stroke (possibly <code>null</code>).
1238:             * 
1239:             * @see #setSectionOutlineStroke(Stroke)
1240:             * 
1241:             * @deprecated Use {@link #getSectionOutlineStroke(Comparable)} and 
1242:             *     {@link #getBaseSectionOutlineStroke()}.  Deprecated as of version 
1243:             *     1.0.6.
1244:             */
1245:            public Stroke getSectionOutlineStroke() {
1246:                return this .sectionOutlineStroke;
1247:            }
1248:
1249:            /**
1250:             * Sets the outline stroke for ALL sections in the plot.  If this is set to
1251:             * </code>null</code>, then a list of paints is used instead (to allow
1252:             * different colors to be used for each section).
1253:             *
1254:             * @param stroke  the stroke (<code>null</code> permitted).
1255:             * 
1256:             * @see #getSectionOutlineStroke()
1257:             * 
1258:             * @deprecated Use {@link #setSectionOutlineStroke(Comparable, Stroke)} and 
1259:             *     {@link #setBaseSectionOutlineStroke(Stroke)}.  Deprecated as of 
1260:             *     version 1.0.6.
1261:             */
1262:            public void setSectionOutlineStroke(Stroke stroke) {
1263:                this .sectionOutlineStroke = stroke;
1264:                notifyListeners(new PlotChangeEvent(this ));
1265:            }
1266:
1267:            /**
1268:             * Returns the outline stroke associated with the specified key, or 
1269:             * <code>null</code> if there is no stroke associated with the key.
1270:             * 
1271:             * @param key  the key (<code>null</code> not permitted).
1272:             * 
1273:             * @return The stroke associated with the specified key, or 
1274:             *     <code>null</code>.
1275:             *     
1276:             * @throws IllegalArgumentException if <code>key</code> is 
1277:             *     <code>null</code>.
1278:             * 
1279:             * @see #setSectionOutlineStroke(Comparable, Stroke)
1280:             * 
1281:             * @since 1.0.3
1282:             */
1283:            public Stroke getSectionOutlineStroke(Comparable key) {
1284:                // null argument check delegated...
1285:                return this .sectionOutlineStrokeMap.getStroke(key);
1286:            }
1287:
1288:            /**
1289:             * Sets the outline stroke associated with the specified key, and sends a 
1290:             * {@link PlotChangeEvent} to all registered listeners.
1291:             * 
1292:             * @param key  the key (<code>null</code> not permitted).
1293:             * @param stroke  the stroke.
1294:             * 
1295:             * @throws IllegalArgumentException if <code>key</code> is 
1296:             *     <code>null</code>.
1297:             *     
1298:             * @see #getSectionOutlineStroke(Comparable)
1299:             * 
1300:             * @since 1.0.3
1301:             */
1302:            public void setSectionOutlineStroke(Comparable key, Stroke stroke) {
1303:                // null argument check delegated...
1304:                this .sectionOutlineStrokeMap.put(key, stroke);
1305:                notifyListeners(new PlotChangeEvent(this ));
1306:            }
1307:
1308:            /**
1309:             * Returns the base section stroke.  This is used when no other stroke is 
1310:             * available.
1311:             * 
1312:             * @return The stroke (never <code>null</code>).
1313:             * 
1314:             * @see #setBaseSectionOutlineStroke(Stroke)
1315:             */
1316:            public Stroke getBaseSectionOutlineStroke() {
1317:                return this .baseSectionOutlineStroke;
1318:            }
1319:
1320:            /**
1321:             * Sets the base section stroke.
1322:             * 
1323:             * @param stroke  the stroke (<code>null</code> not permitted).
1324:             * 
1325:             * @see #getBaseSectionOutlineStroke()
1326:             */
1327:            public void setBaseSectionOutlineStroke(Stroke stroke) {
1328:                if (stroke == null) {
1329:                    throw new IllegalArgumentException(
1330:                            "Null 'stroke' argument.");
1331:                }
1332:                this .baseSectionOutlineStroke = stroke;
1333:                notifyListeners(new PlotChangeEvent(this ));
1334:            }
1335:
1336:            /**
1337:             * Returns the shadow paint.
1338:             * 
1339:             * @return The paint (possibly <code>null</code>).
1340:             * 
1341:             * @see #setShadowPaint(Paint)
1342:             */
1343:            public Paint getShadowPaint() {
1344:                return this .shadowPaint;
1345:            }
1346:
1347:            /**
1348:             * Sets the shadow paint and sends a {@link PlotChangeEvent} to all 
1349:             * registered listeners.
1350:             * 
1351:             * @param paint  the paint (<code>null</code> permitted).
1352:             * 
1353:             * @see #getShadowPaint()
1354:             */
1355:            public void setShadowPaint(Paint paint) {
1356:                this .shadowPaint = paint;
1357:                notifyListeners(new PlotChangeEvent(this ));
1358:            }
1359:
1360:            /**
1361:             * Returns the x-offset for the shadow effect.
1362:             * 
1363:             * @return The offset (in Java2D units).
1364:             * 
1365:             * @see #setShadowXOffset(double)
1366:             */
1367:            public double getShadowXOffset() {
1368:                return this .shadowXOffset;
1369:            }
1370:
1371:            /**
1372:             * Sets the x-offset for the shadow effect and sends a 
1373:             * {@link PlotChangeEvent} to all registered listeners.
1374:             * 
1375:             * @param offset  the offset (in Java2D units).
1376:             * 
1377:             * @see #getShadowXOffset()
1378:             */
1379:            public void setShadowXOffset(double offset) {
1380:                this .shadowXOffset = offset;
1381:                notifyListeners(new PlotChangeEvent(this ));
1382:            }
1383:
1384:            /**
1385:             * Returns the y-offset for the shadow effect.
1386:             * 
1387:             * @return The offset (in Java2D units).
1388:             * 
1389:             * @see #setShadowYOffset(double)
1390:             */
1391:            public double getShadowYOffset() {
1392:                return this .shadowYOffset;
1393:            }
1394:
1395:            /**
1396:             * Sets the y-offset for the shadow effect and sends a 
1397:             * {@link PlotChangeEvent} to all registered listeners.
1398:             * 
1399:             * @param offset  the offset (in Java2D units).
1400:             * 
1401:             * @see #getShadowYOffset()
1402:             */
1403:            public void setShadowYOffset(double offset) {
1404:                this .shadowYOffset = offset;
1405:                notifyListeners(new PlotChangeEvent(this ));
1406:            }
1407:
1408:            /**
1409:             * Returns the amount that the section with the specified key should be
1410:             * exploded.
1411:             * 
1412:             * @param key  the key (<code>null</code> not permitted).
1413:             * 
1414:             * @return The amount that the section with the specified key should be
1415:             *     exploded.
1416:             * 
1417:             * @throws IllegalArgumentException if <code>key</code> is 
1418:             *     <code>null</code>.
1419:             *
1420:             * @since 1.0.3
1421:             * 
1422:             * @see #setExplodePercent(Comparable, double)
1423:             */
1424:            public double getExplodePercent(Comparable key) {
1425:                double result = 0.0;
1426:                if (this .explodePercentages != null) {
1427:                    Number percent = (Number) this .explodePercentages.get(key);
1428:                    if (percent != null) {
1429:                        result = percent.doubleValue();
1430:                    }
1431:                }
1432:                return result;
1433:            }
1434:
1435:            /**
1436:             * Sets the amount that a pie section should be exploded and sends a 
1437:             * {@link PlotChangeEvent} to all registered listeners.
1438:             *
1439:             * @param key  the section key (<code>null</code> not permitted).
1440:             * @param percent  the explode percentage (0.30 = 30 percent).
1441:             * 
1442:             * @since 1.0.3
1443:             * 
1444:             * @see #getExplodePercent(Comparable)
1445:             */
1446:            public void setExplodePercent(Comparable key, double percent) {
1447:                if (key == null) {
1448:                    throw new IllegalArgumentException("Null 'key' argument.");
1449:                }
1450:                if (this .explodePercentages == null) {
1451:                    this .explodePercentages = new TreeMap();
1452:                }
1453:                this .explodePercentages.put(key, new Double(percent));
1454:                notifyListeners(new PlotChangeEvent(this ));
1455:            }
1456:
1457:            /**
1458:             * Returns the maximum explode percent.
1459:             * 
1460:             * @return The percent.
1461:             */
1462:            public double getMaximumExplodePercent() {
1463:                double result = 0.0;
1464:                Iterator iterator = this .dataset.getKeys().iterator();
1465:                while (iterator.hasNext()) {
1466:                    Comparable key = (Comparable) iterator.next();
1467:                    Number explode = (Number) this .explodePercentages.get(key);
1468:                    if (explode != null) {
1469:                        result = Math.max(result, explode.doubleValue());
1470:                    }
1471:                }
1472:                return result;
1473:            }
1474:
1475:            /**
1476:             * Returns the section label generator. 
1477:             * 
1478:             * @return The generator (possibly <code>null</code>).
1479:             * 
1480:             * @see #setLabelGenerator(PieSectionLabelGenerator)
1481:             */
1482:            public PieSectionLabelGenerator getLabelGenerator() {
1483:                return this .labelGenerator;
1484:            }
1485:
1486:            /**
1487:             * Sets the section label generator and sends a {@link PlotChangeEvent} to
1488:             * all registered listeners.
1489:             * 
1490:             * @param generator  the generator (<code>null</code> permitted).
1491:             * 
1492:             * @see #getLabelGenerator()
1493:             */
1494:            public void setLabelGenerator(PieSectionLabelGenerator generator) {
1495:                this .labelGenerator = generator;
1496:                notifyListeners(new PlotChangeEvent(this ));
1497:            }
1498:
1499:            /**
1500:             * Returns the gap between the edge of the pie and the labels, expressed as 
1501:             * a percentage of the plot width.
1502:             * 
1503:             * @return The gap (a percentage, where 0.05 = five percent).
1504:             * 
1505:             * @see #setLabelGap(double)
1506:             */
1507:            public double getLabelGap() {
1508:                return this .labelGap;
1509:            }
1510:
1511:            /**
1512:             * Sets the gap between the edge of the pie and the labels (expressed as a 
1513:             * percentage of the plot width) and sends a {@link PlotChangeEvent} to all
1514:             * registered listeners.
1515:             * 
1516:             * @param gap  the gap (a percentage, where 0.05 = five percent).
1517:             * 
1518:             * @see #getLabelGap()
1519:             */
1520:            public void setLabelGap(double gap) {
1521:                this .labelGap = gap;
1522:                notifyListeners(new PlotChangeEvent(this ));
1523:            }
1524:
1525:            /**
1526:             * Returns the maximum label width as a percentage of the plot width.
1527:             * 
1528:             * @return The width (a percentage, where 0.20 = 20 percent).
1529:             * 
1530:             * @see #setMaximumLabelWidth(double)
1531:             */
1532:            public double getMaximumLabelWidth() {
1533:                return this .maximumLabelWidth;
1534:            }
1535:
1536:            /**
1537:             * Sets the maximum label width as a percentage of the plot width and sends
1538:             * a {@link PlotChangeEvent} to all registered listeners.
1539:             * 
1540:             * @param width  the width (a percentage, where 0.20 = 20 percent).
1541:             * 
1542:             * @see #getMaximumLabelWidth()
1543:             */
1544:            public void setMaximumLabelWidth(double width) {
1545:                this .maximumLabelWidth = width;
1546:                notifyListeners(new PlotChangeEvent(this ));
1547:            }
1548:
1549:            /**
1550:             * Returns the flag that controls whether or not label linking lines are
1551:             * visible.
1552:             * 
1553:             * @return A boolean.
1554:             * 
1555:             * @see #setLabelLinksVisible(boolean)
1556:             */
1557:            public boolean getLabelLinksVisible() {
1558:                return this .labelLinksVisible;
1559:            }
1560:
1561:            /**
1562:             * Sets the flag that controls whether or not label linking lines are 
1563:             * visible and sends a {@link PlotChangeEvent} to all registered listeners.
1564:             * Please take care when hiding the linking lines - depending on the data 
1565:             * values, the labels can be displayed some distance away from the
1566:             * corresponding pie section.
1567:             * 
1568:             * @param visible  the flag.
1569:             * 
1570:             * @see #getLabelLinksVisible()
1571:             */
1572:            public void setLabelLinksVisible(boolean visible) {
1573:                this .labelLinksVisible = visible;
1574:                notifyListeners(new PlotChangeEvent(this ));
1575:            }
1576:
1577:            /**
1578:             * Returns the margin (expressed as a percentage of the width or height) 
1579:             * between the edge of the pie and the link point.
1580:             * 
1581:             * @return The link margin (as a percentage, where 0.05 is five percent).
1582:             * 
1583:             * @see #setLabelLinkMargin(double)
1584:             */
1585:            public double getLabelLinkMargin() {
1586:                return this .labelLinkMargin;
1587:            }
1588:
1589:            /**
1590:             * Sets the link margin and sends a {@link PlotChangeEvent} to all 
1591:             * registered listeners.
1592:             * 
1593:             * @param margin  the margin.
1594:             * 
1595:             * @see #getLabelLinkMargin()
1596:             */
1597:            public void setLabelLinkMargin(double margin) {
1598:                this .labelLinkMargin = margin;
1599:                notifyListeners(new PlotChangeEvent(this ));
1600:            }
1601:
1602:            /**
1603:             * Returns the paint used for the lines that connect pie sections to their 
1604:             * corresponding labels.
1605:             * 
1606:             * @return The paint (never <code>null</code>).
1607:             * 
1608:             * @see #setLabelLinkPaint(Paint)
1609:             */
1610:            public Paint getLabelLinkPaint() {
1611:                return this .labelLinkPaint;
1612:            }
1613:
1614:            /**
1615:             * Sets the paint used for the lines that connect pie sections to their 
1616:             * corresponding labels, and sends a {@link PlotChangeEvent} to all 
1617:             * registered listeners.
1618:             * 
1619:             * @param paint  the paint (<code>null</code> not permitted).
1620:             * 
1621:             * @see #getLabelLinkPaint()
1622:             */
1623:            public void setLabelLinkPaint(Paint paint) {
1624:                if (paint == null) {
1625:                    throw new IllegalArgumentException("Null 'paint' argument.");
1626:                }
1627:                this .labelLinkPaint = paint;
1628:                notifyListeners(new PlotChangeEvent(this ));
1629:            }
1630:
1631:            /**
1632:             * Returns the stroke used for the label linking lines.
1633:             * 
1634:             * @return The stroke.
1635:             * 
1636:             * @see #setLabelLinkStroke(Stroke)
1637:             */
1638:            public Stroke getLabelLinkStroke() {
1639:                return this .labelLinkStroke;
1640:            }
1641:
1642:            /**
1643:             * Sets the link stroke and sends a {@link PlotChangeEvent} to all 
1644:             * registered listeners.
1645:             * 
1646:             * @param stroke  the stroke.
1647:             * 
1648:             * @see #getLabelLinkStroke()
1649:             */
1650:            public void setLabelLinkStroke(Stroke stroke) {
1651:                if (stroke == null) {
1652:                    throw new IllegalArgumentException(
1653:                            "Null 'stroke' argument.");
1654:                }
1655:                this .labelLinkStroke = stroke;
1656:                notifyListeners(new PlotChangeEvent(this ));
1657:            }
1658:
1659:            /**
1660:             * Returns the section label font.
1661:             *
1662:             * @return The font (never <code>null</code>).
1663:             * 
1664:             * @see #setLabelFont(Font)
1665:             */
1666:            public Font getLabelFont() {
1667:                return this .labelFont;
1668:            }
1669:
1670:            /**
1671:             * Sets the section label font and sends a {@link PlotChangeEvent} to all 
1672:             * registered listeners.
1673:             *
1674:             * @param font  the font (<code>null</code> not permitted).
1675:             * 
1676:             * @see #getLabelFont()
1677:             */
1678:            public void setLabelFont(Font font) {
1679:                if (font == null) {
1680:                    throw new IllegalArgumentException("Null 'font' argument.");
1681:                }
1682:                this .labelFont = font;
1683:                notifyListeners(new PlotChangeEvent(this ));
1684:            }
1685:
1686:            /**
1687:             * Returns the section label paint.
1688:             *
1689:             * @return The paint (never <code>null</code>).
1690:             * 
1691:             * @see #setLabelPaint(Paint)
1692:             */
1693:            public Paint getLabelPaint() {
1694:                return this .labelPaint;
1695:            }
1696:
1697:            /**
1698:             * Sets the section label paint and sends a {@link PlotChangeEvent} to all 
1699:             * registered listeners.
1700:             *
1701:             * @param paint  the paint (<code>null</code> not permitted).
1702:             * 
1703:             * @see #getLabelPaint()
1704:             */
1705:            public void setLabelPaint(Paint paint) {
1706:                if (paint == null) {
1707:                    throw new IllegalArgumentException("Null 'paint' argument.");
1708:                }
1709:                this .labelPaint = paint;
1710:                notifyListeners(new PlotChangeEvent(this ));
1711:            }
1712:
1713:            /**
1714:             * Returns the section label background paint.
1715:             *
1716:             * @return The paint (possibly <code>null</code>).
1717:             * 
1718:             * @see #setLabelBackgroundPaint(Paint)
1719:             */
1720:            public Paint getLabelBackgroundPaint() {
1721:                return this .labelBackgroundPaint;
1722:            }
1723:
1724:            /**
1725:             * Sets the section label background paint and sends a 
1726:             * {@link PlotChangeEvent} to all registered listeners.
1727:             *
1728:             * @param paint  the paint (<code>null</code> permitted).
1729:             * 
1730:             * @see #getLabelBackgroundPaint()
1731:             */
1732:            public void setLabelBackgroundPaint(Paint paint) {
1733:                this .labelBackgroundPaint = paint;
1734:                notifyListeners(new PlotChangeEvent(this ));
1735:            }
1736:
1737:            /**
1738:             * Returns the section label outline paint.
1739:             *
1740:             * @return The paint (possibly <code>null</code>).
1741:             * 
1742:             * @see #setLabelOutlinePaint(Paint)
1743:             */
1744:            public Paint getLabelOutlinePaint() {
1745:                return this .labelOutlinePaint;
1746:            }
1747:
1748:            /**
1749:             * Sets the section label outline paint and sends a 
1750:             * {@link PlotChangeEvent} to all registered listeners.
1751:             *
1752:             * @param paint  the paint (<code>null</code> permitted).
1753:             * 
1754:             * @see #getLabelOutlinePaint()
1755:             */
1756:            public void setLabelOutlinePaint(Paint paint) {
1757:                this .labelOutlinePaint = paint;
1758:                notifyListeners(new PlotChangeEvent(this ));
1759:            }
1760:
1761:            /**
1762:             * Returns the section label outline stroke.
1763:             *
1764:             * @return The stroke (possibly <code>null</code>).
1765:             * 
1766:             * @see #setLabelOutlineStroke(Stroke)
1767:             */
1768:            public Stroke getLabelOutlineStroke() {
1769:                return this .labelOutlineStroke;
1770:            }
1771:
1772:            /**
1773:             * Sets the section label outline stroke and sends a 
1774:             * {@link PlotChangeEvent} to all registered listeners.
1775:             *
1776:             * @param stroke  the stroke (<code>null</code> permitted).
1777:             * 
1778:             * @see #getLabelOutlineStroke()
1779:             */
1780:            public void setLabelOutlineStroke(Stroke stroke) {
1781:                this .labelOutlineStroke = stroke;
1782:                notifyListeners(new PlotChangeEvent(this ));
1783:            }
1784:
1785:            /**
1786:             * Returns the section label shadow paint.
1787:             *
1788:             * @return The paint (possibly <code>null</code>).
1789:             * 
1790:             * @see #setLabelShadowPaint(Paint)
1791:             */
1792:            public Paint getLabelShadowPaint() {
1793:                return this .labelShadowPaint;
1794:            }
1795:
1796:            /**
1797:             * Sets the section label shadow paint and sends a {@link PlotChangeEvent}
1798:             * to all registered listeners.
1799:             *
1800:             * @param paint  the paint (<code>null</code> permitted).
1801:             * 
1802:             * @see #getLabelShadowPaint()
1803:             */
1804:            public void setLabelShadowPaint(Paint paint) {
1805:                this .labelShadowPaint = paint;
1806:                notifyListeners(new PlotChangeEvent(this ));
1807:            }
1808:
1809:            /**
1810:             * Returns the object responsible for the vertical layout of the pie 
1811:             * section labels.
1812:             * 
1813:             * @return The label distributor (never <code>null</code>).
1814:             * 
1815:             * @since 1.0.6
1816:             */
1817:            public AbstractPieLabelDistributor getLabelDistributor() {
1818:                return this .labelDistributor;
1819:            }
1820:
1821:            /**
1822:             * Sets the label distributor and sends a {@link PlotChangeEvent} to all 
1823:             * registered listeners.
1824:             * 
1825:             * @param distributor  the distributor (<code>null</code> not permitted).
1826:             *
1827:             * @since 1.0.6
1828:             */
1829:            public void setLabelDistributor(
1830:                    AbstractPieLabelDistributor distributor) {
1831:                if (distributor == null) {
1832:                    throw new IllegalArgumentException(
1833:                            "Null 'distributor' argument.");
1834:                }
1835:                this .labelDistributor = distributor;
1836:                notifyListeners(new PlotChangeEvent(this ));
1837:            }
1838:
1839:            /**
1840:             * Returns the tool tip generator, an object that is responsible for 
1841:             * generating the text items used for tool tips by the plot.  If the 
1842:             * generator is <code>null</code>, no tool tips will be created.
1843:             *
1844:             * @return The generator (possibly <code>null</code>).
1845:             * 
1846:             * @see #setToolTipGenerator(PieToolTipGenerator)
1847:             */
1848:            public PieToolTipGenerator getToolTipGenerator() {
1849:                return this .toolTipGenerator;
1850:            }
1851:
1852:            /**
1853:             * Sets the tool tip generator and sends a {@link PlotChangeEvent} to all 
1854:             * registered listeners.  Set the generator to <code>null</code> if you 
1855:             * don't want any tool tips.
1856:             *
1857:             * @param generator  the generator (<code>null</code> permitted).
1858:             * 
1859:             * @see #getToolTipGenerator()
1860:             */
1861:            public void setToolTipGenerator(PieToolTipGenerator generator) {
1862:                this .toolTipGenerator = generator;
1863:                notifyListeners(new PlotChangeEvent(this ));
1864:            }
1865:
1866:            /**
1867:             * Returns the URL generator.
1868:             *
1869:             * @return The generator (possibly <code>null</code>).
1870:             * 
1871:             * @see #setURLGenerator(PieURLGenerator)
1872:             */
1873:            public PieURLGenerator getURLGenerator() {
1874:                return this .urlGenerator;
1875:            }
1876:
1877:            /**
1878:             * Sets the URL generator and sends a {@link PlotChangeEvent} to all 
1879:             * registered listeners.
1880:             *
1881:             * @param generator  the generator (<code>null</code> permitted).
1882:             * 
1883:             * @see #getURLGenerator()
1884:             */
1885:            public void setURLGenerator(PieURLGenerator generator) {
1886:                this .urlGenerator = generator;
1887:                notifyListeners(new PlotChangeEvent(this ));
1888:            }
1889:
1890:            /**
1891:             * Returns the minimum arc angle that will be drawn.  Pie sections for an 
1892:             * angle smaller than this are not drawn, to avoid a JDK bug.
1893:             *
1894:             * @return The minimum angle.
1895:             * 
1896:             * @see #setMinimumArcAngleToDraw(double)
1897:             */
1898:            public double getMinimumArcAngleToDraw() {
1899:                return this .minimumArcAngleToDraw;
1900:            }
1901:
1902:            /**
1903:             * Sets the minimum arc angle that will be drawn.  Pie sections for an 
1904:             * angle smaller than this are not drawn, to avoid a JDK bug.  See this 
1905:             * link for details:
1906:             * <br><br>
1907:             * <a href="http://www.jfree.org/phpBB2/viewtopic.php?t=2707">
1908:             * http://www.jfree.org/phpBB2/viewtopic.php?t=2707</a>
1909:             * <br><br>
1910:             * ...and this bug report in the Java Bug Parade:
1911:             * <br><br>
1912:             * <a href=
1913:             * "http://developer.java.sun.com/developer/bugParade/bugs/4836495.html">
1914:             * http://developer.java.sun.com/developer/bugParade/bugs/4836495.html</a>
1915:             *
1916:             * @param angle  the minimum angle.
1917:             * 
1918:             * @see #getMinimumArcAngleToDraw()
1919:             */
1920:            public void setMinimumArcAngleToDraw(double angle) {
1921:                this .minimumArcAngleToDraw = angle;
1922:            }
1923:
1924:            /**
1925:             * Returns the shape used for legend items.
1926:             * 
1927:             * @return The shape (never <code>null</code>).
1928:             * 
1929:             * @see #setLegendItemShape(Shape)
1930:             */
1931:            public Shape getLegendItemShape() {
1932:                return this .legendItemShape;
1933:            }
1934:
1935:            /**
1936:             * Sets the shape used for legend items and sends a {@link PlotChangeEvent}
1937:             * to all registered listeners.
1938:             * 
1939:             * @param shape  the shape (<code>null</code> not permitted).
1940:             * 
1941:             * @see #getLegendItemShape()
1942:             */
1943:            public void setLegendItemShape(Shape shape) {
1944:                if (shape == null) {
1945:                    throw new IllegalArgumentException("Null 'shape' argument.");
1946:                }
1947:                this .legendItemShape = shape;
1948:                notifyListeners(new PlotChangeEvent(this ));
1949:            }
1950:
1951:            /**
1952:             * Returns the legend label generator.
1953:             * 
1954:             * @return The legend label generator (never <code>null</code>).
1955:             * 
1956:             * @see #setLegendLabelGenerator(PieSectionLabelGenerator)
1957:             */
1958:            public PieSectionLabelGenerator getLegendLabelGenerator() {
1959:                return this .legendLabelGenerator;
1960:            }
1961:
1962:            /**
1963:             * Sets the legend label generator and sends a {@link PlotChangeEvent} to 
1964:             * all registered listeners.
1965:             * 
1966:             * @param generator  the generator (<code>null</code> not permitted).
1967:             * 
1968:             * @see #getLegendLabelGenerator()
1969:             */
1970:            public void setLegendLabelGenerator(
1971:                    PieSectionLabelGenerator generator) {
1972:                if (generator == null) {
1973:                    throw new IllegalArgumentException(
1974:                            "Null 'generator' argument.");
1975:                }
1976:                this .legendLabelGenerator = generator;
1977:                notifyListeners(new PlotChangeEvent(this ));
1978:            }
1979:
1980:            /**
1981:             * Returns the legend label tool tip generator.
1982:             * 
1983:             * @return The legend label tool tip generator (possibly <code>null</code>).
1984:             * 
1985:             * @see #setLegendLabelToolTipGenerator(PieSectionLabelGenerator)
1986:             */
1987:            public PieSectionLabelGenerator getLegendLabelToolTipGenerator() {
1988:                return this .legendLabelToolTipGenerator;
1989:            }
1990:
1991:            /**
1992:             * Sets the legend label tool tip generator and sends a 
1993:             * {@link PlotChangeEvent} to all registered listeners.
1994:             * 
1995:             * @param generator  the generator (<code>null</code> permitted).
1996:             * 
1997:             * @see #getLegendLabelToolTipGenerator()
1998:             */
1999:            public void setLegendLabelToolTipGenerator(
2000:                    PieSectionLabelGenerator generator) {
2001:                this .legendLabelToolTipGenerator = generator;
2002:                notifyListeners(new PlotChangeEvent(this ));
2003:            }
2004:
2005:            /**
2006:             * Returns the legend label URL generator.
2007:             * 
2008:             * @return The legend label URL generator (possibly <code>null</code>).
2009:             * 
2010:             * @see #setLegendLabelURLGenerator(PieURLGenerator)
2011:             * 
2012:             * @since 1.0.4
2013:             */
2014:            public PieURLGenerator getLegendLabelURLGenerator() {
2015:                return this .legendLabelURLGenerator;
2016:            }
2017:
2018:            /**
2019:             * Sets the legend label URL generator and sends a 
2020:             * {@link PlotChangeEvent} to all registered listeners.
2021:             * 
2022:             * @param generator  the generator (<code>null</code> permitted).
2023:             * 
2024:             * @see #getLegendLabelURLGenerator()
2025:             * 
2026:             * @since 1.0.4
2027:             */
2028:            public void setLegendLabelURLGenerator(PieURLGenerator generator) {
2029:                this .legendLabelURLGenerator = generator;
2030:                notifyListeners(new PlotChangeEvent(this ));
2031:            }
2032:
2033:            /**
2034:             * Initialises the drawing procedure.  This method will be called before 
2035:             * the first item is rendered, giving the plot an opportunity to initialise
2036:             * any state information it wants to maintain.
2037:             *
2038:             * @param g2  the graphics device.
2039:             * @param plotArea  the plot area (<code>null</code> not permitted).
2040:             * @param plot  the plot.
2041:             * @param index  the secondary index (<code>null</code> for primary 
2042:             *               renderer).
2043:             * @param info  collects chart rendering information for return to caller.
2044:             * 
2045:             * @return A state object (maintains state information relevant to one 
2046:             *         chart drawing).
2047:             */
2048:            public PiePlotState initialise(Graphics2D g2, Rectangle2D plotArea,
2049:                    PiePlot plot, Integer index, PlotRenderingInfo info) {
2050:
2051:                PiePlotState state = new PiePlotState(info);
2052:                state.setPassesRequired(2);
2053:                state.setTotal(DatasetUtilities.calculatePieDatasetTotal(plot
2054:                        .getDataset()));
2055:                state.setLatestAngle(plot.getStartAngle());
2056:                return state;
2057:
2058:            }
2059:
2060:            /**
2061:             * Draws the plot on a Java 2D graphics device (such as the screen or a 
2062:             * printer).
2063:             *
2064:             * @param g2  the graphics device.
2065:             * @param area  the area within which the plot should be drawn.
2066:             * @param anchor  the anchor point (<code>null</code> permitted).
2067:             * @param parentState  the state from the parent plot, if there is one.
2068:             * @param info  collects info about the drawing 
2069:             *              (<code>null</code> permitted).
2070:             */
2071:            public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
2072:                    PlotState parentState, PlotRenderingInfo info) {
2073:
2074:                // adjust for insets...
2075:                RectangleInsets insets = getInsets();
2076:                insets.trim(area);
2077:
2078:                if (info != null) {
2079:                    info.setPlotArea(area);
2080:                    info.setDataArea(area);
2081:                }
2082:
2083:                drawBackground(g2, area);
2084:                drawOutline(g2, area);
2085:
2086:                Shape savedClip = g2.getClip();
2087:                g2.clip(area);
2088:
2089:                Composite originalComposite = g2.getComposite();
2090:                g2.setComposite(AlphaComposite.getInstance(
2091:                        AlphaComposite.SRC_OVER, getForegroundAlpha()));
2092:
2093:                if (!DatasetUtilities.isEmptyOrNull(this .dataset)) {
2094:                    drawPie(g2, area, info);
2095:                } else {
2096:                    drawNoDataMessage(g2, area);
2097:                }
2098:
2099:                g2.setClip(savedClip);
2100:                g2.setComposite(originalComposite);
2101:
2102:                drawOutline(g2, area);
2103:
2104:            }
2105:
2106:            /**
2107:             * Draws the pie.
2108:             *
2109:             * @param g2  the graphics device.
2110:             * @param plotArea  the plot area.
2111:             * @param info  chart rendering info.
2112:             */
2113:            protected void drawPie(Graphics2D g2, Rectangle2D plotArea,
2114:                    PlotRenderingInfo info) {
2115:
2116:                PiePlotState state = initialise(g2, plotArea, this , null, info);
2117:
2118:                // adjust the plot area for interior spacing and labels...
2119:                double labelWidth = 0.0;
2120:                if (this .labelGenerator != null) {
2121:                    labelWidth = this .labelGap + this .maximumLabelWidth
2122:                            + this .labelLinkMargin;
2123:                }
2124:                double gapHorizontal = plotArea.getWidth()
2125:                        * (this .interiorGap + labelWidth);
2126:                double gapVertical = plotArea.getHeight() * this .interiorGap;
2127:
2128:                double linkX = plotArea.getX() + gapHorizontal / 2;
2129:                double linkY = plotArea.getY() + gapVertical / 2;
2130:                double linkW = plotArea.getWidth() - gapHorizontal;
2131:                double linkH = plotArea.getHeight() - gapVertical;
2132:
2133:                // make the link area a square if the pie chart is to be circular...
2134:                if (this .circular) {
2135:                    double min = Math.min(linkW, linkH) / 2;
2136:                    linkX = (linkX + linkX + linkW) / 2 - min;
2137:                    linkY = (linkY + linkY + linkH) / 2 - min;
2138:                    linkW = 2 * min;
2139:                    linkH = 2 * min;
2140:                }
2141:
2142:                // the link area defines the dog leg points for the linking lines to 
2143:                // the labels
2144:                Rectangle2D linkArea = new Rectangle2D.Double(linkX, linkY,
2145:                        linkW, linkH);
2146:                state.setLinkArea(linkArea);
2147:
2148:                // the explode area defines the max circle/ellipse for the exploded 
2149:                // pie sections.  it is defined by shrinking the linkArea by the 
2150:                // linkMargin factor.
2151:                double hh = linkArea.getWidth() * this .labelLinkMargin;
2152:                double vv = linkArea.getHeight() * this .labelLinkMargin;
2153:                Rectangle2D explodeArea = new Rectangle2D.Double(linkX + hh
2154:                        / 2.0, linkY + vv / 2.0, linkW - hh, linkH - vv);
2155:
2156:                state.setExplodedPieArea(explodeArea);
2157:
2158:                // the pie area defines the circle/ellipse for regular pie sections.
2159:                // it is defined by shrinking the explodeArea by the explodeMargin 
2160:                // factor. 
2161:                double maximumExplodePercent = getMaximumExplodePercent();
2162:                double percent = maximumExplodePercent
2163:                        / (1.0 + maximumExplodePercent);
2164:
2165:                double h1 = explodeArea.getWidth() * percent;
2166:                double v1 = explodeArea.getHeight() * percent;
2167:                Rectangle2D pieArea = new Rectangle2D.Double(explodeArea.getX()
2168:                        + h1 / 2.0, explodeArea.getY() + v1 / 2.0, explodeArea
2169:                        .getWidth()
2170:                        - h1, explodeArea.getHeight() - v1);
2171:
2172:                state.setPieArea(pieArea);
2173:                state.setPieCenterX(pieArea.getCenterX());
2174:                state.setPieCenterY(pieArea.getCenterY());
2175:                state.setPieWRadius(pieArea.getWidth() / 2.0);
2176:                state.setPieHRadius(pieArea.getHeight() / 2.0);
2177:                // plot the data (unless the dataset is null)...
2178:                if ((this .dataset != null)
2179:                        && (this .dataset.getKeys().size() > 0)) {
2180:
2181:                    List keys = this .dataset.getKeys();
2182:                    double totalValue = DatasetUtilities
2183:                            .calculatePieDatasetTotal(this .dataset);
2184:
2185:                    int passesRequired = state.getPassesRequired();
2186:                    for (int pass = 0; pass < passesRequired; pass++) {
2187:                        double runningTotal = 0.0;
2188:                        for (int section = 0; section < keys.size(); section++) {
2189:                            Number n = this .dataset.getValue(section);
2190:                            if (n != null) {
2191:                                double value = n.doubleValue();
2192:                                if (value > 0.0) {
2193:                                    runningTotal += value;
2194:                                    drawItem(g2, section, explodeArea, state,
2195:                                            pass);
2196:                                }
2197:                            }
2198:                        }
2199:                    }
2200:
2201:                    drawLabels(g2, keys, totalValue, plotArea, linkArea, state);
2202:
2203:                } else {
2204:                    drawNoDataMessage(g2, plotArea);
2205:                }
2206:            }
2207:
2208:            /**
2209:             * Draws a single data item.
2210:             *
2211:             * @param g2  the graphics device (<code>null</code> not permitted).
2212:             * @param section  the section index.
2213:             * @param dataArea  the data plot area.
2214:             * @param state  state information for one chart.
2215:             * @param currentPass  the current pass index.
2216:             */
2217:            protected void drawItem(Graphics2D g2, int section,
2218:                    Rectangle2D dataArea, PiePlotState state, int currentPass) {
2219:
2220:                Number n = this .dataset.getValue(section);
2221:                if (n == null) {
2222:                    return;
2223:                }
2224:                double value = n.doubleValue();
2225:                double angle1 = 0.0;
2226:                double angle2 = 0.0;
2227:
2228:                if (this .direction == Rotation.CLOCKWISE) {
2229:                    angle1 = state.getLatestAngle();
2230:                    angle2 = angle1 - value / state.getTotal() * 360.0;
2231:                } else if (this .direction == Rotation.ANTICLOCKWISE) {
2232:                    angle1 = state.getLatestAngle();
2233:                    angle2 = angle1 + value / state.getTotal() * 360.0;
2234:                } else {
2235:                    throw new IllegalStateException(
2236:                            "Rotation type not recognised.");
2237:                }
2238:
2239:                double angle = (angle2 - angle1);
2240:                if (Math.abs(angle) > getMinimumArcAngleToDraw()) {
2241:                    double ep = 0.0;
2242:                    double mep = getMaximumExplodePercent();
2243:                    if (mep > 0.0) {
2244:                        ep = getExplodePercent(section) / mep;
2245:                    }
2246:                    Rectangle2D arcBounds = getArcBounds(state.getPieArea(),
2247:                            state.getExplodedPieArea(), angle1, angle, ep);
2248:                    Arc2D.Double arc = new Arc2D.Double(arcBounds, angle1,
2249:                            angle, Arc2D.PIE);
2250:
2251:                    if (currentPass == 0) {
2252:                        if (this .shadowPaint != null) {
2253:                            Shape shadowArc = ShapeUtilities
2254:                                    .createTranslatedShape(arc,
2255:                                            (float) this .shadowXOffset,
2256:                                            (float) this .shadowYOffset);
2257:                            g2.setPaint(this .shadowPaint);
2258:                            g2.fill(shadowArc);
2259:                        }
2260:                    } else if (currentPass == 1) {
2261:                        Comparable key = getSectionKey(section);
2262:                        Paint paint = lookupSectionPaint(key, true);
2263:                        g2.setPaint(paint);
2264:                        g2.fill(arc);
2265:
2266:                        Paint outlinePaint = lookupSectionOutlinePaint(key);
2267:                        Stroke outlineStroke = lookupSectionOutlineStroke(key);
2268:                        if (this .sectionOutlinesVisible) {
2269:                            g2.setPaint(outlinePaint);
2270:                            g2.setStroke(outlineStroke);
2271:                            g2.draw(arc);
2272:                        }
2273:
2274:                        // update the linking line target for later
2275:                        // add an entity for the pie section
2276:                        if (state.getInfo() != null) {
2277:                            EntityCollection entities = state
2278:                                    .getEntityCollection();
2279:                            if (entities != null) {
2280:                                String tip = null;
2281:                                if (this .toolTipGenerator != null) {
2282:                                    tip = this .toolTipGenerator
2283:                                            .generateToolTip(this .dataset, key);
2284:                                }
2285:                                String url = null;
2286:                                if (this .urlGenerator != null) {
2287:                                    url = this .urlGenerator.generateURL(
2288:                                            this .dataset, key, this .pieIndex);
2289:                                }
2290:                                PieSectionEntity entity = new PieSectionEntity(
2291:                                        arc, this .dataset, this .pieIndex,
2292:                                        section, key, tip, url);
2293:                                entities.add(entity);
2294:                            }
2295:                        }
2296:                    }
2297:                }
2298:                state.setLatestAngle(angle2);
2299:            }
2300:
2301:            /**
2302:             * Draws the labels for the pie sections.
2303:             * 
2304:             * @param g2  the graphics device.
2305:             * @param keys  the keys.
2306:             * @param totalValue  the total value.
2307:             * @param plotArea  the plot area.
2308:             * @param linkArea  the link area.
2309:             * @param state  the state.
2310:             */
2311:            protected void drawLabels(Graphics2D g2, List keys,
2312:                    double totalValue, Rectangle2D plotArea,
2313:                    Rectangle2D linkArea, PiePlotState state) {
2314:
2315:                Composite originalComposite = g2.getComposite();
2316:                g2.setComposite(AlphaComposite.getInstance(
2317:                        AlphaComposite.SRC_OVER, 1.0f));
2318:
2319:                // classify the keys according to which side the label will appear...
2320:                DefaultKeyedValues leftKeys = new DefaultKeyedValues();
2321:                DefaultKeyedValues rightKeys = new DefaultKeyedValues();
2322:
2323:                double runningTotal1 = 0.0;
2324:                Iterator iterator1 = keys.iterator();
2325:                while (iterator1.hasNext()) {
2326:                    Comparable key = (Comparable) iterator1.next();
2327:                    boolean include = true;
2328:                    double v = 0.0;
2329:                    Number n = this .dataset.getValue(key);
2330:                    if (n == null) {
2331:                        include = !this .ignoreNullValues;
2332:                    } else {
2333:                        v = n.doubleValue();
2334:                        include = this .ignoreZeroValues ? v > 0.0 : v >= 0.0;
2335:                    }
2336:
2337:                    if (include) {
2338:                        runningTotal1 = runningTotal1 + v;
2339:                        // work out the mid angle (0 - 90 and 270 - 360) = right, 
2340:                        // otherwise left
2341:                        double mid = this .startAngle
2342:                                + (this .direction.getFactor()
2343:                                        * ((runningTotal1 - v / 2.0) * 360) / totalValue);
2344:                        if (Math.cos(Math.toRadians(mid)) < 0.0) {
2345:                            leftKeys.addValue(key, new Double(mid));
2346:                        } else {
2347:                            rightKeys.addValue(key, new Double(mid));
2348:                        }
2349:                    }
2350:                }
2351:
2352:                g2.setFont(getLabelFont());
2353:                float maxLabelWidth = (float) (getMaximumLabelWidth() * plotArea
2354:                        .getWidth());
2355:
2356:                // draw the labels...
2357:                if (this .labelGenerator != null) {
2358:                    drawLeftLabels(leftKeys, g2, plotArea, linkArea,
2359:                            maxLabelWidth, state);
2360:                    drawRightLabels(rightKeys, g2, plotArea, linkArea,
2361:                            maxLabelWidth, state);
2362:                }
2363:                g2.setComposite(originalComposite);
2364:
2365:            }
2366:
2367:            /**
2368:             * Draws the left labels.
2369:             * 
2370:             * @param leftKeys  a collection of keys and angles (to the middle of the
2371:             *         section, in degrees) for the sections on the left side of the 
2372:             *         plot.
2373:             * @param g2  the graphics device.
2374:             * @param plotArea  the plot area.
2375:             * @param linkArea  the link area.
2376:             * @param maxLabelWidth  the maximum label width.
2377:             * @param state  the state.
2378:             */
2379:            protected void drawLeftLabels(KeyedValues leftKeys, Graphics2D g2,
2380:                    Rectangle2D plotArea, Rectangle2D linkArea,
2381:                    float maxLabelWidth, PiePlotState state) {
2382:
2383:                this .labelDistributor.clear();
2384:                double lGap = plotArea.getWidth() * this .labelGap;
2385:                double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0;
2386:                for (int i = 0; i < leftKeys.getItemCount(); i++) {
2387:                    String label = this .labelGenerator.generateSectionLabel(
2388:                            this .dataset, leftKeys.getKey(i));
2389:                    if (label != null) {
2390:                        TextBlock block = TextUtilities.createTextBlock(label,
2391:                                this .labelFont, this .labelPaint, maxLabelWidth,
2392:                                new G2TextMeasurer(g2));
2393:                        TextBox labelBox = new TextBox(block);
2394:                        labelBox.setBackgroundPaint(this .labelBackgroundPaint);
2395:                        labelBox.setOutlinePaint(this .labelOutlinePaint);
2396:                        labelBox.setOutlineStroke(this .labelOutlineStroke);
2397:                        labelBox.setShadowPaint(this .labelShadowPaint);
2398:                        double theta = Math.toRadians(leftKeys.getValue(i)
2399:                                .doubleValue());
2400:                        double baseY = state.getPieCenterY() - Math.sin(theta)
2401:                                * verticalLinkRadius;
2402:                        double hh = labelBox.getHeight(g2);
2403:
2404:                        this .labelDistributor
2405:                                .addPieLabelRecord(new PieLabelRecord(leftKeys
2406:                                        .getKey(i), theta, baseY, labelBox, hh,
2407:                                        lGap / 2.0 + lGap / 2.0
2408:                                                * -Math.cos(theta),
2409:                                        0.9 + getExplodePercent(leftKeys
2410:                                                .getKey(i))));
2411:                    }
2412:                }
2413:                this .labelDistributor.distributeLabels(plotArea.getMinY(),
2414:                        plotArea.getHeight());
2415:                for (int i = 0; i < this .labelDistributor.getItemCount(); i++) {
2416:                    drawLeftLabel(g2, state, this .labelDistributor
2417:                            .getPieLabelRecord(i));
2418:                }
2419:            }
2420:
2421:            /**
2422:             * Draws the right labels.
2423:             * 
2424:             * @param keys  the keys.
2425:             * @param g2  the graphics device.
2426:             * @param plotArea  the plot area.
2427:             * @param linkArea  the link area.
2428:             * @param maxLabelWidth  the maximum label width.
2429:             * @param state  the state.
2430:             */
2431:            protected void drawRightLabels(KeyedValues keys, Graphics2D g2,
2432:                    Rectangle2D plotArea, Rectangle2D linkArea,
2433:                    float maxLabelWidth, PiePlotState state) {
2434:
2435:                // draw the right labels...
2436:                this .labelDistributor.clear();
2437:                double lGap = plotArea.getWidth() * this .labelGap;
2438:                double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0;
2439:
2440:                for (int i = 0; i < keys.getItemCount(); i++) {
2441:                    String label = this .labelGenerator.generateSectionLabel(
2442:                            this .dataset, keys.getKey(i));
2443:
2444:                    if (label != null) {
2445:                        TextBlock block = TextUtilities.createTextBlock(label,
2446:                                this .labelFont, this .labelPaint, maxLabelWidth,
2447:                                new G2TextMeasurer(g2));
2448:                        TextBox labelBox = new TextBox(block);
2449:                        labelBox.setBackgroundPaint(this .labelBackgroundPaint);
2450:                        labelBox.setOutlinePaint(this .labelOutlinePaint);
2451:                        labelBox.setOutlineStroke(this .labelOutlineStroke);
2452:                        labelBox.setShadowPaint(this .labelShadowPaint);
2453:                        double theta = Math.toRadians(keys.getValue(i)
2454:                                .doubleValue());
2455:                        double baseY = state.getPieCenterY() - Math.sin(theta)
2456:                                * verticalLinkRadius;
2457:                        double hh = labelBox.getHeight(g2);
2458:                        this .labelDistributor
2459:                                .addPieLabelRecord(new PieLabelRecord(keys
2460:                                        .getKey(i), theta, baseY, labelBox, hh,
2461:                                        lGap / 2.0 + lGap / 2.0
2462:                                                * Math.cos(theta),
2463:                                        0.9 + getExplodePercent(keys.getKey(i))));
2464:                    }
2465:                }
2466:                this .labelDistributor.distributeLabels(plotArea.getMinY(),
2467:                        plotArea.getHeight());
2468:                for (int i = 0; i < this .labelDistributor.getItemCount(); i++) {
2469:                    drawRightLabel(g2, state, this .labelDistributor
2470:                            .getPieLabelRecord(i));
2471:                }
2472:
2473:            }
2474:
2475:            /**
2476:             * Returns a collection of legend items for the pie chart.
2477:             *
2478:             * @return The legend items (never <code>null</code>).
2479:             */
2480:            public LegendItemCollection getLegendItems() {
2481:
2482:                LegendItemCollection result = new LegendItemCollection();
2483:                if (this .dataset == null) {
2484:                    return result;
2485:                }
2486:                List keys = this .dataset.getKeys();
2487:                int section = 0;
2488:                Shape shape = getLegendItemShape();
2489:                Iterator iterator = keys.iterator();
2490:                while (iterator.hasNext()) {
2491:                    Comparable key = (Comparable) iterator.next();
2492:                    Number n = this .dataset.getValue(key);
2493:                    boolean include = true;
2494:                    if (n == null) {
2495:                        include = !this .ignoreNullValues;
2496:                    } else {
2497:                        double v = n.doubleValue();
2498:                        if (v == 0.0) {
2499:                            include = !this .ignoreZeroValues;
2500:                        } else {
2501:                            include = v > 0.0;
2502:                        }
2503:                    }
2504:                    if (include) {
2505:                        String label = this .legendLabelGenerator
2506:                                .generateSectionLabel(this .dataset, key);
2507:                        if (label != null) {
2508:                            String description = label;
2509:                            String toolTipText = null;
2510:                            if (this .legendLabelToolTipGenerator != null) {
2511:                                toolTipText = this .legendLabelToolTipGenerator
2512:                                        .generateSectionLabel(this .dataset, key);
2513:                            }
2514:                            String urlText = null;
2515:                            if (this .legendLabelURLGenerator != null) {
2516:                                urlText = this .legendLabelURLGenerator
2517:                                        .generateURL(this .dataset, key,
2518:                                                this .pieIndex);
2519:                            }
2520:                            Paint paint = lookupSectionPaint(key, true);
2521:                            Paint outlinePaint = lookupSectionOutlinePaint(key);
2522:                            Stroke outlineStroke = lookupSectionOutlineStroke(key);
2523:                            LegendItem item = new LegendItem(label,
2524:                                    description, toolTipText, urlText, true,
2525:                                    shape, true, paint, true, outlinePaint,
2526:                                    outlineStroke,
2527:                                    false, // line not visible
2528:                                    new Line2D.Float(), new BasicStroke(),
2529:                                    Color.black);
2530:                            item.setDataset(getDataset());
2531:                            result.add(item);
2532:                        }
2533:                        section++;
2534:                    } else {
2535:                        section++;
2536:                    }
2537:                }
2538:                return result;
2539:            }
2540:
2541:            /**
2542:             * Returns a short string describing the type of plot.
2543:             *
2544:             * @return The plot type.
2545:             */
2546:            public String getPlotType() {
2547:                return localizationResources.getString("Pie_Plot");
2548:            }
2549:
2550:            /**
2551:             * Returns a rectangle that can be used to create a pie section (taking
2552:             * into account the amount by which the pie section is 'exploded').
2553:             *
2554:             * @param unexploded  the area inside which the unexploded pie sections are
2555:             *                    drawn.
2556:             * @param exploded  the area inside which the exploded pie sections are 
2557:             *                  drawn.
2558:             * @param angle  the start angle.
2559:             * @param extent  the extent of the arc.
2560:             * @param explodePercent  the amount by which the pie section is exploded.
2561:             *
2562:             * @return A rectangle that can be used to create a pie section.
2563:             */
2564:            protected Rectangle2D getArcBounds(Rectangle2D unexploded,
2565:                    Rectangle2D exploded, double angle, double extent,
2566:                    double explodePercent) {
2567:
2568:                if (explodePercent == 0.0) {
2569:                    return unexploded;
2570:                } else {
2571:                    Arc2D arc1 = new Arc2D.Double(unexploded, angle,
2572:                            extent / 2, Arc2D.OPEN);
2573:                    Point2D point1 = arc1.getEndPoint();
2574:                    Arc2D.Double arc2 = new Arc2D.Double(exploded, angle,
2575:                            extent / 2, Arc2D.OPEN);
2576:                    Point2D point2 = arc2.getEndPoint();
2577:                    double deltaX = (point1.getX() - point2.getX())
2578:                            * explodePercent;
2579:                    double deltaY = (point1.getY() - point2.getY())
2580:                            * explodePercent;
2581:                    return new Rectangle2D.Double(unexploded.getX() - deltaX,
2582:                            unexploded.getY() - deltaY, unexploded.getWidth(),
2583:                            unexploded.getHeight());
2584:                }
2585:            }
2586:
2587:            /**
2588:             * Draws a section label on the left side of the pie chart.
2589:             * 
2590:             * @param g2  the graphics device.
2591:             * @param state  the state.
2592:             * @param record  the label record.
2593:             */
2594:            protected void drawLeftLabel(Graphics2D g2, PiePlotState state,
2595:                    PieLabelRecord record) {
2596:
2597:                double anchorX = state.getLinkArea().getMinX();
2598:                double targetX = anchorX - record.getGap();
2599:                double targetY = record.getAllocatedY();
2600:
2601:                if (this .labelLinksVisible) {
2602:                    double theta = record.getAngle();
2603:                    double linkX = state.getPieCenterX() + Math.cos(theta)
2604:                            * state.getPieWRadius() * record.getLinkPercent();
2605:                    double linkY = state.getPieCenterY() - Math.sin(theta)
2606:                            * state.getPieHRadius() * record.getLinkPercent();
2607:                    double elbowX = state.getPieCenterX() + Math.cos(theta)
2608:                            * state.getLinkArea().getWidth() / 2.0;
2609:                    double elbowY = state.getPieCenterY() - Math.sin(theta)
2610:                            * state.getLinkArea().getHeight() / 2.0;
2611:                    double anchorY = elbowY;
2612:                    g2.setPaint(this .labelLinkPaint);
2613:                    g2.setStroke(this .labelLinkStroke);
2614:                    g2.draw(new Line2D.Double(linkX, linkY, elbowX, elbowY));
2615:                    g2
2616:                            .draw(new Line2D.Double(anchorX, anchorY, elbowX,
2617:                                    elbowY));
2618:                    g2.draw(new Line2D.Double(anchorX, anchorY, targetX,
2619:                            targetY));
2620:                }
2621:                TextBox tb = record.getLabel();
2622:                tb.draw(g2, (float) targetX, (float) targetY,
2623:                        RectangleAnchor.RIGHT);
2624:
2625:            }
2626:
2627:            /**
2628:             * Draws a section label on the right side of the pie chart.
2629:             * 
2630:             * @param g2  the graphics device.
2631:             * @param state  the state.
2632:             * @param record  the label record.
2633:             */
2634:            protected void drawRightLabel(Graphics2D g2, PiePlotState state,
2635:                    PieLabelRecord record) {
2636:
2637:                double anchorX = state.getLinkArea().getMaxX();
2638:                double targetX = anchorX + record.getGap();
2639:                double targetY = record.getAllocatedY();
2640:
2641:                if (this .labelLinksVisible) {
2642:                    double theta = record.getAngle();
2643:                    double linkX = state.getPieCenterX() + Math.cos(theta)
2644:                            * state.getPieWRadius() * record.getLinkPercent();
2645:                    double linkY = state.getPieCenterY() - Math.sin(theta)
2646:                            * state.getPieHRadius() * record.getLinkPercent();
2647:                    double elbowX = state.getPieCenterX() + Math.cos(theta)
2648:                            * state.getLinkArea().getWidth() / 2.0;
2649:                    double elbowY = state.getPieCenterY() - Math.sin(theta)
2650:                            * state.getLinkArea().getHeight() / 2.0;
2651:                    double anchorY = elbowY;
2652:                    g2.setPaint(this .labelLinkPaint);
2653:                    g2.setStroke(this .labelLinkStroke);
2654:                    g2.draw(new Line2D.Double(linkX, linkY, elbowX, elbowY));
2655:                    g2
2656:                            .draw(new Line2D.Double(anchorX, anchorY, elbowX,
2657:                                    elbowY));
2658:                    g2.draw(new Line2D.Double(anchorX, anchorY, targetX,
2659:                            targetY));
2660:                }
2661:
2662:                TextBox tb = record.getLabel();
2663:                tb.draw(g2, (float) targetX, (float) targetY,
2664:                        RectangleAnchor.LEFT);
2665:
2666:            }
2667:
2668:            /**
2669:             * Tests this plot for equality with an arbitrary object.  Note that the 
2670:             * plot's dataset is NOT included in the test for equality.
2671:             *
2672:             * @param obj  the object to test against (<code>null</code> permitted).
2673:             *
2674:             * @return <code>true</code> or <code>false</code>.
2675:             */
2676:            public boolean equals(Object obj) {
2677:                if (obj == this ) {
2678:                    return true;
2679:                }
2680:                if (!(obj instanceof  PiePlot)) {
2681:                    return false;
2682:                }
2683:                if (!super .equals(obj)) {
2684:                    return false;
2685:                }
2686:                PiePlot that = (PiePlot) obj;
2687:                if (this .pieIndex != that.pieIndex) {
2688:                    return false;
2689:                }
2690:                if (this .interiorGap != that.interiorGap) {
2691:                    return false;
2692:                }
2693:                if (this .circular != that.circular) {
2694:                    return false;
2695:                }
2696:                if (this .startAngle != that.startAngle) {
2697:                    return false;
2698:                }
2699:                if (this .direction != that.direction) {
2700:                    return false;
2701:                }
2702:                if (this .ignoreZeroValues != that.ignoreZeroValues) {
2703:                    return false;
2704:                }
2705:                if (this .ignoreNullValues != that.ignoreNullValues) {
2706:                    return false;
2707:                }
2708:                if (!PaintUtilities.equal(this .sectionPaint, that.sectionPaint)) {
2709:                    return false;
2710:                }
2711:                if (!ObjectUtilities.equal(this .sectionPaintMap,
2712:                        that.sectionPaintMap)) {
2713:                    return false;
2714:                }
2715:                if (!PaintUtilities.equal(this .baseSectionPaint,
2716:                        that.baseSectionPaint)) {
2717:                    return false;
2718:                }
2719:                if (this .sectionOutlinesVisible != that.sectionOutlinesVisible) {
2720:                    return false;
2721:                }
2722:                if (!PaintUtilities.equal(this .sectionOutlinePaint,
2723:                        that.sectionOutlinePaint)) {
2724:                    return false;
2725:                }
2726:                if (!ObjectUtilities.equal(this .sectionOutlinePaintMap,
2727:                        that.sectionOutlinePaintMap)) {
2728:                    return false;
2729:                }
2730:                if (!PaintUtilities.equal(this .baseSectionOutlinePaint,
2731:                        that.baseSectionOutlinePaint)) {
2732:                    return false;
2733:                }
2734:                if (!ObjectUtilities.equal(this .sectionOutlineStroke,
2735:                        that.sectionOutlineStroke)) {
2736:                    return false;
2737:                }
2738:                if (!ObjectUtilities.equal(this .sectionOutlineStrokeMap,
2739:                        that.sectionOutlineStrokeMap)) {
2740:                    return false;
2741:                }
2742:                if (!ObjectUtilities.equal(this .baseSectionOutlineStroke,
2743:                        that.baseSectionOutlineStroke)) {
2744:                    return false;
2745:                }
2746:                if (!PaintUtilities.equal(this .shadowPaint, that.shadowPaint)) {
2747:                    return false;
2748:                }
2749:                if (!(this .shadowXOffset == that.shadowXOffset)) {
2750:                    return false;
2751:                }
2752:                if (!(this .shadowYOffset == that.shadowYOffset)) {
2753:                    return false;
2754:                }
2755:                if (!ObjectUtilities.equal(this .explodePercentages,
2756:                        that.explodePercentages)) {
2757:                    return false;
2758:                }
2759:                if (!ObjectUtilities.equal(this .labelGenerator,
2760:                        that.labelGenerator)) {
2761:                    return false;
2762:                }
2763:                if (!ObjectUtilities.equal(this .labelFont, that.labelFont)) {
2764:                    return false;
2765:                }
2766:                if (!PaintUtilities.equal(this .labelPaint, that.labelPaint)) {
2767:                    return false;
2768:                }
2769:                if (!PaintUtilities.equal(this .labelBackgroundPaint,
2770:                        that.labelBackgroundPaint)) {
2771:                    return false;
2772:                }
2773:                if (!PaintUtilities.equal(this .labelOutlinePaint,
2774:                        that.labelOutlinePaint)) {
2775:                    return false;
2776:                }
2777:                if (!ObjectUtilities.equal(this .labelOutlineStroke,
2778:                        that.labelOutlineStroke)) {
2779:                    return false;
2780:                }
2781:                if (!PaintUtilities.equal(this .labelShadowPaint,
2782:                        that.labelShadowPaint)) {
2783:                    return false;
2784:                }
2785:                if (!(this .maximumLabelWidth == that.maximumLabelWidth)) {
2786:                    return false;
2787:                }
2788:                if (!(this .labelGap == that.labelGap)) {
2789:                    return false;
2790:                }
2791:                if (!(this .labelLinkMargin == that.labelLinkMargin)) {
2792:                    return false;
2793:                }
2794:                if (this .labelLinksVisible != that.labelLinksVisible) {
2795:                    return false;
2796:                }
2797:                if (!PaintUtilities.equal(this .labelLinkPaint,
2798:                        that.labelLinkPaint)) {
2799:                    return false;
2800:                }
2801:                if (!ObjectUtilities.equal(this .labelLinkStroke,
2802:                        that.labelLinkStroke)) {
2803:                    return false;
2804:                }
2805:                if (!ObjectUtilities.equal(this .toolTipGenerator,
2806:                        that.toolTipGenerator)) {
2807:                    return false;
2808:                }
2809:                if (!ObjectUtilities
2810:                        .equal(this .urlGenerator, that.urlGenerator)) {
2811:                    return false;
2812:                }
2813:                if (!(this .minimumArcAngleToDraw == that.minimumArcAngleToDraw)) {
2814:                    return false;
2815:                }
2816:                if (!ShapeUtilities.equal(this .legendItemShape,
2817:                        that.legendItemShape)) {
2818:                    return false;
2819:                }
2820:                if (!ObjectUtilities.equal(this .legendLabelGenerator,
2821:                        that.legendLabelGenerator)) {
2822:                    return false;
2823:                }
2824:                if (!ObjectUtilities.equal(this .legendLabelToolTipGenerator,
2825:                        that.legendLabelToolTipGenerator)) {
2826:                    return false;
2827:                }
2828:                if (!ObjectUtilities.equal(this .legendLabelURLGenerator,
2829:                        that.legendLabelURLGenerator)) {
2830:                    return false;
2831:                }
2832:                // can't find any difference...
2833:                return true;
2834:            }
2835:
2836:            /**
2837:             * Returns a clone of the plot.
2838:             *
2839:             * @return A clone.
2840:             *
2841:             * @throws CloneNotSupportedException if some component of the plot does 
2842:             *         not support cloning.
2843:             */
2844:            public Object clone() throws CloneNotSupportedException {
2845:                PiePlot clone = (PiePlot) super .clone();
2846:                if (clone.dataset != null) {
2847:                    clone.dataset.addChangeListener(clone);
2848:                }
2849:                if (this .urlGenerator instanceof  PublicCloneable) {
2850:                    clone.urlGenerator = (PieURLGenerator) ObjectUtilities
2851:                            .clone(this .urlGenerator);
2852:                }
2853:                clone.legendItemShape = ShapeUtilities
2854:                        .clone(this .legendItemShape);
2855:                if (this .legendLabelGenerator != null) {
2856:                    clone.legendLabelGenerator = (PieSectionLabelGenerator) ObjectUtilities
2857:                            .clone(this .legendLabelGenerator);
2858:                }
2859:                if (this .legendLabelToolTipGenerator != null) {
2860:                    clone.legendLabelToolTipGenerator = (PieSectionLabelGenerator) ObjectUtilities
2861:                            .clone(this .legendLabelToolTipGenerator);
2862:                }
2863:                if (this .legendLabelURLGenerator instanceof  PublicCloneable) {
2864:                    clone.legendLabelURLGenerator = (PieURLGenerator) ObjectUtilities
2865:                            .clone(this .legendLabelURLGenerator);
2866:                }
2867:                return clone;
2868:            }
2869:
2870:            /**
2871:             * Provides serialization support.
2872:             *
2873:             * @param stream  the output stream.
2874:             *
2875:             * @throws IOException  if there is an I/O error.
2876:             */
2877:            private void writeObject(ObjectOutputStream stream)
2878:                    throws IOException {
2879:                stream.defaultWriteObject();
2880:                SerialUtilities.writePaint(this .sectionPaint, stream);
2881:                SerialUtilities.writePaint(this .baseSectionPaint, stream);
2882:                SerialUtilities.writePaint(this .sectionOutlinePaint, stream);
2883:                SerialUtilities
2884:                        .writePaint(this .baseSectionOutlinePaint, stream);
2885:                SerialUtilities.writeStroke(this .sectionOutlineStroke, stream);
2886:                SerialUtilities.writeStroke(this .baseSectionOutlineStroke,
2887:                        stream);
2888:                SerialUtilities.writePaint(this .shadowPaint, stream);
2889:                SerialUtilities.writePaint(this .labelPaint, stream);
2890:                SerialUtilities.writePaint(this .labelBackgroundPaint, stream);
2891:                SerialUtilities.writePaint(this .labelOutlinePaint, stream);
2892:                SerialUtilities.writeStroke(this .labelOutlineStroke, stream);
2893:                SerialUtilities.writePaint(this .labelShadowPaint, stream);
2894:                SerialUtilities.writePaint(this .labelLinkPaint, stream);
2895:                SerialUtilities.writeStroke(this .labelLinkStroke, stream);
2896:                SerialUtilities.writeShape(this .legendItemShape, stream);
2897:            }
2898:
2899:            /**
2900:             * Provides serialization support.
2901:             *
2902:             * @param stream  the input stream.
2903:             *
2904:             * @throws IOException  if there is an I/O error.
2905:             * @throws ClassNotFoundException  if there is a classpath problem.
2906:             */
2907:            private void readObject(ObjectInputStream stream)
2908:                    throws IOException, ClassNotFoundException {
2909:                stream.defaultReadObject();
2910:                this .sectionPaint = SerialUtilities.readPaint(stream);
2911:                this .baseSectionPaint = SerialUtilities.readPaint(stream);
2912:                this .sectionOutlinePaint = SerialUtilities.readPaint(stream);
2913:                this .baseSectionOutlinePaint = SerialUtilities
2914:                        .readPaint(stream);
2915:                this .sectionOutlineStroke = SerialUtilities.readStroke(stream);
2916:                this .baseSectionOutlineStroke = SerialUtilities
2917:                        .readStroke(stream);
2918:                this .shadowPaint = SerialUtilities.readPaint(stream);
2919:                this .labelPaint = SerialUtilities.readPaint(stream);
2920:                this .labelBackgroundPaint = SerialUtilities.readPaint(stream);
2921:                this .labelOutlinePaint = SerialUtilities.readPaint(stream);
2922:                this .labelOutlineStroke = SerialUtilities.readStroke(stream);
2923:                this .labelShadowPaint = SerialUtilities.readPaint(stream);
2924:                this .labelLinkPaint = SerialUtilities.readPaint(stream);
2925:                this .labelLinkStroke = SerialUtilities.readStroke(stream);
2926:                this .legendItemShape = SerialUtilities.readShape(stream);
2927:            }
2928:
2929:            // DEPRECATED METHODS...
2930:
2931:            /**
2932:             * Returns the paint for the specified section.
2933:             * 
2934:             * @param section  the section index (zero-based).
2935:             * 
2936:             * @return The paint (never <code>null</code>).
2937:             * 
2938:             * @deprecated Use {@link #getSectionPaint(Comparable)} instead.
2939:             */
2940:            public Paint getSectionPaint(int section) {
2941:                Comparable key = getSectionKey(section);
2942:                return getSectionPaint(key);
2943:            }
2944:
2945:            /**
2946:             * Sets the paint used to fill a section of the pie and sends a 
2947:             * {@link PlotChangeEvent} to all registered listeners.
2948:             *
2949:             * @param section  the section index (zero-based).
2950:             * @param paint  the paint (<code>null</code> permitted).
2951:             * 
2952:             * @deprecated Use {@link #setSectionPaint(Comparable, Paint)} instead.
2953:             */
2954:            public void setSectionPaint(int section, Paint paint) {
2955:                Comparable key = getSectionKey(section);
2956:                setSectionPaint(key, paint);
2957:            }
2958:
2959:            /**
2960:             * Returns the paint for the specified section.
2961:             * 
2962:             * @param section  the section index (zero-based).
2963:             * 
2964:             * @return The paint (possibly <code>null</code>).
2965:             * 
2966:             * @deprecated Use {@link #getSectionOutlinePaint(Comparable)} instead.
2967:             */
2968:            public Paint getSectionOutlinePaint(int section) {
2969:                Comparable key = getSectionKey(section);
2970:                return getSectionOutlinePaint(key);
2971:            }
2972:
2973:            /**
2974:             * Sets the paint used to fill a section of the pie and sends a 
2975:             * {@link PlotChangeEvent} to all registered listeners.
2976:             *
2977:             * @param section  the section index (zero-based).
2978:             * @param paint  the paint (<code>null</code> permitted).
2979:             * 
2980:             * @deprecated Use {@link #setSectionOutlinePaint(Comparable, Paint)} 
2981:             *     instead.
2982:             */
2983:            public void setSectionOutlinePaint(int section, Paint paint) {
2984:                Comparable key = getSectionKey(section);
2985:                setSectionOutlinePaint(key, paint);
2986:            }
2987:
2988:            /**
2989:             * Returns the stroke for the specified section.
2990:             * 
2991:             * @param section  the section index (zero-based).
2992:             * 
2993:             * @return The stroke (possibly <code>null</code>).
2994:             *
2995:             * @deprecated Use {@link #getSectionOutlineStroke(Comparable)} instead.
2996:             */
2997:            public Stroke getSectionOutlineStroke(int section) {
2998:                Comparable key = getSectionKey(section);
2999:                return getSectionOutlineStroke(key);
3000:            }
3001:
3002:            /**
3003:             * Sets the stroke used to fill a section of the pie and sends a 
3004:             * {@link PlotChangeEvent} to all registered listeners.
3005:             *
3006:             * @param section  the section index (zero-based).
3007:             * @param stroke  the stroke (<code>null</code> permitted).
3008:             * 
3009:             * @deprecated Use {@link #setSectionOutlineStroke(Comparable, Stroke)} 
3010:             *     instead.
3011:             */
3012:            public void setSectionOutlineStroke(int section, Stroke stroke) {
3013:                Comparable key = getSectionKey(section);
3014:                setSectionOutlineStroke(key, stroke);
3015:            }
3016:
3017:            /**
3018:             * Returns the amount that a section should be 'exploded'.
3019:             *
3020:             * @param section  the section number.
3021:             *
3022:             * @return The amount that a section should be 'exploded'.
3023:             * 
3024:             * @deprecated Use {@link #getExplodePercent(Comparable)} instead.
3025:             */
3026:            public double getExplodePercent(int section) {
3027:                Comparable key = getSectionKey(section);
3028:                return getExplodePercent(key);
3029:            }
3030:
3031:            /**
3032:             * Sets the amount that a pie section should be exploded and sends a 
3033:             * {@link PlotChangeEvent} to all registered listeners.
3034:             *
3035:             * @param section  the section index.
3036:             * @param percent  the explode percentage (0.30 = 30 percent).
3037:             * 
3038:             * @deprecated Use {@link #setExplodePercent(Comparable, double)} instead.
3039:             */
3040:            public void setExplodePercent(int section, double percent) {
3041:                Comparable key = getSectionKey(section);
3042:                setExplodePercent(key, percent);
3043:            }
3044:
3045:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.