KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > krysalis > jcharts > Chart


1 /***********************************************************************************************
2  * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved.
3  *
4  * Redistribution and use of this software and associated documentation ("Software"), with or
5  * without modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain copyright statements and notices.
8  * Redistributions must also contain a copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
11  * conditions and the following disclaimer in the documentation and/or other materials
12  * provided with the distribution.
13  *
14  * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote
15  * products derived from this Software without prior written permission of Nathaniel G.
16  * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net
17  *
18  * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear
19  * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a
20  * registered trademark of Nathaniel G. Auvil.
21  *
22  * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/).
23  *
24  * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY
25  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
27  * jCharts OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
32  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
33  ************************************************************************************************/

34
35 package org.krysalis.jcharts;
36
37
38 import org.krysalis.jcharts.chartData.ChartDataException;
39 import org.krysalis.jcharts.imageMap.ImageMap;
40 import org.krysalis.jcharts.properties.ChartProperties;
41 import org.krysalis.jcharts.properties.LegendProperties;
42 import org.krysalis.jcharts.properties.PropertyException;
43 import org.krysalis.jcharts.test.HTMLGenerator;
44
45 import java.awt.*;
46 import java.awt.font.FontRenderContext JavaDoc;
47 import java.awt.font.LineBreakMeasurer JavaDoc;
48 import java.awt.font.TextAttribute JavaDoc;
49 import java.awt.font.TextLayout JavaDoc;
50 import java.awt.geom.Rectangle2D JavaDoc;
51 import java.awt.image.BufferedImage JavaDoc;
52 import java.io.Serializable JavaDoc;
53 import java.text.AttributedString JavaDoc;
54
55
56 /*************************************************************************************
57  * Base class of all charts.
58  *
59  * @author Nathaniel Auvil, Sandor Dornbush
60  * @version $Id: Chart.java,v 1.3 2003/06/21 19:44:35 nathaniel_auvil Exp $
61  ************************************************************************************/

62 public abstract class Chart implements Serializable JavaDoc
63 {
64     //---Be aware that the calls BufferedImage.getGraphics() and BufferedImage.createGraphics(), actually
65
//--- create a new Graphics2D Object on each invocation. So keep a reference here.
66
private Graphics2D graphics2D;
67
68     private int width;
69     private int height;
70
71     private Legend legend;
72
73     //---general properties of all chart types.
74
private ChartProperties chartProperties;
75
76
77     //---used to generate an image map for the image
78
private boolean generateImageMap = false;
79     private ImageMap imageMap = null;
80     private BufferedImage JavaDoc bufferedImage = null;
81
82
83     /******************************************************************************************
84      * Constructor
85      *
86      * @param legendProperties
87      * @param chartProperties
88      * @param pixelWidth
89      * @param pixelHeight
90      *******************************************************************************************/

91     public Chart( LegendProperties legendProperties, ChartProperties chartProperties, int pixelWidth, int pixelHeight )
92     {
93         this.width = pixelWidth;
94         this.height = pixelHeight;
95         this.chartProperties = chartProperties;
96
97         if( legendProperties != null )
98         {
99             this.legend = new Legend( this, legendProperties );
100             legendProperties.setSize( new Dimension( width, height ) );
101         }
102     }
103
104
105     /******************************************************************************************
106      * Returns flag indicating whether to generate an ImageMap
107      *
108      * @return boolean
109      *******************************************************************************************/

110     public boolean getGenerateImageMapFlag()
111     {
112         return this.generateImageMap;
113     }
114
115
116     /******************************************************************************************
117      * Returns the BufferedImage used to generate the ImageMap. Only should be called on
118      * binary format images, such as PNG and JPG, as it will not work on SVG.
119      *
120      * This is a HACK and the design of jCharts should do better than this!!!!!!
121      *
122      * @return BufferedImage
123      *******************************************************************************************/

124     public BufferedImage JavaDoc getBufferedImage()
125     {
126         return this.bufferedImage;
127     }
128
129
130     /******************************************************************************************
131      * Renders the chart into a BufferedImage so that we can calculate all the Image Map
132      * coordinates.
133      *
134      * @throws ChartDataException
135      * @throws PropertyException
136      *******************************************************************************************/

137     public void renderWithImageMap() throws ChartDataException, PropertyException
138     {
139         this.bufferedImage = new BufferedImage JavaDoc( this.getImageWidth(), this.getImageHeight(), BufferedImage.TYPE_INT_RGB );
140         this.setGraphics2D( this.bufferedImage.createGraphics() );
141         this.generateImageMap = true;
142
143         this.render();
144     }
145
146
147     /******************************************************************************************
148      * Call this to kick off rendering of the chart
149      *
150      * @throws ChartDataException
151      * @throws PropertyException
152      *******************************************************************************************/

153     public void render() throws ChartDataException, PropertyException
154     {
155         if( this.chartProperties.useAntiAliasing() )
156         {
157             this.graphics2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
158         }
159         else
160         {
161             this.graphics2D.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF );
162         }
163
164
165         Rectangle2D.Float JavaDoc rectangle = new Rectangle2D.Float JavaDoc( 0, 0, this.width, this.height );
166
167         //---fill the background
168
this.graphics2D.setPaint( this.chartProperties.getBackgroundPaint() );
169         this.graphics2D.fill( rectangle );
170
171         //---draw a border around the chart if desired
172
if( this.chartProperties.getBorderStroke() != null )
173         {
174             //---there is a one pixel difference when you fill versus draw a rectangle
175
rectangle.width -= 1;
176             rectangle.height -= 1;
177             this.chartProperties.getBorderStroke().draw( this.graphics2D, rectangle );
178         }
179
180         //---draw the chart
181
this.renderChart();
182     }
183
184
185     /*************************************************************************************************
186      * Displays the chart title and returns the height of the title PLUS title padding.
187      *
188      * @param chartTitle
189      * @param fontRenderContext
190      * @return float the height required by the title. If no title is displayed, zero is returned.
191      **************************************************************************************************/

192     protected float renderChartTitle( String JavaDoc chartTitle, FontRenderContext JavaDoc fontRenderContext )
193     {
194         float height = 0;
195
196         if( chartTitle != null )
197         {
198             //---the y value of where to write the current line
199
float currentLine = this.getChartProperties().getEdgePadding();
200
201             // change title into an AttributedString with the font as an attribute
202
AttributedString JavaDoc s = new AttributedString JavaDoc( chartTitle );
203             s.addAttribute( TextAttribute.FONT, this.getChartProperties().getTitleFont().getFont() );
204
205             //---get LineBreakMeasurer on the attributed string...it will break the text for us
206
LineBreakMeasurer JavaDoc measurer = new LineBreakMeasurer JavaDoc( s.getIterator(), fontRenderContext );
207
208             //---set the text color
209
this.getGraphics2D().setPaint( this.getChartProperties().getTitleFont().getPaint() );
210
211             //---draw each title line. Subtract padding from each side for printable width.
212
float wrappingWidth= this.getImageWidth() - ( this.getChartProperties().getEdgePadding() * 2 );
213
214             TextLayout JavaDoc titleTextLayout= null;
215             while( ( titleTextLayout = measurer.nextLayout( wrappingWidth ) ) != null )
216             {
217                 //---set the current line to where the title will be written
218
currentLine += titleTextLayout.getAscent();
219
220                 titleTextLayout.draw( this.getGraphics2D(),
221                                              ( ( this.getImageWidth() - titleTextLayout.getAdvance() ) / 2 ),
222                                              currentLine );
223
224                 //---keep track of total height of all the title lines
225
height += titleTextLayout.getAscent() + titleTextLayout.getDescent();
226             }
227
228             //---add in the padding between the title and the top of the chart.
229
height += this.getChartProperties().getTitlePadding();
230         }
231
232         return height;
233     }
234
235
236     /******************************************************************************************
237      *
238      * @throws ChartDataException
239      * @throws PropertyException
240      *******************************************************************************************/

241     abstract protected void renderChart() throws ChartDataException, PropertyException;
242
243
244     /******************************************************************************************
245      * Returns the BufferedImage width
246      *
247      * @return int
248      *******************************************************************************************/

249     public final int getImageWidth()
250     {
251         return this.width;
252     }
253
254
255     /******************************************************************************************
256      * Returns the BufferedImage height
257      *
258      * @return int
259      *******************************************************************************************/

260     public final int getImageHeight()
261     {
262         return this.height;
263     }
264
265
266     /******************************************************************************************
267      * Returns the general properties Object.
268      *
269      * @return ChartProperties
270      *******************************************************************************************/

271     public final ChartProperties getChartProperties()
272     {
273         return this.chartProperties;
274     }
275
276
277     /******************************************************************************************
278      * Returns the Legend. Will be NULL if no Legend is desired.
279      *
280      * @return Legend
281      *******************************************************************************************/

282     protected final Legend getLegend()
283     {
284         return this.legend;
285     }
286
287
288     /******************************************************************************************
289      * Returns flag indicating if there is a Legend.
290      *
291      * @return boolean
292      *******************************************************************************************/

293     public final boolean hasLegend()
294     {
295         return this.legend != null;
296     }
297
298
299     /******************************************************************************************
300      * Sets the graphics object to render the chart on by the encoder.
301      *
302      * @param graphics2D
303      *******************************************************************************************/

304     public final void setGraphics2D( Graphics2D graphics2D )
305     {
306         this.graphics2D = graphics2D;
307     }
308
309
310     /******************************************************************************************
311      * Shortcut method to get Graphics2D. Be aware that the call BufferedImage.getGraphics()
312      * and BufferedImage.createGraphics(), actually create a new Grpahics2D Object on each
313      * invocation. This returns the member reference so calls to this are not creating a new
314      * Object each time.
315      *
316      * @return Graphics2D
317      *******************************************************************************************/

318     public final Graphics2D getGraphics2D()
319     {
320         return this.graphics2D;
321     }
322
323
324     /**********************************************************************************************
325      * To optimze performance of the ImageMap Object, we create it once we know how many data
326      * elements are in the chart which is dependent on the AxisChart or PieChart2D
327      *
328      * @param imageMap
329      **********************************************************************************************/

330     public final void setImageMap( ImageMap imageMap )
331     {
332         this.imageMap = imageMap;
333     }
334
335
336     /**********************************************************************************************
337      *
338      * @return imageMap
339      **********************************************************************************************/

340     public final ImageMap getImageMap()
341     {
342         return this.imageMap;
343     }
344
345
346     /**********************************************************************************************
347      * Enables the testing routines to display the contents of this Object.
348      *
349      * @param htmlGenerator
350      * @param imageFileName
351      * @param imageMap if this is NULL we are not creating image map data in html
352      **********************************************************************************************/

353     public void toHTML( HTMLGenerator htmlGenerator, String JavaDoc imageFileName, ImageMap imageMap )
354     {
355         htmlGenerator.chartTableStart( this.getClass().getName(), imageFileName, imageMap );
356
357         htmlGenerator.chartTableRowStart();
358         this.chartProperties.toHTML( htmlGenerator );
359         htmlGenerator.chartTableRowEnd();
360
361         if( this.legend != null )
362         {
363             htmlGenerator.chartTableRowStart();
364             this.getLegend().toHTML( htmlGenerator );
365             htmlGenerator.chartTableRowEnd();
366         }
367
368         htmlGenerator.chartTableEnd();
369     }
370
371
372 }
373
Popular Tags