Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/chart/XMLChartTheme.java @ 875:5e9efdda6894
merged gnv-artifacts/1.0
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:13:56 +0200 |
parents | 05bf8534a35a |
children | f953c9a559d8 |
comparison
equal
deleted
inserted
replaced
722:bb3ffe7d719e | 875:5e9efdda6894 |
---|---|
1 package de.intevation.gnv.chart; | |
2 | |
3 import de.intevation.artifactdatabase.Config; | |
4 | |
5 import java.awt.Color; | |
6 import java.awt.Font; | |
7 import java.awt.Paint; | |
8 | |
9 import java.awt.geom.Ellipse2D; | |
10 | |
11 import org.apache.log4j.Logger; | |
12 | |
13 import org.jfree.chart.StandardChartTheme; | |
14 | |
15 import org.jfree.chart.plot.XYPlot; | |
16 | |
17 import org.jfree.chart.renderer.xy.AbstractXYItemRenderer; | |
18 import org.jfree.chart.renderer.xy.XYBarRenderer; | |
19 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; | |
20 | |
21 import org.jfree.ui.RectangleInsets; | |
22 | |
23 import org.jfree.util.UnitType; | |
24 | |
25 import org.w3c.dom.Document; | |
26 | |
27 /** | |
28 * Implementation of JFreeChart's default implementation | |
29 * <code>StandardChartTheme</code>. This class takes an xml document with a | |
30 * bunch of parameters and turns it into a <code>ChartTheme</code> to change | |
31 * the appearance of charts. | |
32 * | |
33 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | |
34 */ | |
35 public class XMLChartTheme | |
36 extends StandardChartTheme | |
37 { | |
38 /** | |
39 * Default color. | |
40 */ | |
41 private static final Color DEFAULT_COLOR = Color.BLACK; | |
42 | |
43 /** | |
44 * Logger used for logging with log4j. | |
45 */ | |
46 private Logger log = Logger.getLogger(XMLChartTheme.class); | |
47 | |
48 /** | |
49 * Field storing the visibility of the domain crosshair | |
50 */ | |
51 protected boolean domainCrosshairVisible; | |
52 | |
53 /** | |
54 * Field storing the visibility of the range crosshair | |
55 */ | |
56 protected boolean rangeCrosshairVisible; | |
57 | |
58 /** | |
59 * Field storing the visiblity of lines. | |
60 */ | |
61 protected boolean renderLines; | |
62 | |
63 /** | |
64 * Field storing the visibility of data points | |
65 */ | |
66 protected boolean renderShapes; | |
67 | |
68 /** | |
69 * Field storing the width of a data point | |
70 */ | |
71 protected int pointWidth; | |
72 | |
73 /** | |
74 * Field storing the height of a data point. | |
75 */ | |
76 protected int pointHeight; | |
77 | |
78 /** | |
79 * Field storing the base color of a bin in a histogram chart | |
80 */ | |
81 protected Paint histogramBasePaint; | |
82 | |
83 | |
84 /** | |
85 * Constructor | |
86 * | |
87 * @param name Name for this theme. | |
88 */ | |
89 public XMLChartTheme(String name) { | |
90 super(name); | |
91 } | |
92 | |
93 | |
94 /** | |
95 * Setter method for the visibility of the domain crosshair. | |
96 * | |
97 * @param visible True, if domain crosshair should be visible | |
98 */ | |
99 public void setDomainCrosshairVisible(boolean visible) { | |
100 this.domainCrosshairVisible = visible; | |
101 } | |
102 | |
103 | |
104 /** | |
105 * Getter method for retrieving the visibility of the domain crosshair. | |
106 * | |
107 * @return Visibility of the domain crosshair. | |
108 */ | |
109 public boolean getDomainCrosshairVisible() { | |
110 return domainCrosshairVisible; | |
111 } | |
112 | |
113 | |
114 /** | |
115 * Getter method for retrieving the visibility of the range crosshair. | |
116 * | |
117 * @return Visibility of the range crosshair. | |
118 */ | |
119 public boolean getRangeCrosshairVisible() { | |
120 return rangeCrosshairVisible; | |
121 } | |
122 | |
123 | |
124 /** | |
125 * Setter method for the visibility of the range crosshair. | |
126 * | |
127 * @param visible True, if range crosshair should be visible | |
128 */ | |
129 public void setRangeCrosshairVisible(boolean visible) { | |
130 this.rangeCrosshairVisible = visible; | |
131 } | |
132 | |
133 | |
134 /** | |
135 * Method to set the bin color of histograms. | |
136 * | |
137 * @param c Bin color | |
138 */ | |
139 public void setHistogramBasePaint(Color c) { | |
140 this.histogramBasePaint = c; | |
141 } | |
142 | |
143 | |
144 /** | |
145 * Getter method for retrieving the bin color. | |
146 * | |
147 * @return Bin color | |
148 */ | |
149 public Paint getHistogramBasePaint() { | |
150 return histogramBasePaint; | |
151 } | |
152 | |
153 | |
154 /** | |
155 * Take a given xml document and read the configuration of a chart | |
156 * appearance. | |
157 * | |
158 * @param document XML document | |
159 */ | |
160 public void applyXMLConfiguration(Document document) { | |
161 log.debug("create XMLChartTheme"); | |
162 | |
163 init(document); | |
164 } | |
165 | |
166 | |
167 /** | |
168 * Start parsing the different settings from <code>document</code>. | |
169 * | |
170 * @param document XML document | |
171 */ | |
172 private void init(Document document) { | |
173 log.debug("init XMLChartTheme parameters"); | |
174 | |
175 initChartParameters(document); | |
176 initTitleParameters(document); | |
177 initSubtitleParameters(document); | |
178 initPlotParameters(document); | |
179 initAxisParameters(document); | |
180 initLegendParameters(document); | |
181 initRenderer(document); | |
182 initHistogramColor(document); | |
183 } | |
184 | |
185 | |
186 /** | |
187 * Read parameters configuring the title of a chart. | |
188 * | |
189 * @param document XML document | |
190 */ | |
191 private void initTitleParameters(Document document) { | |
192 log.debug("init title parameters."); | |
193 | |
194 int size = getInt(document, "theme/title/font/size/@value"); | |
195 String type = getString(document, "theme/title/font/type/@value"); | |
196 boolean bold = getBool(document, "theme/title/font/bold/@value"); | |
197 | |
198 setExtraLargeFont(createFont(type, size, bold)); | |
199 | |
200 String color = getString(document, "theme/title/font/color/@value"); | |
201 Color c = decodeColor(color); | |
202 if (c != null) | |
203 setTitlePaint(c); | |
204 } | |
205 | |
206 | |
207 /** | |
208 * Read parameters configuring the subtitle of a chart. | |
209 * | |
210 * @param document XML document | |
211 */ | |
212 private void initSubtitleParameters(Document document) { | |
213 log.debug("init title parameters."); | |
214 | |
215 int size = getInt(document, "theme/subtitle/font/size/@value"); | |
216 String type = getString(document, "theme/subtitle/font/type/@value"); | |
217 boolean bold = getBool(document, "theme/subtitle/font/bold/@value"); | |
218 | |
219 setLargeFont(createFont(type, size, bold)); | |
220 | |
221 String col = getString(document, "theme/subtitle/font/color/@value"); | |
222 setSubtitlePaint(Color.decode(col)); | |
223 } | |
224 | |
225 | |
226 /** | |
227 * Read parameters configuring the background color of a chart. | |
228 * | |
229 * @param document XML document | |
230 */ | |
231 private void initChartParameters(Document document) { | |
232 log.debug("init chart parameters."); | |
233 | |
234 String bg = getString(document, "theme/chart/background/color/@value"); | |
235 Color c = decodeColor(bg); | |
236 if (c != null) | |
237 setChartBackgroundPaint(c); | |
238 } | |
239 | |
240 | |
241 /** | |
242 * Read parameters configuring the plot of a chart. | |
243 * | |
244 * @param document XML document | |
245 */ | |
246 private void initPlotParameters(Document document) { | |
247 log.debug("init plot parameters."); | |
248 | |
249 String tmp = null; | |
250 tmp = getString(document, "theme/plot/background/color/@value"); | |
251 Color c = decodeColor(tmp); | |
252 if (c != null) | |
253 setPlotBackgroundPaint(c); | |
254 | |
255 tmp = getString(document, "theme/plot/outline/color/@value"); | |
256 c = decodeColor(tmp); | |
257 if (c != null) | |
258 setPlotOutlinePaint(c); | |
259 | |
260 tmp = getString(document, "theme/plot/domaingridline/color/@value"); | |
261 c = decodeColor(tmp); | |
262 if (c != null) | |
263 setDomainGridlinePaint(c); | |
264 | |
265 tmp = getString(document, "theme/plot/rangegridline/color/@value"); | |
266 c = decodeColor(tmp); | |
267 if (c != null) | |
268 setRangeGridlinePaint(c); | |
269 | |
270 boolean rangeCrosshairVisible = getBool( | |
271 document, "theme/plot/rangecrosshair/visible/@value"); | |
272 setRangeCrosshairVisible(rangeCrosshairVisible); | |
273 | |
274 boolean domainCrosshairVisible = getBool( | |
275 document, "theme/plot/domaincrosshair/visible/@value"); | |
276 setDomainCrosshairVisible(domainCrosshairVisible); | |
277 | |
278 int top = getInt(document, "theme/plot/offset/top/@value"); | |
279 int bottom = getInt(document, "theme/plot/offset/bottom/@value"); | |
280 int left = getInt(document, "theme/plot/offset/left/@value"); | |
281 int right = getInt(document, "theme/plot/offset/right/@value"); | |
282 setAxisOffset(new RectangleInsets( | |
283 UnitType.RELATIVE, | |
284 top, left, bottom, right) | |
285 ); | |
286 } | |
287 | |
288 | |
289 /** | |
290 * Read parameters configuring the axes of a plot. | |
291 * | |
292 * @param document XML document | |
293 */ | |
294 private void initAxisParameters(Document document) { | |
295 log.debug("init axis parameters."); | |
296 | |
297 String tmp = null; | |
298 tmp = getString(document, "theme/axis/label/color/@value"); | |
299 Color c = decodeColor(tmp); | |
300 if (c != null) | |
301 setAxisLabelPaint(c); | |
302 | |
303 tmp = getString(document, "theme/axis/ticklabel/color/@value"); | |
304 c = decodeColor(tmp); | |
305 if (c != null) | |
306 setTickLabelPaint(c); | |
307 } | |
308 | |
309 | |
310 /** | |
311 * Read parameters configuring the legend of a chart. | |
312 * | |
313 * @param document XML document | |
314 */ | |
315 private void initLegendParameters(Document document) { | |
316 log.debug("init legend parameters."); | |
317 | |
318 String tmp = null; | |
319 tmp = getString(document, "theme/legend/font/color/@value"); | |
320 Color c = decodeColor(tmp); | |
321 if (c != null) | |
322 setLegendItemPaint(c); | |
323 | |
324 tmp = getString(document, "theme/legend/background/color/@value"); | |
325 c = decodeColor(tmp); | |
326 if (c != null) | |
327 setLegendBackgroundPaint(c); | |
328 } | |
329 | |
330 | |
331 /** | |
332 * Read parameters configuring the renderer of a plot. | |
333 * | |
334 * @param document XML document | |
335 */ | |
336 private void initRenderer(Document document) { | |
337 log.debug("init renderer parameters."); | |
338 | |
339 pointWidth = getInt(document, "theme/plot/itemrenderer/width/@value"); | |
340 log.debug("Read point width of " + pointWidth); | |
341 pointHeight = getInt(document, "theme/plot/itemrenderer/height/@value"); | |
342 log.debug("Read point height of " + pointHeight); | |
343 renderLines = getBool( | |
344 document, "theme/plot/itemrenderer/renderLines/@value" | |
345 ); | |
346 renderShapes = getBool( | |
347 document, "theme/plot/itemrenderer/renderPoints/@value" | |
348 ); | |
349 } | |
350 | |
351 | |
352 /** | |
353 * Read base color of bins in histogram charts. | |
354 * | |
355 * @param document XML document | |
356 */ | |
357 private void initHistogramColor(Document document) { | |
358 log.debug("init histogram color"); | |
359 String tmp = getString(document, "theme/histogram/bar/color/@value"); | |
360 Color c = decodeColor(tmp); | |
361 | |
362 if (c != null) | |
363 setHistogramBasePaint(c); | |
364 } | |
365 | |
366 | |
367 /** | |
368 * Read a xpath expression and return the matched string. | |
369 * | |
370 * @param document Document | |
371 * @param xpath XPath expression | |
372 * | |
373 * @return Matched string | |
374 */ | |
375 private static String getString(Document document, String xpath) { | |
376 return Config.getStringXPath(document, xpath); | |
377 } | |
378 | |
379 | |
380 /** | |
381 * Read a xpath and turn it into an integer. | |
382 * | |
383 * @param document Document | |
384 * @param xpath XPath expression | |
385 * | |
386 * @return Matched string as integer representation. Return 0 if no integer | |
387 * have been found at <code>xpath</code>. | |
388 */ | |
389 private static int getInt(Document document, String xpath) { | |
390 String tmp = getString(document, xpath); | |
391 | |
392 if (tmp != null) | |
393 return Integer.parseInt(tmp); | |
394 else | |
395 return 0; | |
396 } | |
397 | |
398 | |
399 /** | |
400 * Read a xpath and turn it into a boolean. | |
401 * | |
402 * @param document Document | |
403 * @param xpath XPath expression | |
404 * | |
405 * @return Matched string as boolean representation. Return false if no | |
406 * boolean have been found at <code>xpath</code>. | |
407 */ | |
408 private static boolean getBool(Document document, String xpath) { | |
409 String tmp = getString(document, xpath); | |
410 | |
411 if (tmp != null) | |
412 return Boolean.parseBoolean(tmp); | |
413 else | |
414 return false; | |
415 } | |
416 | |
417 | |
418 /** | |
419 * Turns a string into a color using {@link java.awt.Color}. | |
420 * | |
421 * @param color as string | |
422 * | |
423 * @return Color | |
424 */ | |
425 protected Color decodeColor(String color) { | |
426 try { | |
427 if (color == null) | |
428 return null; | |
429 | |
430 return Color.decode(color); | |
431 } | |
432 catch (NumberFormatException nfe) { | |
433 log.warn("Error while parsing color: " + color, nfe); | |
434 } | |
435 | |
436 return null; | |
437 } | |
438 | |
439 | |
440 /** | |
441 * Create a font with the given parameters. | |
442 * | |
443 * @param type Font type | |
444 * @param size Font size | |
445 * @param bold Font weight | |
446 * | |
447 * @return Font | |
448 */ | |
449 protected Font createFont(String type, int size, boolean bold) { | |
450 Font font = null; | |
451 if (bold) | |
452 font = new Font(type, Font.BOLD, size); | |
453 else | |
454 font = new Font(type, Font.PLAIN, size); | |
455 | |
456 return font; | |
457 } | |
458 | |
459 | |
460 /** | |
461 * Apply settings of this <code>ChartTheme</code> to the given | |
462 * <code>XYPlot</code>. | |
463 * | |
464 * @param plot XYPlot | |
465 */ | |
466 @Override | |
467 protected void applyToXYPlot(XYPlot plot) { | |
468 log.debug("apply theme parameter to XYPlot"); | |
469 | |
470 super.applyToXYPlot(plot); | |
471 plot.setDomainCrosshairVisible(this.domainCrosshairVisible); | |
472 plot.setRangeCrosshairVisible(this.rangeCrosshairVisible); | |
473 | |
474 AbstractXYItemRenderer renderer = (AbstractXYItemRenderer) | |
475 plot.getRenderer(); | |
476 | |
477 if (renderer instanceof XYLineAndShapeRenderer) | |
478 applyToXYLineAndShapeRenderer(plot); | |
479 | |
480 if (renderer instanceof XYBarRenderer) | |
481 applyToXYBarRenderer(plot); | |
482 } | |
483 | |
484 | |
485 /** | |
486 * Apply settings of this <code>ChartTheme</code> to the | |
487 * <code>XYLineAndShapeRenderer</code> of the given <code>XYPlot</code>. | |
488 * | |
489 * @param plot XYPlot | |
490 */ | |
491 protected void applyToXYLineAndShapeRenderer(XYPlot plot) { | |
492 if (plot == null) | |
493 return; | |
494 | |
495 XYLineAndShapeRenderer renderer = | |
496 (XYLineAndShapeRenderer) plot.getRenderer(); | |
497 | |
498 Ellipse2D.Double point = new Ellipse2D.Double( | |
499 -(pointWidth/2), -(pointHeight/2), pointWidth, pointHeight | |
500 ); | |
501 | |
502 renderer.setSeriesShape(0, point); | |
503 renderer.setSeriesShapesVisible(0, renderShapes); | |
504 renderer.setSeriesLinesVisible(0, renderLines); | |
505 | |
506 plot.setRenderer(renderer); | |
507 } | |
508 | |
509 | |
510 /** | |
511 * Apply settings of this <code>ChartTheme</code> to the | |
512 * <code>XYBarRenderer</code> of the given <code>XYPlot</code>. | |
513 * | |
514 * @param plot XYPlot | |
515 */ | |
516 protected void applyToXYBarRenderer(XYPlot plot) { | |
517 if (plot == null) | |
518 return; | |
519 | |
520 XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer(); | |
521 | |
522 renderer.setSeriesPaint(0, histogramBasePaint); | |
523 } | |
524 } | |
525 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : |