comparison gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonPlot.java @ 1119:7c4f81f74c47

merged gnv-artifacts
author Thomas Arendsen Hein <thomas@intevation.de>
date Fri, 28 Sep 2012 12:14:00 +0200
parents f953c9a559d8
children
comparison
equal deleted inserted replaced
1027:fca4b5eb8d2f 1119:7c4f81f74c47
1 /*
2 * Copyright (c) 2010 by Intevation GmbH
3 *
4 * This program is free software under the LGPL (>=v2.1)
5 * Read the file LGPL.txt coming with the software for details
6 * or visit http://www.gnu.org/licenses/ if it does not exist.
7 */
8
9 package de.intevation.gnv.jfreechart;
10
11 import java.awt.AlphaComposite;
12 import java.awt.Composite;
13 import java.awt.Graphics2D;
14 import java.awt.Shape;
15
16 import java.awt.geom.Point2D;
17 import java.awt.geom.Rectangle2D;
18
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22
23 import org.jfree.chart.axis.Axis;
24 import org.jfree.chart.axis.AxisCollection;
25 import org.jfree.chart.axis.AxisLocation;
26 import org.jfree.chart.axis.AxisSpace;
27 import org.jfree.chart.axis.AxisState;
28 import org.jfree.chart.axis.ValueAxis;
29
30 import org.jfree.chart.plot.Plot;
31 import org.jfree.chart.plot.PlotOrientation;
32 import org.jfree.chart.plot.PlotRenderingInfo;
33 import org.jfree.chart.plot.PlotState;
34
35 import org.jfree.data.Range;
36
37 import org.jfree.ui.RectangleEdge;
38 import org.jfree.ui.RectangleInsets;
39
40 import org.jfree.util.ObjectList;
41
42 /**
43 * A class for plotting polygons into a 2D chart. This plot makes use of <code>
44 * PolygonRenderer</code>.
45 *
46 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a>
47 */
48 // TODO implement cloneable
49 public class PolygonPlot
50 extends Plot
51 {
52 public static final String PLOT_TYPE = "PolygonPlot";
53
54 public static final PlotOrientation DEFAULT_PLOT_ORIENTATION =
55 PlotOrientation.VERTICAL;
56
57 private PolygonDataset dataset;
58 private transient PolygonRenderer renderer;
59
60 private PlotOrientation orientation;
61
62 private RectangleInsets axisOffset;
63
64 private ObjectList domainAxisLocation;
65 private ObjectList rangeAxisLocation;
66 private ObjectList domainAxes;
67 private ObjectList rangeAxes;
68
69
70 /**
71 * Constructs a new PolygonPlot with a dataset and a renderer.
72 *
73 * @param dataset Dataset containing polygons.
74 * @param renderer The renderer used to draw polygons.
75 */
76 public PolygonPlot(PolygonDataset dataset, PolygonRenderer renderer) {
77 this(dataset, renderer, null, null, PlotOrientation.HORIZONTAL);
78 }
79
80
81 /**
82 * @param dataset Dataset containing polygons.
83 * @param renderer The renderer used to draw polygons.
84 * @param orientation The orientation used for this plot.
85 */
86 public PolygonPlot(
87 PolygonDataset dataset,
88 PolygonRenderer renderer,
89 PlotOrientation orientation
90 ) {
91 this(dataset, renderer, null, null, orientation);
92 }
93
94
95 /**
96 * @param dataset Dataset containing polygons.
97 * @param renderer The renderer used to draw polygons.
98 * @param domainAxis The x axis.
99 * @param rangeAxis The y axis.
100 * @param orientation The orientation used for this plot.
101 */
102 public PolygonPlot(
103 PolygonDataset dataset,
104 PolygonRenderer renderer,
105 ValueAxis domainAxis,
106 ValueAxis rangeAxis,
107 PlotOrientation orientation
108 ) {
109 super();
110
111 this.dataset = dataset;
112 this.renderer = renderer;
113 this.domainAxes = new ObjectList();
114 this.rangeAxes = new ObjectList();
115 this.domainAxisLocation = new ObjectList();
116 this.rangeAxisLocation = new ObjectList();
117 this.axisOffset = RectangleInsets.ZERO_INSETS;
118
119 if (orientation != null)
120 this.orientation = orientation;
121 else
122 this.orientation = DEFAULT_PLOT_ORIENTATION;
123
124 if (domainAxis != null) {
125 this.domainAxes.set(0, domainAxis);
126 domainAxis.setPlot(this);
127 }
128 domainAxisLocation.set(0, AxisLocation.BOTTOM_OR_LEFT);
129
130 if (rangeAxis != null) {
131 this.rangeAxes.set(0, rangeAxis);
132 rangeAxis.setPlot(this);
133 }
134 rangeAxisLocation.set(0, AxisLocation.BOTTOM_OR_LEFT);
135
136 configureDomainAxis();
137 configureRangeAxis();
138 }
139
140
141 public void configureDomainAxis() {
142 // we just have 1 dataset
143 Range domainAxisRange = getDataset().getDomainBounds();
144
145 for (int i = 0; i < domainAxes.size(); i++) {
146 ValueAxis axis = (ValueAxis) domainAxes.get(i);
147
148 if (axis != null) {
149 axis.configure();
150 axis.setRange(domainAxisRange);
151 }
152 }
153 }
154
155 public ValueAxis getDomainAxis() {
156 return getDomainAxis(0);
157 }
158
159 public void setDomainAxis(ValueAxis axis) {
160 domainAxes.set(0, axis);
161 }
162
163 public ValueAxis getDomainAxis(int index) {
164 return index < domainAxes.size()
165 ? (ValueAxis)domainAxes.get(index)
166 : null;
167 }
168
169 public ValueAxis getRangeAxis() {
170 return getRangeAxis(0);
171 }
172
173 public void setRangeAxis(ValueAxis axis) {
174 rangeAxes.set(0, axis);
175 }
176
177 public ValueAxis getRangeAxis(int index) {
178 return index < rangeAxes.size()
179 ? (ValueAxis)rangeAxes.get(index)
180 : null;
181 }
182
183 public void configureRangeAxis() {
184 // we just have 1 dataset
185 Range rangeAxisRange = getDataset().getRangeBounds();
186
187 for (int i = 0; i < rangeAxes.size(); i++) {
188 ValueAxis axis = (ValueAxis) rangeAxes.get(i);
189
190 if (axis != null) {
191 axis.configure();
192 axis.setRange(rangeAxisRange);
193 }
194 }
195 }
196
197 public PolygonDataset getDataset(){
198 return this.dataset;
199 }
200
201 public String getPlotType() {
202 return PLOT_TYPE;
203 }
204
205 public void setDataset(PolygonDataset dataset) {
206 this.dataset = dataset;
207 }
208
209
210 /**
211 * This is the major method to draw the into a given Graphic2D object.
212 *
213 * @param g2 Graphics object where the plot is drawn into.
214 * @param area The bounds for drawing this plot.
215 * @param anchor An anchor point.
216 * @param parentState The plot state.
217 * @param info
218 */
219 public void draw(
220 Graphics2D g2,
221 Rectangle2D area,
222 Point2D anchor,
223 PlotState parentState,
224 PlotRenderingInfo info
225 ) {
226 Graphics2D savedG2 = g2;
227 Rectangle2D savedDataArea = area;
228
229 if (info != null) {
230 info.setPlotArea(area);
231 info.setDataArea(area);
232 }
233
234 AxisSpace space = calculateAxisSpace(g2, area);
235 Rectangle2D dataArea = space.shrink(area, null);
236
237 // draw background and outline
238 drawBackground(g2, area);
239 drawOutline(g2, area);
240
241 Shape savedClip = g2.getClip();
242 g2.clip(area);
243
244 Composite originalComposite = g2.getComposite();
245 g2.setComposite(AlphaComposite.getInstance(
246 AlphaComposite.SRC_OVER,
247 getForegroundAlpha()
248 ));
249
250 // draw axis
251 drawAxes(g2, area, dataArea, info);
252
253 if (!isEmptyOrNull(dataset)) {
254 // draw data
255 drawPolygons(savedG2, dataArea, info);
256 drawLabels(savedG2, dataArea, info);
257 }
258
259 g2.setClip(savedClip);
260 g2.setComposite(originalComposite);
261 }
262
263
264 /**
265 * Method to draw the axis for this plot.
266 *
267 * @param g2
268 * @param plotArea
269 * @param dataArea
270 * @param plotState
271 */
272 private void drawAxes(
273 Graphics2D g2,
274 Rectangle2D plotArea,
275 Rectangle2D dataArea,
276 PlotRenderingInfo plotState
277 ) {
278 AxisCollection axisCollection = new AxisCollection();
279
280 for (int i = 0; i < domainAxes.size(); i++) {
281 ValueAxis axis = (ValueAxis) domainAxes.get(i);
282 if (axis != null)
283 axisCollection.add(axis, getDomainAxisEdge(i));
284 }
285
286 for (int i = 0; i < rangeAxes.size(); i++) {
287 ValueAxis axis = (ValueAxis) rangeAxes.get(i);
288 if (axis != null)
289 axisCollection.add(axis, getRangeAxisEdge(i));
290 }
291
292 Map axisStateMap = new HashMap();
293
294 // draw the top axes
295 double cursor = dataArea.getMinY() - this.axisOffset.calculateTopOutset(
296 dataArea.getHeight());
297 Iterator iterator = axisCollection.getAxesAtTop().iterator();
298 while (iterator.hasNext()) {
299 ValueAxis axis = (ValueAxis) iterator.next();
300 AxisState info = axis.draw(g2, cursor, plotArea, dataArea,
301 RectangleEdge.TOP, plotState);
302 cursor = info.getCursor();
303 axisStateMap.put(axis, info);
304 }
305
306 // draw the bottom axes
307 cursor = dataArea.getMaxY()
308 + this.axisOffset.calculateBottomOutset(dataArea.getHeight());
309 iterator = axisCollection.getAxesAtBottom().iterator();
310 while (iterator.hasNext()) {
311 ValueAxis axis = (ValueAxis) iterator.next();
312 AxisState info = axis.draw(g2, cursor, plotArea, dataArea,
313 RectangleEdge.BOTTOM, plotState);
314 cursor = info.getCursor();
315 axisStateMap.put(axis, info);
316 }
317
318 // draw the left axes
319 cursor = dataArea.getMinX()
320 - this.axisOffset.calculateLeftOutset(dataArea.getWidth());
321 iterator = axisCollection.getAxesAtLeft().iterator();
322 while (iterator.hasNext()) {
323 ValueAxis axis = (ValueAxis) iterator.next();
324 AxisState info = axis.draw(g2, cursor, plotArea, dataArea,
325 RectangleEdge.LEFT, plotState);
326 cursor = info.getCursor();
327 axisStateMap.put(axis, info);
328 }
329
330 // draw the right axes
331 cursor = dataArea.getMaxX()
332 + this.axisOffset.calculateRightOutset(dataArea.getWidth());
333 iterator = axisCollection.getAxesAtRight().iterator();
334 while (iterator.hasNext()) {
335 ValueAxis axis = (ValueAxis) iterator.next();
336 AxisState info = axis.draw(g2, cursor, plotArea, dataArea,
337 RectangleEdge.RIGHT, plotState);
338 cursor = info.getCursor();
339 axisStateMap.put(axis, info);
340 }
341 }
342
343
344 /**
345 * Put some labels at data items into the plot. Uses PolygonRenderer to do
346 * this job.
347 *
348 * @param g2
349 * @param area
350 * @param info
351 */
352 private void drawLabels(
353 Graphics2D g2,
354 Rectangle2D area,
355 PlotRenderingInfo info
356 ) {
357 renderer.drawLabels(g2, this, area, dataset);
358 }
359
360
361 /**
362 * Plot the polygons. Uses PolygonRenderer to do this job.
363 *
364 * @param g2
365 * @param area
366 * @param info
367 */
368 private void drawPolygons(
369 Graphics2D g2,
370 Rectangle2D area,
371 PlotRenderingInfo info
372 ) {
373 renderer.drawPolygons(g2, this, area, dataset);
374 }
375
376
377 private AxisSpace calculateAxisSpace(Graphics2D g2, Rectangle2D plotArea) {
378 AxisSpace space = new AxisSpace();
379 space = calculateRangeAxisSpace(g2, plotArea, space);
380 Rectangle2D tmpPlotArea = space.shrink(plotArea, null);
381 space = calculateDomainAxisSpace(g2, plotArea, space);
382
383 return space;
384 }
385
386
387 private AxisSpace calculateDomainAxisSpace(
388 Graphics2D g2,
389 Rectangle2D plotArea,
390 AxisSpace space
391 ) {
392 if (space == null)
393 space = new AxisSpace();
394
395 for (int i = 0; i < domainAxes.size(); i++) {
396 Axis axis = (Axis) domainAxes.get(i);
397
398 if (axis != null) {
399 RectangleEdge edge = getDomainAxisEdge(i);
400 space = axis.reserveSpace(g2, this, plotArea, edge, space);
401 }
402 }
403
404 return space;
405 }
406
407
408 private AxisSpace calculateRangeAxisSpace(
409 Graphics2D g2,
410 Rectangle2D plotArea,
411 AxisSpace space
412 ) {
413 if (space == null)
414 space = new AxisSpace();
415
416 for (int i = 0; i < rangeAxes.size(); i++) {
417 Axis axis = (Axis) rangeAxes.get(i);
418
419 if (axis != null) {
420 RectangleEdge edge = getRangeAxisEdge(i);
421 space = axis.reserveSpace(g2, this, plotArea, edge, space);
422 }
423 }
424
425 return space;
426 }
427
428
429 public RectangleEdge getDomainAxisEdge() {
430 return Plot.resolveDomainAxisLocation(
431 getDomainAxisLocation(), orientation
432 );
433 }
434
435
436 public RectangleEdge getDomainAxisEdge(int idx) {
437 AxisLocation location = getDomainAxisLocation(idx);
438 RectangleEdge result = Plot.resolveDomainAxisLocation(
439 location, orientation
440 );
441
442 if (result == null)
443 result = RectangleEdge.opposite(getDomainAxisEdge());
444
445 return result;
446 }
447
448
449 public RectangleEdge getRangeAxisEdge() {
450 return Plot.resolveRangeAxisLocation(
451 getRangeAxisLocation(), orientation
452 );
453 }
454
455
456 public RectangleEdge getRangeAxisEdge(int idx) {
457 AxisLocation location = getRangeAxisLocation(idx);
458 RectangleEdge result = Plot.resolveRangeAxisLocation(
459 location,
460 orientation
461 );
462
463 if (result == null)
464 result = RectangleEdge.opposite(getRangeAxisEdge());
465
466 return result;
467 }
468
469
470 public AxisLocation getDomainAxisLocation() {
471 return (AxisLocation) domainAxisLocation.get(0);
472 }
473
474
475 public AxisLocation getDomainAxisLocation(int idx) {
476 if (idx < domainAxisLocation.size())
477 return (AxisLocation) domainAxisLocation.get(idx);
478
479 return null;
480 }
481
482
483 public AxisLocation getRangeAxisLocation() {
484 return (AxisLocation) rangeAxisLocation.get(0);
485 }
486
487
488 public AxisLocation getRangeAxisLocation(int idx) {
489 if (idx < rangeAxisLocation.size())
490 return (AxisLocation) rangeAxisLocation.get(idx);
491
492 return null;
493 }
494
495
496 /**
497 * @return true, if dataset is null or if it does not contain any
498 * PolygonSeries, otherwise false.
499 */
500 private boolean isEmptyOrNull(PolygonDataset dataset) {
501 if (dataset != null) {
502 int seriesCount = dataset.getSeriesCount();
503 for (int s = 0; s < seriesCount; s++) {
504 PolygonSeries series = dataset.getSeries(s);
505 if (series.getItemCount() > 0) {
506 return false;
507 }
508 }
509 }
510 return true;
511 }
512 }
513 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :

http://dive4elements.wald.intevation.org