KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > xy > HighLowRenderer


1 /* ===========================================================
2  * JFreeChart : a free chart library for the Java(tm) platform
3  * ===========================================================
4  *
5  * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
6  *
7  * Project Info: http://www.jfree.org/jfreechart/index.html
8  *
9  * This library is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Lesser General Public License as published by
11  * the Free Software Foundation; either version 2.1 of the License, or
12  * (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22  * USA.
23  *
24  * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
25  * in the United States and other countries.]
26  *
27  * --------------------
28  * HighLowRenderer.java
29  * --------------------
30  * (C) Copyright 2001-2006, by Object Refinery Limited.
31  *
32  * Original Author: David Gilbert (for Object Refinery Limited);
33  * Contributor(s): Richard Atkinson;
34  * Christian W. Zuckschwerdt;
35  *
36  * $Id: HighLowRenderer.java,v 1.5.2.3 2006/07/06 10:03:34 mungady Exp $
37  *
38  * Changes
39  * -------
40  * 13-Dec-2001 : Version 1 (DG);
41  * 23-Jan-2002 : Added DrawInfo parameter to drawItem() method (DG);
42  * 28-Mar-2002 : Added a property change listener mechanism so that renderers
43  * no longer need to be immutable (DG);
44  * 09-Apr-2002 : Removed translatedRangeZero from the drawItem() method, and
45  * changed the return type of the drawItem method to void,
46  * reflecting a change in the XYItemRenderer interface. Added
47  * tooltip code to drawItem() method (DG);
48  * 05-Aug-2002 : Small modification to drawItem method to support URLs for
49  * HTML image maps (RA);
50  * 25-Mar-2003 : Implemented Serializable (DG);
51  * 01-May-2003 : Modified drawItem() method signature (DG);
52  * 30-Jul-2003 : Modified entity constructor (CZ);
53  * 31-Jul-2003 : Deprecated constructor (DG);
54  * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
55  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
56  * 29-Jan-2004 : Fixed bug (882392) when rendering with
57  * PlotOrientation.HORIZONTAL (DG);
58  * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState. Renamed
59  * XYToolTipGenerator --> XYItemLabelGenerator (DG);
60  * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
61  * getYValue() (DG);
62  * 01-Nov-2005 : Added optional openTickPaint and closeTickPaint settings (DG);
63  * ------------- JFREECHART 1.0.0 ---------------------------------------------
64  * 06-Jul-2006 : Replace dataset methods getX() --> getXValue() (DG);
65  *
66  */

67
68 package org.jfree.chart.renderer.xy;
69
70 import java.awt.Graphics2D JavaDoc;
71 import java.awt.Paint JavaDoc;
72 import java.awt.Shape JavaDoc;
73 import java.awt.Stroke JavaDoc;
74 import java.awt.geom.Line2D JavaDoc;
75 import java.awt.geom.Rectangle2D JavaDoc;
76 import java.io.IOException JavaDoc;
77 import java.io.ObjectInputStream JavaDoc;
78 import java.io.ObjectOutputStream JavaDoc;
79 import java.io.Serializable JavaDoc;
80
81 import org.jfree.chart.axis.ValueAxis;
82 import org.jfree.chart.entity.EntityCollection;
83 import org.jfree.chart.entity.XYItemEntity;
84 import org.jfree.chart.event.RendererChangeEvent;
85 import org.jfree.chart.labels.XYToolTipGenerator;
86 import org.jfree.chart.plot.CrosshairState;
87 import org.jfree.chart.plot.PlotOrientation;
88 import org.jfree.chart.plot.PlotRenderingInfo;
89 import org.jfree.chart.plot.XYPlot;
90 import org.jfree.data.xy.OHLCDataset;
91 import org.jfree.data.xy.XYDataset;
92 import org.jfree.io.SerialUtilities;
93 import org.jfree.ui.RectangleEdge;
94 import org.jfree.util.PaintUtilities;
95 import org.jfree.util.PublicCloneable;
96
97 /**
98  * A renderer that draws high/low/open/close markers on an {@link XYPlot}
99  * (requires a {@link OHLCDataset}). This renderer does not include code to
100  * calculate the crosshair point for the plot.
101  */

102 public class HighLowRenderer extends AbstractXYItemRenderer
103                              implements XYItemRenderer,
104                                         Cloneable JavaDoc,
105                                         PublicCloneable,
106                                         Serializable JavaDoc {
107     
108     /** For serialization. */
109     private static final long serialVersionUID = -8135673815876552516L;
110     
111     /** A flag that controls whether the open ticks are drawn. */
112     private boolean drawOpenTicks;
113
114     /** A flag that controls whether the close ticks are drawn. */
115     private boolean drawCloseTicks;
116     
117     /**
118      * The paint used for the open ticks (if <code>null</code>, the series
119      * paint is used instead).
120      */

121     private transient Paint JavaDoc openTickPaint;
122     
123     /**
124      * The paint used for the close ticks (if <code>null</code>, the series
125      * paint is used instead).
126      */

127     private transient Paint JavaDoc closeTickPaint;
128
129     /**
130      * The default constructor.
131      */

132     public HighLowRenderer() {
133         super();
134         this.drawOpenTicks = true;
135         this.drawCloseTicks = true;
136     }
137
138     /**
139      * Returns the flag that controls whether open ticks are drawn.
140      *
141      * @return A boolean.
142      */

143     public boolean getDrawOpenTicks() {
144         return this.drawOpenTicks;
145     }
146     
147     /**
148      * Sets the flag that controls whether open ticks are drawn, and sends a
149      * {@link RendererChangeEvent} to all registered listeners.
150      *
151      * @param draw the flag.
152      */

153     public void setDrawOpenTicks(boolean draw) {
154         this.drawOpenTicks = draw;
155         notifyListeners(new RendererChangeEvent(this));
156     }
157     
158     /**
159      * Returns the flag that controls whether close ticks are drawn.
160      *
161      * @return A boolean.
162      */

163     public boolean getDrawCloseTicks() {
164         return this.drawCloseTicks;
165     }
166     
167     /**
168      * Sets the flag that controls whether close ticks are drawn, and sends a
169      * {@link RendererChangeEvent} to all registered listeners.
170      *
171      * @param draw the flag.
172      */

173     public void setDrawCloseTicks(boolean draw) {
174         this.drawCloseTicks = draw;
175         notifyListeners(new RendererChangeEvent(this));
176     }
177     
178     /**
179      * Returns the paint used to draw the ticks for the open values.
180      *
181      * @return The paint used to draw the ticks for the open values (possibly
182      * <code>null</code>).
183      */

184     public Paint JavaDoc getOpenTickPaint() {
185         return this.openTickPaint;
186     }
187     
188     /**
189      * Sets the paint used to draw the ticks for the open values and sends a
190      * {@link RendererChangeEvent} to all registered listeners. If you set
191      * this to <code>null</code> (the default), the series paint is used
192      * instead.
193      *
194      * @param paint the paint (<code>null</code> permitted).
195      */

196     public void setOpenTickPaint(Paint JavaDoc paint) {
197         this.openTickPaint = paint;
198         notifyListeners(new RendererChangeEvent(this));
199     }
200     
201     /**
202      * Returns the paint used to draw the ticks for the close values.
203      *
204      * @return The paint used to draw the ticks for the close values (possibly
205      * <code>null</code>).
206      */

207     public Paint JavaDoc getCloseTickPaint() {
208         return this.closeTickPaint;
209     }
210     
211     /**
212      * Sets the paint used to draw the ticks for the close values and sends a
213      * {@link RendererChangeEvent} to all registered listeners. If you set
214      * this to <code>null</code> (the default), the series paint is used
215      * instead.
216      *
217      * @param paint the paint (<code>null</code> permitted).
218      */

219     public void setCloseTickPaint(Paint JavaDoc paint) {
220         this.closeTickPaint = paint;
221         notifyListeners(new RendererChangeEvent(this));
222     }
223     
224     /**
225      * Draws the visual representation of a single data item.
226      *
227      * @param g2 the graphics device.
228      * @param state the renderer state.
229      * @param dataArea the area within which the plot is being drawn.
230      * @param info collects information about the drawing.
231      * @param plot the plot (can be used to obtain standard color
232      * information etc).
233      * @param domainAxis the domain axis.
234      * @param rangeAxis the range axis.
235      * @param dataset the dataset.
236      * @param series the series index (zero-based).
237      * @param item the item index (zero-based).
238      * @param crosshairState crosshair information for the plot
239      * (<code>null</code> permitted).
240      * @param pass the pass index.
241      */

242     public void drawItem(Graphics2D JavaDoc g2,
243                          XYItemRendererState state,
244                          Rectangle2D JavaDoc dataArea,
245                          PlotRenderingInfo info,
246                          XYPlot plot,
247                          ValueAxis domainAxis,
248                          ValueAxis rangeAxis,
249                          XYDataset dataset,
250                          int series,
251                          int item,
252                          CrosshairState crosshairState,
253                          int pass) {
254
255         double x = dataset.getXValue(series, item);
256         if (!domainAxis.getRange().contains(x)) {
257             return; // the x value is not within the axis range
258
}
259         double xx = domainAxis.valueToJava2D(x, dataArea,
260                 plot.getDomainAxisEdge());
261         
262         // setup for collecting optional entity info...
263
Shape JavaDoc entityArea = null;
264         EntityCollection entities = null;
265         if (info != null) {
266             entities = info.getOwner().getEntityCollection();
267         }
268
269         PlotOrientation orientation = plot.getOrientation();
270         RectangleEdge location = plot.getRangeAxisEdge();
271
272         Paint JavaDoc itemPaint = getItemPaint(series, item);
273         Stroke JavaDoc itemStroke = getItemStroke(series, item);
274         g2.setPaint(itemPaint);
275         g2.setStroke(itemStroke);
276         
277         if (dataset instanceof OHLCDataset) {
278             OHLCDataset hld = (OHLCDataset) dataset;
279             
280             double yHigh = hld.getHighValue(series, item);
281             double yLow = hld.getLowValue(series, item);
282             if (!Double.isNaN(yHigh) && !Double.isNaN(yLow)) {
283                 double yyHigh = rangeAxis.valueToJava2D(yHigh, dataArea,
284                         location);
285                 double yyLow = rangeAxis.valueToJava2D(yLow, dataArea,
286                         location);
287                 if (orientation == PlotOrientation.HORIZONTAL) {
288                     g2.draw(new Line2D.Double JavaDoc(yyLow, xx, yyHigh, xx));
289                     entityArea = new Rectangle2D.Double JavaDoc(Math.min(yyLow, yyHigh),
290                             xx - 1.0, Math.abs(yyHigh - yyLow), 2.0);
291                 }
292                 else if (orientation == PlotOrientation.VERTICAL) {
293                     g2.draw(new Line2D.Double JavaDoc(xx, yyLow, xx, yyHigh));
294                     entityArea = new Rectangle2D.Double JavaDoc(xx - 1.0,
295                             Math.min(yyLow, yyHigh), 2.0,
296                             Math.abs(yyHigh - yyLow));
297                 }
298             }
299             
300             double delta = 2.0;
301             if (domainAxis.isInverted()) {
302                 delta = -delta;
303             }
304             if (getDrawOpenTicks()) {
305                 double yOpen = hld.getOpenValue(series, item);
306                 if (!Double.isNaN(yOpen)) {
307                     double yyOpen = rangeAxis.valueToJava2D(yOpen, dataArea,
308                             location);
309                     if (this.openTickPaint != null) {
310                         g2.setPaint(this.openTickPaint);
311                     }
312                     else {
313                         g2.setPaint(itemPaint);
314                     }
315                     if (orientation == PlotOrientation.HORIZONTAL) {
316                         g2.draw(new Line2D.Double JavaDoc(yyOpen, xx + delta, yyOpen,
317                                 xx));
318                     }
319                     else if (orientation == PlotOrientation.VERTICAL) {
320                         g2.draw(new Line2D.Double JavaDoc(xx - delta, yyOpen, xx,
321                                 yyOpen));
322                     }
323                 }
324             }
325             
326             if (getDrawCloseTicks()) {
327                 double yClose = hld.getCloseValue(series, item);
328                 if (!Double.isNaN(yClose)) {
329                     double yyClose = rangeAxis.valueToJava2D(
330                         yClose, dataArea, location);
331                     if (this.closeTickPaint != null) {
332                         g2.setPaint(this.closeTickPaint);
333                     }
334                     else {
335                         g2.setPaint(itemPaint);
336                     }
337                     if (orientation == PlotOrientation.HORIZONTAL) {
338                         g2.draw(new Line2D.Double JavaDoc(yyClose, xx, yyClose,
339                                 xx - delta));
340                     }
341                     else if (orientation == PlotOrientation.VERTICAL) {
342                         g2.draw(new Line2D.Double JavaDoc(xx, yyClose, xx + delta,
343                                 yyClose));
344                     }
345                 }
346             }
347   
348         }
349         else {
350             // not a HighLowDataset, so just draw a line connecting this point
351
// with the previous point...
352
if (item > 0) {
353                 double x0 = dataset.getXValue(series, item - 1);
354                 double y0 = dataset.getYValue(series, item - 1);
355                 double y = dataset.getYValue(series, item);
356                 if (Double.isNaN(x0) || Double.isNaN(y0) || Double.isNaN(y)) {
357                     return;
358                 }
359                 double xx0 = domainAxis.valueToJava2D(x0, dataArea,
360                         plot.getDomainAxisEdge());
361                 double yy0 = rangeAxis.valueToJava2D(y0, dataArea, location);
362                 double yy = rangeAxis.valueToJava2D(y, dataArea, location);
363                 if (orientation == PlotOrientation.HORIZONTAL) {
364                     g2.draw(new Line2D.Double JavaDoc(yy0, xx0, yy, xx));
365                 }
366                 else if (orientation == PlotOrientation.VERTICAL) {
367                     g2.draw(new Line2D.Double JavaDoc(xx0, yy0, xx, yy));
368                 }
369             }
370         }
371         
372         // add an entity for the item...
373
if (entities != null) {
374             String JavaDoc tip = null;
375             XYToolTipGenerator generator = getToolTipGenerator(series, item);
376             if (generator != null) {
377                 tip = generator.generateToolTip(dataset, series, item);
378             }
379             String JavaDoc url = null;
380             if (getURLGenerator() != null) {
381                 url = getURLGenerator().generateURL(dataset, series, item);
382             }
383             XYItemEntity entity = new XYItemEntity(entityArea, dataset,
384                     series, item, tip, url);
385             entities.add(entity);
386         }
387
388     }
389     
390     /**
391      * Returns a clone of the renderer.
392      *
393      * @return A clone.
394      *
395      * @throws CloneNotSupportedException if the renderer cannot be cloned.
396      */

397     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
398         return super.clone();
399     }
400     
401     /**
402      * Tests this renderer for equality with an arbitrary object.
403      *
404      * @param obj the object (<code>null</code> permitted).
405      *
406      * @return A boolean.
407      */

408     public boolean equals(Object JavaDoc obj) {
409         if (this == obj) {
410             return true;
411         }
412         if (!(obj instanceof HighLowRenderer)) {
413             return false;
414         }
415         HighLowRenderer that = (HighLowRenderer) obj;
416         if (this.drawOpenTicks != that.drawOpenTicks) {
417             return false;
418         }
419         if (this.drawCloseTicks != that.drawCloseTicks) {
420             return false;
421         }
422         if (!PaintUtilities.equal(this.openTickPaint, that.openTickPaint)) {
423             return false;
424         }
425         if (!PaintUtilities.equal(this.closeTickPaint, that.closeTickPaint)) {
426             return false;
427         }
428         if (!super.equals(obj)) {
429             return false;
430         }
431         return true;
432     }
433     
434     /**
435      * Provides serialization support.
436      *
437      * @param stream the input stream.
438      *
439      * @throws IOException if there is an I/O error.
440      * @throws ClassNotFoundException if there is a classpath problem.
441      */

442     private void readObject(ObjectInputStream JavaDoc stream)
443             throws IOException JavaDoc, ClassNotFoundException JavaDoc {
444         stream.defaultReadObject();
445         this.openTickPaint = SerialUtilities.readPaint(stream);
446         this.closeTickPaint = SerialUtilities.readPaint(stream);
447     }
448     
449     /**
450      * Provides serialization support.
451      *
452      * @param stream the output stream.
453      *
454      * @throws IOException if there is an I/O error.
455      */

456     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
457         stream.defaultWriteObject();
458         SerialUtilities.writePaint(this.openTickPaint, stream);
459         SerialUtilities.writePaint(this.closeTickPaint, stream);
460     }
461
462 }
463
Popular Tags