KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > MinMaxCategoryRenderer


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * ---------------------------
23  * MinMaxCategoryRenderer.java
24  * ---------------------------
25  * (C) Copyright 2002, 2003, by Object Refinery Limited.
26  *
27  * Original Author: Tomer Peretz;
28  * Contributor(s): David Gilbert (for Object Refinery Limited);
29  * Christian W. Zuckschwerdt;
30  * Nicolas Brodu (for Astrium and EADS Corporate Research Center);
31  *
32  * $Id: MinMaxCategoryRenderer.java,v 1.20 2003/11/03 14:21:27 mungady Exp $
33  *
34  * Changes:
35  * --------
36  * 29-May-2002 : Version 1 (TP);
37  * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
38  * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and CategoryToolTipGenerator
39  * interface (DG);
40  * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
41  * 17-Jan-2003 : Moved plot classes to a separate package (DG);
42  * 10-Apr-2003 : Changed CategoryDataset to KeyedValues2DDataset in drawItem(...) method (DG);
43  * 30-Jul-2003 : Modified entity constructor (CZ);
44  * 08-Sep-2003 : Implemented Serializable (NB);
45  * 29-Oct-2003 : Added workaround for font alignment in PDF output (DG);
46  *
47  */

48
49 package org.jfree.chart.renderer;
50
51 import java.awt.BasicStroke JavaDoc;
52 import java.awt.Color JavaDoc;
53 import java.awt.Component JavaDoc;
54 import java.awt.Graphics JavaDoc;
55 import java.awt.Graphics2D JavaDoc;
56 import java.awt.Paint JavaDoc;
57 import java.awt.Shape JavaDoc;
58 import java.awt.Stroke JavaDoc;
59 import java.awt.geom.AffineTransform JavaDoc;
60 import java.awt.geom.Arc2D JavaDoc;
61 import java.awt.geom.GeneralPath JavaDoc;
62 import java.awt.geom.Line2D JavaDoc;
63 import java.awt.geom.Rectangle2D JavaDoc;
64 import java.io.IOException JavaDoc;
65 import java.io.ObjectInputStream JavaDoc;
66 import java.io.ObjectOutputStream JavaDoc;
67
68 import javax.swing.Icon JavaDoc;
69
70 import org.jfree.chart.Marker;
71 import org.jfree.chart.axis.CategoryAxis;
72 import org.jfree.chart.axis.ValueAxis;
73 import org.jfree.chart.entity.CategoryItemEntity;
74 import org.jfree.chart.entity.EntityCollection;
75 import org.jfree.chart.labels.CategoryItemLabelGenerator;
76 import org.jfree.chart.plot.CategoryPlot;
77 import org.jfree.data.CategoryDataset;
78 import org.jfree.data.Range;
79 import org.jfree.io.SerialUtilities;
80
81 /**
82  * Renderer for drawing min max plot. This renderer draws all the series under the same category
83  * in the same x position using <code>objectIcon</code> and a line from the maximum value to the
84  * minimum value.
85  * <p>
86  * For use with the {@link org.jfree.chart.plot.CategoryPlot} class.
87  *
88  * @author Tomer Peretz
89  */

90 public class MinMaxCategoryRenderer extends AbstractCategoryItemRenderer {
91
92     /** A flag indicating whether or not lines are drawn between XY points. */
93     private boolean plotLines = false;
94
95     /** The paint of the line between the minimum value and the maximum value.*/
96     private transient Paint JavaDoc groupPaint = Color.black;
97
98     /** The stroke of the line between the minimum value and the maximum value.*/
99     private transient Stroke JavaDoc groupStroke = new BasicStroke JavaDoc(1.0f);
100
101     /** The icon used to indicate the minimum value.*/
102     private transient Icon JavaDoc minIcon = getIcon(new Arc2D.Double JavaDoc(-4, -4, 8, 8, 0, 360, Arc2D.OPEN),
103                                              null, Color.black);
104
105     /** The icon used to indicate the maximum value.*/
106     private transient Icon JavaDoc maxIcon = getIcon(new Arc2D.Double JavaDoc(-4, -4, 8, 8, 0, 360, Arc2D.OPEN),
107                                              null, Color.black);
108
109     /** The icon used to indicate the values.*/
110     private transient Icon JavaDoc objectIcon = getIcon(new Line2D.Double JavaDoc(-4, 0, 4, 0), false, true);
111
112     /** The last category. */
113     private int lastCategory = -1;
114
115     /** The minimum. */
116     private double min;
117
118     /** The maximum. */
119     private double max;
120
121     /** The minimum number. */
122     private Number JavaDoc minValue;
123
124     /** The maximum number. */
125     private Number JavaDoc maxValue;
126
127     /**
128      * Default constructor.
129      */

130     public MinMaxCategoryRenderer () {
131     }
132
133     /**
134      * Draw a single data item.
135      *
136      * @param g2 the graphics device.
137      * @param state the renderer state.
138      * @param dataArea the area in which the data is drawn.
139      * @param plot the plot.
140      * @param domainAxis the domain axis.
141      * @param rangeAxis the range axis.
142      * @param dataset the dataset.
143      * @param row the row index (zero-based).
144      * @param column the column index (zero-based).
145      */

146     public void drawItem (Graphics2D JavaDoc g2,
147                           CategoryItemRendererState state,
148                           Rectangle2D JavaDoc dataArea,
149                           CategoryPlot plot,
150                           CategoryAxis domainAxis,
151                           ValueAxis rangeAxis,
152                           CategoryDataset dataset,
153                           int row,
154                           int column) {
155
156         // first check the number we are plotting...
157
Number JavaDoc value = dataset.getValue(row, column);
158         if (value != null) {
159             // current data point...
160
double x1 = domainAxis.getCategoryMiddle(column, getColumnCount(), dataArea,
161                                                      plot.getDomainAxisEdge());
162             double y1 = rangeAxis.translateValueToJava2D(value.doubleValue(), dataArea,
163                                                          plot.getRangeAxisEdge());
164             g2.setPaint(getItemPaint(row, column));
165             g2.setStroke(getItemStroke(row, column));
166             Shape JavaDoc shape = null;
167             shape = new Rectangle2D.Double JavaDoc(x1 - 4, y1 - 4, 8.0, 8.0);
168             objectIcon.paintIcon(null, g2, (int) x1, (int) y1);
169             if (lastCategory == column) {
170                 if (minValue.doubleValue() > value.doubleValue()) {
171                     min = y1;
172                     minValue = value;
173                 }
174                 if (maxValue.doubleValue() < value.doubleValue()) {
175                     max = y1;
176                     maxValue = value;
177                 }
178                 if (dataset.getRowCount() - 1 == row) {
179                     g2.setPaint(groupPaint);
180                     g2.setStroke(groupStroke);
181                     g2.draw(new Line2D.Double JavaDoc(x1, min, x1, max));
182                     minIcon.paintIcon(null, g2, (int) x1, (int) min);
183                     maxIcon.paintIcon(null, g2, (int) x1, (int) max);
184 // if (isItemLabelVisible(row, column)) {
185
// NumberFormat formatter = getValueLabelFormatter();
186
// Font labelFont = getValueLabelFont();
187
// g2.setFont(labelFont);
188
// Paint paint = getValueLabelPaint();
189
// g2.setPaint(paint);
190
// boolean rotate = getVerticalValueLabels();
191
// drawLabel(g2, formatter.format(minValue), x1, min,
192
// labelFont, rotate, LineAndShapeRenderer.BOTTOM);
193
// drawLabel(g2, formatter.format(maxValue), x1, max,
194
// labelFont, rotate, LineAndShapeRenderer.TOP);
195
// }
196
}
197             }
198             else {
199                 lastCategory = column;
200                 min = y1;
201                 max = y1;
202                 minValue = value;
203                 maxValue = value;
204             }
205             // connect to the previous point
206
if (this.plotLines) {
207                 if (column != 0) {
208                     Number JavaDoc previousValue = dataset.getValue(row, column - 1);
209                     if (previousValue != null) {
210                         // previous data point...
211
double previous = previousValue.doubleValue();
212                         double x0 = domainAxis.getCategoryStart(column - 1, getColumnCount(),
213                                                                 dataArea,
214                                                                 plot.getDomainAxisEdge());
215                         double y0 = rangeAxis.translateValueToJava2D(previous, dataArea,
216                                                                      plot.getRangeAxisEdge());
217                         g2.setPaint(getItemPaint(row, column));
218                         g2.setStroke(getItemStroke(row, column));
219                         Line2D JavaDoc line = new Line2D.Double JavaDoc(x0, y0, x1, y1);
220                         g2.draw(line);
221                     }
222                 }
223             }
224
225             // collect entity and tool tip information...
226
if (state.getInfo() != null) {
227                 EntityCollection entities = state.getInfo().getOwner().getEntityCollection();
228                 if (entities != null && shape != null) {
229                     String JavaDoc tip = null;
230                     CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column);
231                     if (generator != null) {
232                         tip = generator.generateToolTip(dataset, row, column);
233                     }
234                     CategoryItemEntity entity = new CategoryItemEntity(
235                         shape, tip, null, dataset, row, dataset.getColumnKey(column), column);
236                     entities.addEntity(entity);
237                 }
238             }
239         }
240     }
241
242 // /**
243
// * Draws a value label on the plot.
244
// *
245
// * @param g2 the graphics device.
246
// * @param label the label text.
247
// * @param x the x position of the data point.
248
// * @param y the y position of the data point.
249
// * @param labelFont the font to draw the label with.
250
// * @param rotate true if the label is to be rotated 90 degrees, false otherwise
251
// * @param labelPosition the position of the label
252
// */
253
// private void drawLabel (Graphics2D g2, String label, double x, double y,
254
// Font labelFont, boolean rotate, int labelPosition) {
255
//
256
// FontMetrics fm = g2.getFontMetrics(labelFont);
257
// Rectangle2D labelBounds = fm.getStringBounds(label, g2);
258
// LineMetrics lm = labelFont.getLineMetrics(label, g2.getFontRenderContext());
259
// float lead = lm.getLeading();
260
// double width = labelBounds.getWidth();
261
// double height = labelBounds.getHeight();
262
// float labelx;
263
// float labely;
264
// int position = labelPosition;
265
// if (rotate) {
266
// if (position == LineAndShapeRenderer.TOP) {
267
// labelx = (float) (x + height / 2 - lm.getDescent());
268
// labely = (float) (y - shapeScale);
269
// }
270
// else if (position == LineAndShapeRenderer.BOTTOM) {
271
// labelx = (float) (x + height / 2 - lm.getDescent());
272
// labely = (float) (y + shapeScale + width);
273
// }
274
// else if (position == LineAndShapeRenderer.LEFT) {
275
// labelx = (float) (x - shapeScale / 2 - lead - lm.getDescent());
276
// labely = (float) (y + width / 2);
277
// }
278
// else {
279
// labelx = (float) (x + shapeScale / 2 + lead + lm.getAscent());
280
// labely = (float) (y + width / 2);
281
// }
282
// RefineryUtilities.drawRotatedString(label, g2, labelx, labely, -Math.PI / 2);
283
// }
284
// else {
285
// if (position == LineAndShapeRenderer.TOP) {
286
// labelx = (float) (x - width / 2);
287
// labely = (float) (y - shapeScale / 2 - lm.getDescent() - lead);
288
// }
289
// else if (position == LineAndShapeRenderer.BOTTOM) {
290
// labelx = (float) (x - width / 2);
291
// labely = (float) (y + shapeScale / 2 + lm.getAscent() + lead);
292
// }
293
// else if (position == LineAndShapeRenderer.LEFT) {
294
// labelx = (float) (x - shapeScale - width);
295
// labely = (float) (y + height / 2 - lm.getDescent());
296
// }
297
// else {
298
// labelx = (float) (x + shapeScale);
299
// labely = (float) (y + height / 2 - lm.getDescent());
300
// }
301
// g2.drawString(label, labelx, labely);
302
// }
303
// }
304

305     /**
306      * Draws a horizontal line across the chart to represent the marker.
307      *
308      * @param g2 the graphics device.
309      * @param plot the plot.
310      * @param axis the value axis.
311      * @param marker the marker line.
312      * @param axisDataArea the axis data area.
313      * @param dataClipRegion the data clip region.
314      */

315     public void drawRangeMarker (Graphics2D JavaDoc g2, CategoryPlot plot, ValueAxis axis,
316                                  Marker marker, Rectangle2D JavaDoc axisDataArea, Shape JavaDoc dataClipRegion) {
317         double value = marker.getValue();
318         Range range = axis.getRange();
319         if (!range.contains(value)) {
320             return;
321         }
322         double y = axis.translateValueToJava2D(marker.getValue(), axisDataArea,
323                                                plot.getRangeAxisEdge());
324         Line2D JavaDoc line = new Line2D.Double JavaDoc(axisDataArea.getMinX(), y, axisDataArea.getMaxX(), y);
325         g2.setPaint(marker.getOutlinePaint());
326         g2.draw(line);
327     }
328
329     /**
330      * Sets whether or not lines are drawn between category points.
331      *
332      * @param drawLines if true, then line will be drawn between sequenced categories.
333      */

334     public void setDrawLines (boolean drawLines) {
335         this.plotLines = drawLines;
336     }
337
338     /**
339      * Gets whether or not lines are drawn between category points.
340      *
341      * @return boolean true if line will be drawn between sequenced categories, otherwise false.
342      */

343     public boolean isDrawLines () {
344         return plotLines;
345     }
346
347     /**
348      * Sets the paint of the line between the minimum value and the maximum value.
349      *
350      * @param groupPaint the new paint.
351      */

352     public void setGroupPaint (Paint JavaDoc groupPaint) {
353         this.groupPaint = groupPaint;
354     }
355
356     /**
357      * Gets the paint of the line between the minimum value and the maximum value.
358      *
359      * @return the paint.
360      */

361     public Paint JavaDoc getGroupPaint () {
362         return groupPaint;
363     }
364
365     /**
366      * Sets the stroke of the line between the minimum value and the maximum value.
367      *
368      * @param groupStroke The new stroke
369      */

370     public void setGroupStroke (Stroke JavaDoc groupStroke) {
371         this.groupStroke = groupStroke;
372     }
373
374     /**
375      * Gets the stroke of the line between the minimum value and the maximum value.
376      *
377      * @return Stroke The current stroke.
378      */

379     public Stroke JavaDoc getGroupStroke () {
380         return groupStroke;
381     }
382
383     /**
384      * Sets the icon used to indicate the values.
385      *
386      * @param objectIcon the icon.
387      */

388     public void setObjectIcon (Icon JavaDoc objectIcon) {
389         this.objectIcon = objectIcon;
390     }
391
392     /**
393      * Gets the icon used to indicate the values.
394      *
395      * @return the icon.
396      */

397     public Icon JavaDoc getObjectIcon () {
398         return objectIcon;
399     }
400
401     /**
402      * Sets the icon used to indicate the maximum value.
403      *
404      * @param maxIcon the max icon.
405      */

406     public void setMaxIcon (Icon JavaDoc maxIcon) {
407         this.maxIcon = maxIcon;
408     }
409
410     /**
411      * Gets the icon used to indicate the maximum value.
412      *
413      * @return the icon
414      */

415     public Icon JavaDoc getMaxIcone () {
416         return maxIcon;
417     }
418
419     /**
420      * Sets the icon used to indicate the minimum value.
421      *
422      * @param minIcon the min icon.
423      */

424     public void setMinIcon (Icon JavaDoc minIcon) {
425         this.minIcon = minIcon;
426     }
427
428     /**
429      * Gets the icon used to indicate the minimum value.
430      *
431      * @return Icon
432      */

433     public Icon JavaDoc getMinIcon () {
434         return minIcon;
435     }
436
437     /**
438      * Returns an icon.
439      *
440      * @param shape the shape.
441      * @param fillPaint the fill paint.
442      * @param outlinePaint the outline paint.
443      *
444      * @return the icon.
445      */

446     private Icon JavaDoc getIcon(Shape JavaDoc shape, final Paint JavaDoc fillPaint, final Paint JavaDoc outlinePaint) {
447
448       final int width = shape.getBounds().width;
449       final int height = shape.getBounds().height;
450       final GeneralPath JavaDoc path = new GeneralPath JavaDoc(shape);
451       return new Icon JavaDoc() {
452           public void paintIcon(Component JavaDoc c, Graphics JavaDoc g, int x, int y) {
453               Graphics2D JavaDoc g2 = (Graphics2D JavaDoc) g;
454               path.transform(AffineTransform.getTranslateInstance(x, y));
455               if (fillPaint != null) {
456                   g2.setPaint(fillPaint);
457                   g2.fill(path);
458               }
459               if (outlinePaint != null) {
460                   g2.setPaint(outlinePaint);
461                   g2.draw(path);
462               }
463               path.transform(AffineTransform.getTranslateInstance(-x, -y));
464         }
465
466         public int getIconWidth() {
467             return width;
468         }
469
470         public int getIconHeight() {
471             return height;
472         }
473
474       };
475     }
476
477     /**
478      * Returns an icon.
479      *
480      * @param shape the shape.
481      * @param fill the fill flag.
482      * @param outline the outline flag.
483      *
484      * @return the icon.
485      */

486     private Icon JavaDoc getIcon(Shape JavaDoc shape, final boolean fill, final boolean outline) {
487         final int width = shape.getBounds().width;
488         final int height = shape.getBounds().height;
489         final GeneralPath JavaDoc path = new GeneralPath JavaDoc(shape);
490         return new Icon JavaDoc() {
491             public void paintIcon(Component JavaDoc c, Graphics JavaDoc g, int x, int y) {
492                 Graphics2D JavaDoc g2 = (Graphics2D JavaDoc) g;
493                 path.transform(AffineTransform.getTranslateInstance(x, y));
494                 if (fill) {
495                     g2.fill(path);
496                 }
497                 if (outline) {
498                     g2.draw(path);
499                 }
500                 path.transform(AffineTransform.getTranslateInstance(-x, -y));
501             }
502
503             public int getIconWidth() {
504                 return width;
505             }
506
507             public int getIconHeight() {
508                 return height;
509             }
510         };
511     }
512     
513     /**
514      * Provides serialization support.
515      *
516      * @param stream the output stream.
517      *
518      * @throws IOException if there is an I/O error.
519      */

520     private void writeObject(ObjectOutputStream JavaDoc stream) throws IOException JavaDoc {
521         stream.defaultWriteObject();
522         SerialUtilities.writeStroke(this.groupStroke, stream);
523         SerialUtilities.writePaint(this.groupPaint, stream);
524     }
525     
526     /**
527      * Provides serialization support.
528      *
529      * @param stream the input stream.
530      *
531      * @throws IOException if there is an I/O error.
532      * @throws ClassNotFoundException if there is a classpath problem.
533      */

534     private void readObject(ObjectInputStream JavaDoc stream) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
535         stream.defaultReadObject();
536         this.groupStroke = SerialUtilities.readStroke(stream);
537         this.groupPaint = SerialUtilities.readPaint(stream);
538           
539         minIcon = getIcon(new Arc2D.Double JavaDoc(-4, -4, 8, 8, 0, 360, Arc2D.OPEN), null, Color.black);
540         maxIcon = getIcon(new Arc2D.Double JavaDoc(-4, -4, 8, 8, 0, 360, Arc2D.OPEN), null, Color.black);
541         objectIcon = getIcon(new Line2D.Double JavaDoc(-4, 0, 4, 0), false, true);
542     }
543     
544 }
545
Popular Tags