KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > category > LineRenderer3D


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  * LineRenderer3D.java
29  * -------------------
30  * (C) Copyright 2004-2006, by Tobias Selb and Contributors.
31  *
32  * Original Author: Tobias Selb;
33  * Contributor(s): David Gilbert (for Object Refinery Limited);
34  *
35  * $Id: LineRenderer3D.java,v 1.10.2.5 2006/08/04 11:30:39 mungady Exp $
36  *
37  * Changes
38  * -------
39  * 15-Oct-2004 : Version 1 (TS);
40  * 05-Nov-2004 : Modified drawItem() signature (DG);
41  * 11-Nov-2004 : Now uses ShapeUtilities class to translate shapes (DG);
42  * 26-Jan-2005 : Update for changes in super class (DG);
43  * 13-Apr-2005 : Check item visibility in drawItem() method (DG);
44  * 09-Jun-2005 : Use addItemEntity() in drawItem() method (DG);
45  * 10-Jun-2005 : Fixed capitalisation of setXOffset() and setYOffset() (DG);
46  *
47  */

48
49 package org.jfree.chart.renderer.category;
50
51 import java.awt.AlphaComposite JavaDoc;
52 import java.awt.Color JavaDoc;
53 import java.awt.Composite JavaDoc;
54 import java.awt.Graphics2D JavaDoc;
55 import java.awt.Image JavaDoc;
56 import java.awt.Paint JavaDoc;
57 import java.awt.Shape JavaDoc;
58 import java.awt.Stroke JavaDoc;
59 import java.awt.geom.GeneralPath JavaDoc;
60 import java.awt.geom.Line2D JavaDoc;
61 import java.awt.geom.Rectangle2D JavaDoc;
62 import java.io.Serializable JavaDoc;
63
64 import org.jfree.chart.Effect3D;
65 import org.jfree.chart.axis.CategoryAxis;
66 import org.jfree.chart.axis.ValueAxis;
67 import org.jfree.chart.entity.EntityCollection;
68 import org.jfree.chart.event.RendererChangeEvent;
69 import org.jfree.chart.plot.CategoryPlot;
70 import org.jfree.chart.plot.Marker;
71 import org.jfree.chart.plot.PlotOrientation;
72 import org.jfree.chart.plot.ValueMarker;
73 import org.jfree.data.Range;
74 import org.jfree.data.category.CategoryDataset;
75 import org.jfree.util.ShapeUtilities;
76
77 /**
78  * A line renderer with a 3D effect.
79  *
80  * @author Tobias Selb (http://www.uepselon.com)
81  */

82 public class LineRenderer3D extends LineAndShapeRenderer
83                             implements Effect3D, Serializable JavaDoc {
84    
85     /** For serialization. */
86     private static final long serialVersionUID = 5467931468380928736L;
87     
88     /** The default x-offset for the 3D effect. */
89     public static final double DEFAULT_X_OFFSET = 12.0;
90
91     /** The default y-offset for the 3D effect. */
92     public static final double DEFAULT_Y_OFFSET = 8.0;
93    
94     /** The default wall paint. */
95     public static final Paint JavaDoc DEFAULT_WALL_PAINT = new Color JavaDoc(0xDD, 0xDD, 0xDD);
96    
97     /** The size of x-offset for the 3D effect. */
98     private double xOffset;
99
100     /** The size of y-offset for the 3D effect. */
101     private double yOffset;
102    
103     /** The paint used to shade the left and lower 3D wall. */
104     private transient Paint JavaDoc wallPaint;
105    
106     /**
107      * Creates a new renderer.
108      */

109     public LineRenderer3D() {
110         super(true, false); //Create a line renderer only
111
this.xOffset = DEFAULT_X_OFFSET;
112         this.yOffset = DEFAULT_Y_OFFSET;
113         this.wallPaint = DEFAULT_WALL_PAINT;
114     }
115    
116     /**
117      * Returns the x-offset for the 3D effect.
118      *
119      * @return The x-offset.
120      */

121     public double getXOffset() {
122         return this.xOffset;
123     }
124
125     /**
126      * Returns the y-offset for the 3D effect.
127      *
128      * @return The y-offset.
129      */

130     public double getYOffset() {
131         return this.yOffset;
132     }
133    
134     /**
135      * Sets the x-offset.
136      *
137      * @param xOffset the x-offset.
138      */

139     public void setXOffset(double xOffset) {
140         this.xOffset = xOffset;
141         notifyListeners(new RendererChangeEvent(this));
142     }
143
144     /**
145      * Sets the y-offset.
146      *
147      * @param yOffset the y-offset.
148      */

149     public void setYOffset(double yOffset) {
150         this.yOffset = yOffset;
151         notifyListeners(new RendererChangeEvent(this));
152     }
153
154     /**
155      * Returns the paint used to highlight the left and bottom wall in the plot
156      * background.
157      *
158      * @return The paint.
159      */

160     public Paint JavaDoc getWallPaint() {
161         return this.wallPaint;
162     }
163
164     /**
165      * Sets the paint used to hightlight the left and bottom walls in the plot
166      * background.
167      *
168      * @param paint the paint.
169      */

170     public void setWallPaint(Paint JavaDoc paint) {
171         this.wallPaint = paint;
172         notifyListeners(new RendererChangeEvent(this));
173     }
174    
175     /**
176      * Draws the background for the plot.
177      *
178      * @param g2 the graphics device.
179      * @param plot the plot.
180      * @param dataArea the area inside the axes.
181      */

182     public void drawBackground(Graphics2D JavaDoc g2, CategoryPlot plot,
183                                Rectangle2D JavaDoc dataArea) {
184
185         float x0 = (float) dataArea.getX();
186         float x1 = x0 + (float) Math.abs(this.xOffset);
187         float x3 = (float) dataArea.getMaxX();
188         float x2 = x3 - (float) Math.abs(this.xOffset);
189
190         float y0 = (float) dataArea.getMaxY();
191         float y1 = y0 - (float) Math.abs(this.yOffset);
192         float y3 = (float) dataArea.getMinY();
193         float y2 = y3 + (float) Math.abs(this.yOffset);
194
195         GeneralPath JavaDoc clip = new GeneralPath JavaDoc();
196         clip.moveTo(x0, y0);
197         clip.lineTo(x0, y2);
198         clip.lineTo(x1, y3);
199         clip.lineTo(x3, y3);
200         clip.lineTo(x3, y1);
201         clip.lineTo(x2, y0);
202         clip.closePath();
203
204         // fill background...
205
Paint JavaDoc backgroundPaint = plot.getBackgroundPaint();
206         if (backgroundPaint != null) {
207             g2.setPaint(backgroundPaint);
208             g2.fill(clip);
209         }
210
211         GeneralPath JavaDoc leftWall = new GeneralPath JavaDoc();
212         leftWall.moveTo(x0, y0);
213         leftWall.lineTo(x0, y2);
214         leftWall.lineTo(x1, y3);
215         leftWall.lineTo(x1, y1);
216         leftWall.closePath();
217         g2.setPaint(getWallPaint());
218         g2.fill(leftWall);
219
220         GeneralPath JavaDoc bottomWall = new GeneralPath JavaDoc();
221         bottomWall.moveTo(x0, y0);
222         bottomWall.lineTo(x1, y1);
223         bottomWall.lineTo(x3, y1);
224         bottomWall.lineTo(x2, y0);
225         bottomWall.closePath();
226         g2.setPaint(getWallPaint());
227         g2.fill(bottomWall);
228
229         // higlight the background corners...
230
g2.setPaint(Color.lightGray);
231         Line2D JavaDoc corner = new Line2D.Double JavaDoc(x0, y0, x1, y1);
232         g2.draw(corner);
233         corner.setLine(x1, y1, x1, y3);
234         g2.draw(corner);
235         corner.setLine(x1, y1, x3, y1);
236         g2.draw(corner);
237
238         // draw background image, if there is one...
239
Image JavaDoc backgroundImage = plot.getBackgroundImage();
240         if (backgroundImage != null) {
241             Composite JavaDoc originalComposite = g2.getComposite();
242             g2.setComposite(AlphaComposite.getInstance(
243                     AlphaComposite.SRC, plot.getBackgroundAlpha()));
244             g2.drawImage(backgroundImage, (int) x1, (int) y3,
245                     (int) (x3 - x1 + 1), (int) (y1 - y3 + 1), null);
246             g2.setComposite(originalComposite);
247         }
248
249     }
250
251     /**
252      * Draws the outline for the plot.
253      *
254      * @param g2 the graphics device.
255      * @param plot the plot.
256      * @param dataArea the area inside the axes.
257      */

258     public void drawOutline(Graphics2D JavaDoc g2, CategoryPlot plot,
259                             Rectangle2D JavaDoc dataArea) {
260
261         float x0 = (float) dataArea.getX();
262         float x1 = x0 + (float) Math.abs(this.xOffset);
263         float x3 = (float) dataArea.getMaxX();
264         float x2 = x3 - (float) Math.abs(this.xOffset);
265
266         float y0 = (float) dataArea.getMaxY();
267         float y1 = y0 - (float) Math.abs(this.yOffset);
268         float y3 = (float) dataArea.getMinY();
269         float y2 = y3 + (float) Math.abs(this.yOffset);
270
271         GeneralPath JavaDoc clip = new GeneralPath JavaDoc();
272         clip.moveTo(x0, y0);
273         clip.lineTo(x0, y2);
274         clip.lineTo(x1, y3);
275         clip.lineTo(x3, y3);
276         clip.lineTo(x3, y1);
277         clip.lineTo(x2, y0);
278         clip.closePath();
279
280         // put an outline around the data area...
281
Stroke JavaDoc outlineStroke = plot.getOutlineStroke();
282         Paint JavaDoc outlinePaint = plot.getOutlinePaint();
283         if ((outlineStroke != null) && (outlinePaint != null)) {
284             g2.setStroke(outlineStroke);
285             g2.setPaint(outlinePaint);
286             g2.draw(clip);
287         }
288
289     }
290
291     /**
292      * Draws a grid line against the domain axis.
293      *
294      * @param g2 the graphics device.
295      * @param plot the plot.
296      * @param dataArea the area for plotting data (not yet adjusted for any
297      * 3D effect).
298      * @param value the Java2D value at which the grid line should be drawn.
299      *
300      */

301     public void drawDomainGridline(Graphics2D JavaDoc g2,
302                                    CategoryPlot plot,
303                                    Rectangle2D JavaDoc dataArea,
304                                    double value) {
305
306         Line2D JavaDoc line1 = null;
307         Line2D JavaDoc line2 = null;
308         PlotOrientation orientation = plot.getOrientation();
309         if (orientation == PlotOrientation.HORIZONTAL) {
310             double y0 = value;
311             double y1 = value - getYOffset();
312             double x0 = dataArea.getMinX();
313             double x1 = x0 + getXOffset();
314             double x2 = dataArea.getMaxY();
315             line1 = new Line2D.Double JavaDoc(x0, y0, x1, y1);
316             line2 = new Line2D.Double JavaDoc(x1, y1, x2, y1);
317         }
318         else if (orientation == PlotOrientation.VERTICAL) {
319             double x0 = value;
320             double x1 = value + getXOffset();
321             double y0 = dataArea.getMaxY();
322             double y1 = y0 - getYOffset();
323             double y2 = dataArea.getMinY();
324             line1 = new Line2D.Double JavaDoc(x0, y0, x1, y1);
325             line2 = new Line2D.Double JavaDoc(x1, y1, x1, y2);
326         }
327         g2.setPaint(plot.getDomainGridlinePaint());
328         g2.setStroke(plot.getDomainGridlineStroke());
329         g2.draw(line1);
330         g2.draw(line2);
331
332     }
333
334     /**
335      * Draws a grid line against the range axis.
336      *
337      * @param g2 the graphics device.
338      * @param plot the plot.
339      * @param axis the value axis.
340      * @param dataArea the area for plotting data (not yet adjusted for any
341      * 3D effect).
342      * @param value the value at which the grid line should be drawn.
343      *
344      */

345     public void drawRangeGridline(Graphics2D JavaDoc g2,
346                                   CategoryPlot plot,
347                                   ValueAxis axis,
348                                   Rectangle2D JavaDoc dataArea,
349                                   double value) {
350
351         Range range = axis.getRange();
352
353         if (!range.contains(value)) {
354             return;
355         }
356
357         Rectangle2D JavaDoc adjusted = new Rectangle2D.Double JavaDoc(dataArea.getX(),
358                 dataArea.getY() + getYOffset(),
359                 dataArea.getWidth() - getXOffset(),
360                 dataArea.getHeight() - getYOffset());
361
362         Line2D JavaDoc line1 = null;
363         Line2D JavaDoc line2 = null;
364         PlotOrientation orientation = plot.getOrientation();
365         if (orientation == PlotOrientation.HORIZONTAL) {
366             double x0 = axis.valueToJava2D(value, adjusted,
367                     plot.getRangeAxisEdge());
368             double x1 = x0 + getXOffset();
369             double y0 = dataArea.getMaxY();
370             double y1 = y0 - getYOffset();
371             double y2 = dataArea.getMinY();
372             line1 = new Line2D.Double JavaDoc(x0, y0, x1, y1);
373             line2 = new Line2D.Double JavaDoc(x1, y1, x1, y2);
374         }
375         else if (orientation == PlotOrientation.VERTICAL) {
376             double y0 = axis.valueToJava2D(value, adjusted,
377                     plot.getRangeAxisEdge());
378             double y1 = y0 - getYOffset();
379             double x0 = dataArea.getMinX();
380             double x1 = x0 + getXOffset();
381             double x2 = dataArea.getMaxX();
382             line1 = new Line2D.Double JavaDoc(x0, y0, x1, y1);
383             line2 = new Line2D.Double JavaDoc(x1, y1, x2, y1);
384         }
385         g2.setPaint(plot.getRangeGridlinePaint());
386         g2.setStroke(plot.getRangeGridlineStroke());
387         g2.draw(line1);
388         g2.draw(line2);
389
390     }
391
392     /**
393      * Draws a range marker.
394      *
395      * @param g2 the graphics device.
396      * @param plot the plot.
397      * @param axis the value axis.
398      * @param marker the marker.
399      * @param dataArea the area for plotting data (not including 3D effect).
400      */

401     public void drawRangeMarker(Graphics2D JavaDoc g2,
402                                 CategoryPlot plot,
403                                 ValueAxis axis,
404                                 Marker marker,
405                                 Rectangle2D JavaDoc dataArea) {
406
407         if (marker instanceof ValueMarker) {
408             ValueMarker vm = (ValueMarker) marker;
409             double value = vm.getValue();
410             Range range = axis.getRange();
411             if (!range.contains(value)) {
412                 return;
413             }
414
415             Rectangle2D JavaDoc adjusted = new Rectangle2D.Double JavaDoc(dataArea.getX(),
416                     dataArea.getY() + getYOffset(),
417                     dataArea.getWidth() - getXOffset(),
418                     dataArea.getHeight() - getYOffset());
419
420             GeneralPath JavaDoc path = null;
421             PlotOrientation orientation = plot.getOrientation();
422             if (orientation == PlotOrientation.HORIZONTAL) {
423                 float x = (float) axis.valueToJava2D(value, adjusted,
424                         plot.getRangeAxisEdge());
425                 float y = (float) adjusted.getMaxY();
426                 path = new GeneralPath JavaDoc();
427                 path.moveTo(x, y);
428                 path.lineTo((float) (x + getXOffset()),
429                         y - (float) getYOffset());
430                 path.lineTo((float) (x + getXOffset()),
431                         (float) (adjusted.getMinY() - getYOffset()));
432                 path.lineTo(x, (float) adjusted.getMinY());
433                 path.closePath();
434             }
435             else if (orientation == PlotOrientation.VERTICAL) {
436                 float y = (float) axis.valueToJava2D(value, adjusted,
437                         plot.getRangeAxisEdge());
438                 float x = (float) dataArea.getX();
439                 path = new GeneralPath JavaDoc();
440                 path.moveTo(x, y);
441                 path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset);
442                 path.lineTo((float) (adjusted.getMaxX() + this.xOffset),
443                         y - (float) this.yOffset);
444                 path.lineTo((float) (adjusted.getMaxX()), y);
445                 path.closePath();
446             }
447             g2.setPaint(marker.getPaint());
448             g2.fill(path);
449             g2.setPaint(marker.getOutlinePaint());
450             g2.draw(path);
451         }
452     }
453    
454    /**
455      * Draw a single data item.
456      *
457      * @param g2 the graphics device.
458      * @param state the renderer state.
459      * @param dataArea the area in which the data is drawn.
460      * @param plot the plot.
461      * @param domainAxis the domain axis.
462      * @param rangeAxis the range axis.
463      * @param dataset the dataset.
464      * @param row the row index (zero-based).
465      * @param column the column index (zero-based).
466      * @param pass the pass index.
467      */

468     public void drawItem(Graphics2D JavaDoc g2,
469                          CategoryItemRendererState state,
470                          Rectangle2D JavaDoc dataArea,
471                          CategoryPlot plot,
472                          CategoryAxis domainAxis,
473                          ValueAxis rangeAxis,
474                          CategoryDataset dataset,
475                          int row,
476                          int column,
477                          int pass) {
478
479         if (!getItemVisible(row, column)) {
480             return;
481         }
482         
483         // nothing is drawn for null...
484
Number JavaDoc v = dataset.getValue(row, column);
485         if (v == null) {
486             return;
487         }
488        
489         Rectangle2D JavaDoc adjusted = new Rectangle2D.Double JavaDoc(dataArea.getX(),
490                 dataArea.getY() + getYOffset(),
491                 dataArea.getWidth() - getXOffset(),
492                 dataArea.getHeight() - getYOffset());
493        
494         PlotOrientation orientation = plot.getOrientation();
495
496         // current data point...
497
double x1 = domainAxis.getCategoryMiddle(column, getColumnCount(),
498                 adjusted, plot.getDomainAxisEdge());
499         double value = v.doubleValue();
500         double y1 = rangeAxis.valueToJava2D(value, adjusted,
501                 plot.getRangeAxisEdge());
502
503         Shape JavaDoc shape = getItemShape(row, column);
504         if (orientation == PlotOrientation.HORIZONTAL) {
505             shape = ShapeUtilities.createTranslatedShape(shape, y1, x1);
506         }
507         else if (orientation == PlotOrientation.VERTICAL) {
508             shape = ShapeUtilities.createTranslatedShape(shape, x1, y1);
509         }
510        
511         if (getItemLineVisible(row, column)) {
512             if (column != 0) {
513
514                 Number JavaDoc previousValue = dataset.getValue(row, column - 1);
515                 if (previousValue != null) {
516
517                     // previous data point...
518
double previous = previousValue.doubleValue();
519                     double x0 = domainAxis.getCategoryMiddle(column - 1,
520                             getColumnCount(), adjusted,
521                             plot.getDomainAxisEdge());
522                     double y0 = rangeAxis.valueToJava2D(previous, adjusted,
523                             plot.getRangeAxisEdge());
524
525                     double x2 = x0 + getXOffset();
526                     double y2 = y0 - getYOffset();
527                     double x3 = x1 + getXOffset();
528                     double y3 = y1 - getYOffset();
529                    
530                     GeneralPath JavaDoc clip = new GeneralPath JavaDoc();
531                    
532                     if (orientation == PlotOrientation.HORIZONTAL) {
533                         clip.moveTo((float) y0, (float) x0);
534                         clip.lineTo((float) y1, (float) x1);
535                         clip.lineTo((float) y3, (float) x3);
536                         clip.lineTo((float) y2, (float) x2);
537                         clip.lineTo((float) y0, (float) x0);
538                         clip.closePath();
539                     }
540                     else if (orientation == PlotOrientation.VERTICAL) {
541                         clip.moveTo((float) x0, (float) y0);
542                         clip.lineTo((float) x1, (float) y1);
543                         clip.lineTo((float) x3, (float) y3);
544                         clip.lineTo((float) x2, (float) y2);
545                         clip.lineTo((float) x0, (float) y0);
546                         clip.closePath();
547                     }
548                    
549                     g2.setPaint(getItemPaint(row, column));
550                     g2.fill(clip);
551                     g2.setStroke(getItemOutlineStroke(row, column));
552                     g2.setPaint(getItemOutlinePaint(row, column));
553                     g2.draw(clip);
554                 }
555             }
556         }
557
558         // draw the item label if there is one...
559
if (isItemLabelVisible(row, column)) {
560             drawItemLabel(g2, orientation, dataset, row, column, x1, y1,
561                     (value < 0.0));
562         }
563
564         // add an item entity, if this information is being collected
565
EntityCollection entities = state.getEntityCollection();
566         if (entities != null) {
567             addItemEntity(entities, dataset, row, column, shape);
568         }
569
570     }
571
572 }
573
Popular Tags