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

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


001:        /* ===========================================================
002:         * JFreeChart : a free chart library for the Java(tm) platform
003:         * ===========================================================
004:         *
005:         * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
006:         *
007:         * Project Info:  http://www.jfree.org/jfreechart/index.html
008:         *
009:         * This library is free software; you can redistribute it and/or modify it 
010:         * under the terms of the GNU Lesser General Public License as published by 
011:         * the Free Software Foundation; either version 2.1 of the License, or 
012:         * (at your option) any later version.
013:         *
014:         * This library is distributed in the hope that it will be useful, but 
015:         * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
016:         * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
017:         * License for more details.
018:         *
019:         * You should have received a copy of the GNU Lesser General Public
020:         * License along with this library; if not, write to the Free Software
021:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
022:         * USA.  
023:         *
024:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
025:         * in the United States and other countries.]
026:         *
027:         * ------------------------
028:         * CandlestickRenderer.java
029:         * ------------------------
030:         * (C) Copyright 2001-2007, by Object Refinery Limited.
031:         *
032:         * Original Authors:  David Gilbert (for Object Refinery Limited);
033:         *                    Sylvain Vieujot;
034:         * Contributor(s):    Richard Atkinson;
035:         *                    Christian W. Zuckschwerdt;
036:         *                    Jerome Fisher;
037:         *
038:         * $Id: CandlestickRenderer.java,v 1.7.2.6 2007/06/11 11:07:18 mungady Exp $
039:         *
040:         * Changes
041:         * -------
042:         * 13-Dec-2001 : Version 1.  Based on code in the (now redundant) 
043:         *               CandlestickPlot class, written by Sylvain Vieujot (DG);
044:         * 23-Jan-2002 : Added DrawInfo parameter to drawItem() method (DG);
045:         * 28-Mar-2002 : Added a property change listener mechanism so that renderers 
046:         *               no longer need to be immutable.  Added properties for up and 
047:         *               down colors (DG);
048:         * 04-Apr-2002 : Updated with new automatic width calculation and optional 
049:         *               volume display, contributed by Sylvain Vieujot (DG);
050:         * 09-Apr-2002 : Removed translatedRangeZero from the drawItem() method, and 
051:         *               changed the return type of the drawItem method to void, 
052:         *               reflecting a change in the XYItemRenderer interface.  Added 
053:         *               tooltip code to drawItem() method (DG);
054:         * 25-Jun-2002 : Removed redundant code (DG);
055:         * 05-Aug-2002 : Small modification to drawItem method to support URLs for HTML 
056:         *               image maps (RA);
057:         * 19-Sep-2002 : Fixed errors reported by Checkstyle (DG);
058:         * 25-Mar-2003 : Implemented Serializable (DG);
059:         * 01-May-2003 : Modified drawItem() method signature (DG);
060:         * 30-Jun-2003 : Added support for PlotOrientation (for completeness, this 
061:         *               renderer is unlikely to be used with a HORIZONTAL 
062:         *               orientation) (DG);
063:         * 30-Jul-2003 : Modified entity constructor (CZ);
064:         * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
065:         * 29-Aug-2003 : Moved maxVolume calculation to initialise method (see bug 
066:         *               report 796619) (DG);
067:         * 02-Sep-2003 : Added maxCandleWidthInMilliseconds as workaround for bug 
068:         *               796621 (DG);
069:         * 08-Sep-2003 : Changed ValueAxis API (DG);
070:         * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
071:         * 13-Oct-2003 : Applied patch from Jerome Fisher to improve auto width 
072:         *               calculations (DG);
073:         * 23-Dec-2003 : Fixed bug where up and down paint are used incorrectly (DG);
074:         * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
075:         * 15-Jul-2004 : Switched getX() with getXValue() and getY() with 
076:         *               getYValue() (DG);
077:         * ------------- JFREECHART 1.0.x ---------------------------------------------
078:         * 06-Jul-2006 : Swapped calls to getX() --> getXValue(), and the same for the
079:         *               other data values (DG);
080:         * 17-Aug-2006 : Corrections to the equals() method (DG);
081:         * 05-Mar-2007 : Added flag to allow optional use of outline paint (DG);
082:         * 
083:         */
084:
085:        package org.jfree.chart.renderer.xy;
086:
087:        import java.awt.AlphaComposite;
088:        import java.awt.Color;
089:        import java.awt.Composite;
090:        import java.awt.Graphics2D;
091:        import java.awt.Paint;
092:        import java.awt.Shape;
093:        import java.awt.Stroke;
094:        import java.awt.geom.Line2D;
095:        import java.awt.geom.Rectangle2D;
096:        import java.io.IOException;
097:        import java.io.ObjectInputStream;
098:        import java.io.ObjectOutputStream;
099:        import java.io.Serializable;
100:
101:        import org.jfree.chart.axis.ValueAxis;
102:        import org.jfree.chart.entity.EntityCollection;
103:        import org.jfree.chart.entity.XYItemEntity;
104:        import org.jfree.chart.event.RendererChangeEvent;
105:        import org.jfree.chart.labels.HighLowItemLabelGenerator;
106:        import org.jfree.chart.labels.XYToolTipGenerator;
107:        import org.jfree.chart.plot.CrosshairState;
108:        import org.jfree.chart.plot.PlotOrientation;
109:        import org.jfree.chart.plot.PlotRenderingInfo;
110:        import org.jfree.chart.plot.XYPlot;
111:        import org.jfree.data.xy.IntervalXYDataset;
112:        import org.jfree.data.xy.OHLCDataset;
113:        import org.jfree.data.xy.XYDataset;
114:        import org.jfree.io.SerialUtilities;
115:        import org.jfree.ui.RectangleEdge;
116:        import org.jfree.util.PaintUtilities;
117:        import org.jfree.util.PublicCloneable;
118:
119:        /**
120:         * A renderer that draws candlesticks on an {@link XYPlot} (requires a 
121:         * {@link OHLCDataset}).
122:         * <P>
123:         * This renderer does not include code to calculate the crosshair point for the 
124:         * plot.
125:         */
126:        public class CandlestickRenderer extends AbstractXYItemRenderer
127:                implements  XYItemRenderer, Cloneable, PublicCloneable,
128:                Serializable {
129:
130:            /** For serialization. */
131:            private static final long serialVersionUID = 50390395841817121L;
132:
133:            /** The average width method. */
134:            public static final int WIDTHMETHOD_AVERAGE = 0;
135:
136:            /** The smallest width method. */
137:            public static final int WIDTHMETHOD_SMALLEST = 1;
138:
139:            /** The interval data method. */
140:            public static final int WIDTHMETHOD_INTERVALDATA = 2;
141:
142:            /** The method of automatically calculating the candle width. */
143:            private int autoWidthMethod = WIDTHMETHOD_AVERAGE;
144:
145:            /** 
146:             * The number (generally between 0.0 and 1.0) by which the available space 
147:             * automatically calculated for the candles will be multiplied to determine
148:             * the actual width to use. 
149:             */
150:            private double autoWidthFactor = 4.5 / 7;
151:
152:            /** The minimum gap between one candle and the next */
153:            private double autoWidthGap = 0.0;
154:
155:            /** The candle width. */
156:            private double candleWidth;
157:
158:            /** The maximum candlewidth in milliseconds. */
159:            private double maxCandleWidthInMilliseconds = 1000.0 * 60.0 * 60.0 * 20.0;
160:
161:            /** Temporary storage for the maximum candle width. */
162:            private double maxCandleWidth;
163:
164:            /** 
165:             * The paint used to fill the candle when the price moved up from open to 
166:             * close. 
167:             */
168:            private transient Paint upPaint;
169:
170:            /** 
171:             * The paint used to fill the candle when the price moved down from open 
172:             * to close. 
173:             */
174:            private transient Paint downPaint;
175:
176:            /** A flag controlling whether or not volume bars are drawn on the chart. */
177:            private boolean drawVolume;
178:
179:            /** Temporary storage for the maximum volume. */
180:            private transient double maxVolume;
181:
182:            /** 
183:             * A flag that controls whether or not the renderer's outline paint is
184:             * used to draw the outline of the candlestick.  The default value is
185:             * <code>false</code> to avoid a change of behaviour for existing code.
186:             * 
187:             * @since 1.0.5
188:             */
189:            private boolean useOutlinePaint;
190:
191:            /**
192:             * Creates a new renderer for candlestick charts.
193:             */
194:            public CandlestickRenderer() {
195:                this (-1.0);
196:            }
197:
198:            /**
199:             * Creates a new renderer for candlestick charts.
200:             * <P>
201:             * Use -1 for the candle width if you prefer the width to be calculated 
202:             * automatically.
203:             *
204:             * @param candleWidth  The candle width.
205:             */
206:            public CandlestickRenderer(double candleWidth) {
207:                this (candleWidth, true, new HighLowItemLabelGenerator());
208:            }
209:
210:            /**
211:             * Creates a new renderer for candlestick charts.
212:             * <P>
213:             * Use -1 for the candle width if you prefer the width to be calculated 
214:             * automatically.
215:             *
216:             * @param candleWidth  the candle width.
217:             * @param drawVolume  a flag indicating whether or not volume bars should 
218:             *                    be drawn.
219:             * @param toolTipGenerator  the tool tip generator. <code>null</code> is 
220:             *                          none.
221:             */
222:            public CandlestickRenderer(double candleWidth, boolean drawVolume,
223:                    XYToolTipGenerator toolTipGenerator) {
224:                super ();
225:                setBaseToolTipGenerator(toolTipGenerator);
226:                this .candleWidth = candleWidth;
227:                this .drawVolume = drawVolume;
228:                this .upPaint = Color.green;
229:                this .downPaint = Color.red;
230:                this .useOutlinePaint = false; // false preserves the old behaviour
231:                // prior to introducing this flag
232:            }
233:
234:            /**
235:             * Returns the width of each candle.
236:             *
237:             * @return The candle width.
238:             * 
239:             * @see #setCandleWidth(double)
240:             */
241:            public double getCandleWidth() {
242:                return this .candleWidth;
243:            }
244:
245:            /**
246:             * Sets the candle width.
247:             * <P>
248:             * If you set the width to a negative value, the renderer will calculate
249:             * the candle width automatically based on the space available on the chart.
250:             *
251:             * @param width  The width.
252:             * @see #setAutoWidthMethod(int)
253:             * @see #setAutoWidthGap(double)
254:             * @see #setAutoWidthFactor(double)
255:             * @see #setMaxCandleWidthInMilliseconds(double)
256:             */
257:            public void setCandleWidth(double width) {
258:                if (width != this .candleWidth) {
259:                    this .candleWidth = width;
260:                    notifyListeners(new RendererChangeEvent(this ));
261:                }
262:            }
263:
264:            /**
265:             * Returns the maximum width (in milliseconds) of each candle.
266:             *
267:             * @return The maximum candle width in milliseconds.
268:             * 
269:             * @see #setMaxCandleWidthInMilliseconds(double)
270:             */
271:            public double getMaxCandleWidthInMilliseconds() {
272:                return this .maxCandleWidthInMilliseconds;
273:            }
274:
275:            /**
276:             * Sets the maximum candle width (in milliseconds).  
277:             *
278:             * @param millis  The maximum width.
279:             * 
280:             * @see #getMaxCandleWidthInMilliseconds()
281:             * @see #setCandleWidth(double)
282:             * @see #setAutoWidthMethod(int)
283:             * @see #setAutoWidthGap(double)
284:             * @see #setAutoWidthFactor(double)
285:             */
286:            public void setMaxCandleWidthInMilliseconds(double millis) {
287:                this .maxCandleWidthInMilliseconds = millis;
288:                notifyListeners(new RendererChangeEvent(this ));
289:            }
290:
291:            /**
292:             * Returns the method of automatically calculating the candle width.
293:             *
294:             * @return The method of automatically calculating the candle width.
295:             * 
296:             * @see #setAutoWidthMethod(int)
297:             */
298:            public int getAutoWidthMethod() {
299:                return this .autoWidthMethod;
300:            }
301:
302:            /**
303:             * Sets the method of automatically calculating the candle width.
304:             * <p>
305:             * <code>WIDTHMETHOD_AVERAGE</code>: Divides the entire display (ignoring 
306:             * scale factor) by the number of items, and uses this as the available 
307:             * width.<br>
308:             * <code>WIDTHMETHOD_SMALLEST</code>: Checks the interval between each 
309:             * item, and uses the smallest as the available width.<br>
310:             * <code>WIDTHMETHOD_INTERVALDATA</code>: Assumes that the dataset supports
311:             * the IntervalXYDataset interface, and uses the startXValue - endXValue as 
312:             * the available width.
313:             * <br>
314:             *
315:             * @param autoWidthMethod  The method of automatically calculating the 
316:             * candle width.
317:             *
318:             * @see #WIDTHMETHOD_AVERAGE
319:             * @see #WIDTHMETHOD_SMALLEST
320:             * @see #WIDTHMETHOD_INTERVALDATA
321:             * @see #getAutoWidthMethod()
322:             * @see #setCandleWidth(double)
323:             * @see #setAutoWidthGap(double)
324:             * @see #setAutoWidthFactor(double)
325:             * @see #setMaxCandleWidthInMilliseconds(double)
326:             */
327:            public void setAutoWidthMethod(int autoWidthMethod) {
328:                if (this .autoWidthMethod != autoWidthMethod) {
329:                    this .autoWidthMethod = autoWidthMethod;
330:                    notifyListeners(new RendererChangeEvent(this ));
331:                }
332:            }
333:
334:            /**
335:             * Returns the factor by which the available space automatically 
336:             * calculated for the candles will be multiplied to determine the actual 
337:             * width to use.
338:             *
339:             * @return The width factor (generally between 0.0 and 1.0).
340:             * 
341:             * @see #setAutoWidthFactor(double)
342:             */
343:            public double getAutoWidthFactor() {
344:                return this .autoWidthFactor;
345:            }
346:
347:            /**
348:             * Sets the factor by which the available space automatically calculated 
349:             * for the candles will be multiplied to determine the actual width to use.
350:             *
351:             * @param autoWidthFactor The width factor (generally between 0.0 and 1.0).
352:             * 
353:             * @see #getAutoWidthFactor()
354:             * @see #setCandleWidth(double)
355:             * @see #setAutoWidthMethod(int)
356:             * @see #setAutoWidthGap(double)
357:             * @see #setMaxCandleWidthInMilliseconds(double)
358:             */
359:            public void setAutoWidthFactor(double autoWidthFactor) {
360:                if (this .autoWidthFactor != autoWidthFactor) {
361:                    this .autoWidthFactor = autoWidthFactor;
362:                    notifyListeners(new RendererChangeEvent(this ));
363:                }
364:            }
365:
366:            /**
367:             * Returns the amount of space to leave on the left and right of each 
368:             * candle when automatically calculating widths.
369:             *
370:             * @return The gap.
371:             * 
372:             * @see #setAutoWidthGap(double)
373:             */
374:            public double getAutoWidthGap() {
375:                return this .autoWidthGap;
376:            }
377:
378:            /**
379:             * Sets the amount of space to leave on the left and right of each candle 
380:             * when automatically calculating widths.
381:             *
382:             * @param autoWidthGap The gap.
383:             * 
384:             * @see #getAutoWidthGap()
385:             * @see #setCandleWidth(double)
386:             * @see #setAutoWidthMethod(int)
387:             * @see #setAutoWidthFactor(double)
388:             * @see #setMaxCandleWidthInMilliseconds(double)
389:             */
390:            public void setAutoWidthGap(double autoWidthGap) {
391:                if (this .autoWidthGap != autoWidthGap) {
392:                    this .autoWidthGap = autoWidthGap;
393:                    notifyListeners(new RendererChangeEvent(this ));
394:                }
395:            }
396:
397:            /**
398:             * Returns the paint used to fill candles when the price moves up from open
399:             * to close.
400:             *
401:             * @return The paint (possibly <code>null</code>).
402:             * 
403:             * @see #setUpPaint(Paint)
404:             */
405:            public Paint getUpPaint() {
406:                return this .upPaint;
407:            }
408:
409:            /**
410:             * Sets the paint used to fill candles when the price moves up from open
411:             * to close and sends a {@link RendererChangeEvent} to all registered
412:             * listeners.
413:             *
414:             * @param paint  the paint (<code>null</code> permitted).
415:             * 
416:             * @see #getUpPaint()
417:             */
418:            public void setUpPaint(Paint paint) {
419:                this .upPaint = paint;
420:                notifyListeners(new RendererChangeEvent(this ));
421:            }
422:
423:            /**
424:             * Returns the paint used to fill candles when the price moves down from
425:             * open to close.
426:             *
427:             * @return The paint (possibly <code>null</code>).
428:             * 
429:             * @see #setDownPaint(Paint)
430:             */
431:            public Paint getDownPaint() {
432:                return this .downPaint;
433:            }
434:
435:            /**
436:             * Sets the paint used to fill candles when the price moves down from open
437:             * to close and sends a {@link RendererChangeEvent} to all registered
438:             * listeners.
439:             *
440:             * @param paint  The paint (<code>null</code> permitted).
441:             */
442:            public void setDownPaint(Paint paint) {
443:                this .downPaint = paint;
444:                notifyListeners(new RendererChangeEvent(this ));
445:            }
446:
447:            /**
448:             * Returns a flag indicating whether or not volume bars are drawn on the
449:             * chart.
450:             * 
451:             * @return A boolean.
452:             * 
453:             * @since 1.0.5
454:             * 
455:             * @see #setDrawVolume(boolean)
456:             */
457:            public boolean getDrawVolume() {
458:                return this .drawVolume;
459:            }
460:
461:            /**
462:             * Sets a flag that controls whether or not volume bars are drawn in the
463:             * background and sends a {@link RendererChangeEvent} to all registered
464:             * listeners.
465:             *
466:             * @param flag  the flag.
467:             * 
468:             * @see #getDrawVolume()
469:             */
470:            public void setDrawVolume(boolean flag) {
471:                if (this .drawVolume != flag) {
472:                    this .drawVolume = flag;
473:                    notifyListeners(new RendererChangeEvent(this ));
474:                }
475:            }
476:
477:            /**
478:             * Returns the flag that controls whether or not the renderer's outline
479:             * paint is used to draw the candlestick outline.  The default value is
480:             * <code>false</code>.
481:             * 
482:             * @return A boolean.
483:             * 
484:             * @since 1.0.5
485:             * 
486:             * @see #setUseOutlinePaint(boolean)
487:             */
488:            public boolean getUseOutlinePaint() {
489:                return this .useOutlinePaint;
490:            }
491:
492:            /**
493:             * Sets the flag that controls whether or not the renderer's outline
494:             * paint is used to draw the candlestick outline, and sends a 
495:             * {@link RendererChangeEvent} to all registered listeners.
496:             * 
497:             * @param use  the new flag value.
498:             * 
499:             * @since 1.0.5
500:             * 
501:             * @see #getUseOutlinePaint()
502:             */
503:            public void setUseOutlinePaint(boolean use) {
504:                if (this .useOutlinePaint != use) {
505:                    this .useOutlinePaint = use;
506:                    fireChangeEvent();
507:                }
508:            }
509:
510:            /**
511:             * Initialises the renderer then returns the number of 'passes' through the
512:             * data that the renderer will require (usually just one).  This method 
513:             * will be called before the first item is rendered, giving the renderer 
514:             * an opportunity to initialise any state information it wants to maintain.
515:             * The renderer can do nothing if it chooses.
516:             *
517:             * @param g2  the graphics device.
518:             * @param dataArea  the area inside the axes.
519:             * @param plot  the plot.
520:             * @param dataset  the data.
521:             * @param info  an optional info collection object to return data back to 
522:             *              the caller.
523:             *
524:             * @return The number of passes the renderer requires.
525:             */
526:            public XYItemRendererState initialise(Graphics2D g2,
527:                    Rectangle2D dataArea, XYPlot plot, XYDataset dataset,
528:                    PlotRenderingInfo info) {
529:
530:                // calculate the maximum allowed candle width from the axis...
531:                ValueAxis axis = plot.getDomainAxis();
532:                double x1 = axis.getLowerBound();
533:                double x2 = x1 + this .maxCandleWidthInMilliseconds;
534:                RectangleEdge edge = plot.getDomainAxisEdge();
535:                double xx1 = axis.valueToJava2D(x1, dataArea, edge);
536:                double xx2 = axis.valueToJava2D(x2, dataArea, edge);
537:                this .maxCandleWidth = Math.abs(xx2 - xx1);
538:                // Absolute value, since the relative x 
539:                // positions are reversed for horizontal orientation
540:
541:                // calculate the highest volume in the dataset... 
542:                if (this .drawVolume) {
543:                    OHLCDataset highLowDataset = (OHLCDataset) dataset;
544:                    this .maxVolume = 0.0;
545:                    for (int series = 0; series < highLowDataset
546:                            .getSeriesCount(); series++) {
547:                        for (int item = 0; item < highLowDataset
548:                                .getItemCount(series); item++) {
549:                            double volume = highLowDataset.getVolumeValue(
550:                                    series, item);
551:                            if (volume > this .maxVolume) {
552:                                this .maxVolume = volume;
553:                            }
554:
555:                        }
556:                    }
557:                }
558:
559:                return new XYItemRendererState(info);
560:            }
561:
562:            /**
563:             * Draws the visual representation of a single data item.
564:             *
565:             * @param g2  the graphics device.
566:             * @param state  the renderer state.
567:             * @param dataArea  the area within which the plot is being drawn.
568:             * @param info  collects info about the drawing.
569:             * @param plot  the plot (can be used to obtain standard color 
570:             *              information etc).
571:             * @param domainAxis  the domain axis.
572:             * @param rangeAxis  the range axis.
573:             * @param dataset  the dataset.
574:             * @param series  the series index (zero-based).
575:             * @param item  the item index (zero-based).
576:             * @param crosshairState  crosshair information for the plot 
577:             *                        (<code>null</code> permitted).
578:             * @param pass  the pass index.
579:             */
580:            public void drawItem(Graphics2D g2, XYItemRendererState state,
581:                    Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot,
582:                    ValueAxis domainAxis, ValueAxis rangeAxis,
583:                    XYDataset dataset, int series, int item,
584:                    CrosshairState crosshairState, int pass) {
585:
586:                boolean horiz;
587:                PlotOrientation orientation = plot.getOrientation();
588:                if (orientation == PlotOrientation.HORIZONTAL) {
589:                    horiz = true;
590:                } else if (orientation == PlotOrientation.VERTICAL) {
591:                    horiz = false;
592:                } else {
593:                    return;
594:                }
595:
596:                // setup for collecting optional entity info...
597:                EntityCollection entities = null;
598:                if (info != null) {
599:                    entities = info.getOwner().getEntityCollection();
600:                }
601:
602:                OHLCDataset highLowData = (OHLCDataset) dataset;
603:
604:                double x = highLowData.getXValue(series, item);
605:                double yHigh = highLowData.getHighValue(series, item);
606:                double yLow = highLowData.getLowValue(series, item);
607:                double yOpen = highLowData.getOpenValue(series, item);
608:                double yClose = highLowData.getCloseValue(series, item);
609:
610:                RectangleEdge domainEdge = plot.getDomainAxisEdge();
611:                double xx = domainAxis.valueToJava2D(x, dataArea, domainEdge);
612:
613:                RectangleEdge edge = plot.getRangeAxisEdge();
614:                double yyHigh = rangeAxis.valueToJava2D(yHigh, dataArea, edge);
615:                double yyLow = rangeAxis.valueToJava2D(yLow, dataArea, edge);
616:                double yyOpen = rangeAxis.valueToJava2D(yOpen, dataArea, edge);
617:                double yyClose = rangeAxis
618:                        .valueToJava2D(yClose, dataArea, edge);
619:
620:                double volumeWidth;
621:                double stickWidth;
622:                if (this .candleWidth > 0) {
623:                    // These are deliberately not bounded to minimums/maxCandleWidth to
624:                    //  retain old behaviour.
625:                    volumeWidth = this .candleWidth;
626:                    stickWidth = this .candleWidth;
627:                } else {
628:                    double xxWidth = 0;
629:                    int itemCount;
630:                    switch (this .autoWidthMethod) {
631:
632:                    case WIDTHMETHOD_AVERAGE:
633:                        itemCount = highLowData.getItemCount(series);
634:                        if (horiz) {
635:                            xxWidth = dataArea.getHeight() / itemCount;
636:                        } else {
637:                            xxWidth = dataArea.getWidth() / itemCount;
638:                        }
639:                        break;
640:
641:                    case WIDTHMETHOD_SMALLEST:
642:                        // Note: It would be nice to pre-calculate this per series
643:                        itemCount = highLowData.getItemCount(series);
644:                        double lastPos = -1;
645:                        xxWidth = dataArea.getWidth();
646:                        for (int i = 0; i < itemCount; i++) {
647:                            double pos = domainAxis
648:                                    .valueToJava2D(highLowData.getXValue(
649:                                            series, i), dataArea, domainEdge);
650:                            if (lastPos != -1) {
651:                                xxWidth = Math.min(xxWidth, Math.abs(pos
652:                                        - lastPos));
653:                            }
654:                            lastPos = pos;
655:                        }
656:                        break;
657:
658:                    case WIDTHMETHOD_INTERVALDATA:
659:                        IntervalXYDataset intervalXYData = (IntervalXYDataset) dataset;
660:                        double startPos = domainAxis.valueToJava2D(
661:                                intervalXYData.getStartXValue(series, item),
662:                                dataArea, plot.getDomainAxisEdge());
663:                        double endPos = domainAxis.valueToJava2D(intervalXYData
664:                                .getEndXValue(series, item), dataArea, plot
665:                                .getDomainAxisEdge());
666:                        xxWidth = Math.abs(endPos - startPos);
667:                        break;
668:
669:                    }
670:                    xxWidth -= 2 * this .autoWidthGap;
671:                    xxWidth *= this .autoWidthFactor;
672:                    xxWidth = Math.min(xxWidth, this .maxCandleWidth);
673:                    volumeWidth = Math.max(Math.min(1, this .maxCandleWidth),
674:                            xxWidth);
675:                    stickWidth = Math.max(Math.min(3, this .maxCandleWidth),
676:                            xxWidth);
677:                }
678:
679:                Paint p = getItemPaint(series, item);
680:                Paint outlinePaint = null;
681:                if (this .useOutlinePaint) {
682:                    outlinePaint = getItemOutlinePaint(series, item);
683:                }
684:                Stroke s = getItemStroke(series, item);
685:
686:                g2.setStroke(s);
687:
688:                if (this .drawVolume) {
689:                    int volume = (int) highLowData.getVolumeValue(series, item);
690:                    double volumeHeight = volume / this .maxVolume;
691:
692:                    double min, max;
693:                    if (horiz) {
694:                        min = dataArea.getMinX();
695:                        max = dataArea.getMaxX();
696:                    } else {
697:                        min = dataArea.getMinY();
698:                        max = dataArea.getMaxY();
699:                    }
700:
701:                    double zzVolume = volumeHeight * (max - min);
702:
703:                    g2.setPaint(Color.gray);
704:                    Composite originalComposite = g2.getComposite();
705:                    g2.setComposite(AlphaComposite.getInstance(
706:                            AlphaComposite.SRC_OVER, 0.3f));
707:
708:                    if (horiz) {
709:                        g2.fill(new Rectangle2D.Double(min, xx - volumeWidth
710:                                / 2, zzVolume, volumeWidth));
711:                    } else {
712:                        g2.fill(new Rectangle2D.Double(xx - volumeWidth / 2,
713:                                max - zzVolume, volumeWidth, zzVolume));
714:                    }
715:
716:                    g2.setComposite(originalComposite);
717:                }
718:
719:                if (this .useOutlinePaint) {
720:                    g2.setPaint(outlinePaint);
721:                } else {
722:                    g2.setPaint(p);
723:                }
724:
725:                double yyMaxOpenClose = Math.max(yyOpen, yyClose);
726:                double yyMinOpenClose = Math.min(yyOpen, yyClose);
727:                double maxOpenClose = Math.max(yOpen, yClose);
728:                double minOpenClose = Math.min(yOpen, yClose);
729:
730:                // draw the upper shadow
731:                if (yHigh > maxOpenClose) {
732:                    if (horiz) {
733:                        g2.draw(new Line2D.Double(yyHigh, xx, yyMaxOpenClose,
734:                                xx));
735:                    } else {
736:                        g2.draw(new Line2D.Double(xx, yyHigh, xx,
737:                                yyMaxOpenClose));
738:                    }
739:                }
740:
741:                // draw the lower shadow
742:                if (yLow < minOpenClose) {
743:                    if (horiz) {
744:                        g2
745:                                .draw(new Line2D.Double(yyLow, xx,
746:                                        yyMinOpenClose, xx));
747:                    } else {
748:                        g2
749:                                .draw(new Line2D.Double(xx, yyLow, xx,
750:                                        yyMinOpenClose));
751:                    }
752:                }
753:
754:                // draw the body
755:                Shape body = null;
756:                if (horiz) {
757:                    body = new Rectangle2D.Double(yyMinOpenClose, xx
758:                            - stickWidth / 2, yyMaxOpenClose - yyMinOpenClose,
759:                            stickWidth);
760:                } else {
761:                    body = new Rectangle2D.Double(xx - stickWidth / 2,
762:                            yyMinOpenClose, stickWidth, yyMaxOpenClose
763:                                    - yyMinOpenClose);
764:                }
765:                if (yClose > yOpen) {
766:                    if (this .upPaint != null) {
767:                        g2.setPaint(this .upPaint);
768:                    } else {
769:                        g2.setPaint(p);
770:                    }
771:                    g2.fill(body);
772:                } else {
773:                    if (this .downPaint != null) {
774:                        g2.setPaint(this .downPaint);
775:                    } else {
776:                        g2.setPaint(p);
777:                    }
778:                    g2.fill(body);
779:                }
780:                if (this .useOutlinePaint) {
781:                    g2.setPaint(outlinePaint);
782:                } else {
783:                    g2.setPaint(p);
784:                }
785:                g2.draw(body);
786:
787:                // add an entity for the item...
788:                if (entities != null) {
789:                    String tip = null;
790:                    XYToolTipGenerator generator = getToolTipGenerator(series,
791:                            item);
792:                    if (generator != null) {
793:                        tip = generator.generateToolTip(dataset, series, item);
794:                    }
795:                    String url = null;
796:                    if (getURLGenerator() != null) {
797:                        url = getURLGenerator().generateURL(dataset, series,
798:                                item);
799:                    }
800:                    XYItemEntity entity = new XYItemEntity(body, dataset,
801:                            series, item, tip, url);
802:                    entities.add(entity);
803:                }
804:
805:            }
806:
807:            /**
808:             * Tests this renderer for equality with another object.
809:             *
810:             * @param obj  the object (<code>null</code> permitted).
811:             *
812:             * @return <code>true</code> or <code>false</code>.
813:             */
814:            public boolean equals(Object obj) {
815:                if (obj == this ) {
816:                    return true;
817:                }
818:                if (!(obj instanceof  CandlestickRenderer)) {
819:                    return false;
820:                }
821:                CandlestickRenderer that = (CandlestickRenderer) obj;
822:                if (this .candleWidth != that.candleWidth) {
823:                    return false;
824:                }
825:                if (!PaintUtilities.equal(this .upPaint, that.upPaint)) {
826:                    return false;
827:                }
828:                if (!PaintUtilities.equal(this .downPaint, that.downPaint)) {
829:                    return false;
830:                }
831:                if (this .drawVolume != that.drawVolume) {
832:                    return false;
833:                }
834:                if (this .maxCandleWidthInMilliseconds != that.maxCandleWidthInMilliseconds) {
835:                    return false;
836:                }
837:                if (this .autoWidthMethod != that.autoWidthMethod) {
838:                    return false;
839:                }
840:                if (this .autoWidthFactor != that.autoWidthFactor) {
841:                    return false;
842:                }
843:                if (this .autoWidthGap != that.autoWidthGap) {
844:                    return false;
845:                }
846:                if (this .useOutlinePaint != that.useOutlinePaint) {
847:                    return false;
848:                }
849:                return super .equals(obj);
850:            }
851:
852:            /**
853:             * Returns a clone of the renderer.
854:             * 
855:             * @return A clone.
856:             * 
857:             * @throws CloneNotSupportedException  if the renderer cannot be cloned.
858:             */
859:            public Object clone() throws CloneNotSupportedException {
860:                return super .clone();
861:            }
862:
863:            /**
864:             * Provides serialization support.
865:             *
866:             * @param stream  the output stream.
867:             *
868:             * @throws IOException  if there is an I/O error.
869:             */
870:            private void writeObject(ObjectOutputStream stream)
871:                    throws IOException {
872:                stream.defaultWriteObject();
873:                SerialUtilities.writePaint(this .upPaint, stream);
874:                SerialUtilities.writePaint(this .downPaint, stream);
875:            }
876:
877:            /**
878:             * Provides serialization support.
879:             *
880:             * @param stream  the input stream.
881:             *
882:             * @throws IOException  if there is an I/O error.
883:             * @throws ClassNotFoundException  if there is a classpath problem.
884:             */
885:            private void readObject(ObjectInputStream stream)
886:                    throws IOException, ClassNotFoundException {
887:                stream.defaultReadObject();
888:                this .upPaint = SerialUtilities.readPaint(stream);
889:                this .downPaint = SerialUtilities.readPaint(stream);
890:            }
891:
892:            // --- DEPRECATED CODE ----------------------------------------------------
893:
894:            /**
895:             * Returns a flag indicating whether or not volume bars are drawn on the
896:             * chart.
897:             *
898:             * @return <code>true</code> if volume bars are drawn on the chart.
899:             * 
900:             * @deprecated As of 1.0.5, you should use the {@link #getDrawVolume()} 
901:             *         method.
902:             */
903:            public boolean drawVolume() {
904:                return this.drawVolume;
905:            }
906:
907:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.