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

http://dive4elements.wald.intevation.org