Mercurial > dive4elements > gnv-client
comparison gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonRenderer.java @ 450:20a480753ff9
Render labels in vertical cross section charts.
gnv-artifacts/trunk@498 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Mon, 04 Jan 2010 02:49:42 +0000 |
parents | 92b7ccbf6163 |
children | bc5901bb4525 |
comparison
equal
deleted
inserted
replaced
449:c7ca2fce041f | 450:20a480753ff9 |
---|---|
1 package de.intevation.gnv.jfreechart; | 1 package de.intevation.gnv.jfreechart; |
2 | |
3 import java.util.ArrayList; | |
2 | 4 |
3 import java.awt.Color; | 5 import java.awt.Color; |
4 import java.awt.Graphics2D; | 6 import java.awt.Graphics2D; |
5 import java.awt.Paint; | 7 import java.awt.Paint; |
6 import java.awt.Shape; | 8 import java.awt.Shape; |
7 import java.awt.BasicStroke; | 9 import java.awt.BasicStroke; |
10 import java.awt.FontMetrics; | |
11 import java.awt.Font; | |
8 | 12 |
9 import java.awt.geom.GeneralPath; | 13 import java.awt.geom.GeneralPath; |
10 import java.awt.geom.Rectangle2D; | 14 import java.awt.geom.Rectangle2D; |
11 import java.awt.geom.Rectangle2D.Double; | 15 import java.awt.geom.Rectangle2D.Double; |
16 import java.awt.geom.AffineTransform; | |
12 | 17 |
13 import org.jfree.data.Range; | 18 import org.jfree.data.Range; |
14 | 19 |
20 import org.jfree.chart.axis.ValueAxis; | |
21 | |
22 import org.jfree.ui.RectangleEdge; | |
23 | |
15 import org.apache.log4j.Logger; | 24 import org.apache.log4j.Logger; |
16 | 25 |
26 import org.jfree.text.TextUtilities; | |
27 | |
28 | |
17 /** | 29 /** |
18 * @author Ingo Weinzierl <ingo.weinzierl@intevation.de> | 30 * @author Ingo Weinzierl (ingo.weinzierl@intevation.de) |
31 * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) | |
19 */ | 32 */ |
20 public class PolygonRenderer | 33 public class PolygonRenderer |
21 { | 34 { |
22 private static Logger log = Logger.getLogger( | 35 private static Logger log = Logger.getLogger( |
23 PolygonRenderer.class); | 36 PolygonRenderer.class); |
24 | 37 |
25 public static final int AREA = 1; | |
26 public static final int LINES = 2; | |
27 public static final int AREA_AND_LINES = AREA | LINES; | |
28 | |
29 public interface PaintLookup { | 38 public interface PaintLookup { |
30 | 39 |
31 Paint getPaint(int index); | 40 Paint getPaint(int index); |
32 | 41 |
33 } // interface PaintLookup | 42 } // interface PaintLookup |
34 | 43 |
35 protected int type; | 44 public static class DefaultLabelGenerator |
36 | 45 implements PolygonSeriesLabelGenerator |
37 protected PaintLookup lookup; | 46 { |
38 | 47 public DefaultLabelGenerator() { |
39 protected PolygonPlot plot; | 48 } |
40 | 49 |
50 public String generateLabel(PolygonSeries series) { | |
51 Object label = series.getAttribute("label"); | |
52 return label != null | |
53 ? toString(label) | |
54 : null; | |
55 } | |
56 | |
57 protected String toString(Object label) { | |
58 return label.toString(); | |
59 } | |
60 } // class DefaultLabelGenerator | |
61 | |
62 public static final PolygonSeriesLabelGenerator | |
63 DEFAULT_LABEL_GENERATOR_INSTANCE = new DefaultLabelGenerator(); | |
64 | |
65 protected PaintLookup lookup; | |
66 protected PolygonSeriesLabelGenerator labelGenerator; | |
41 | 67 |
42 public PolygonRenderer(PaintLookup lookup) { | 68 public PolygonRenderer(PaintLookup lookup) { |
43 this(lookup, AREA); | 69 this(lookup, null); |
44 } | 70 } |
45 | 71 |
46 public PolygonRenderer(PaintLookup lookup, int type) { | 72 public PolygonRenderer( |
47 this.lookup = lookup; | 73 PaintLookup lookup, |
48 this.type = type; | 74 PolygonSeriesLabelGenerator labelGenerator |
49 } | 75 ) { |
50 | 76 this.lookup = lookup; |
51 public void draw( | 77 this.labelGenerator = labelGenerator; |
78 } | |
79 | |
80 public void drawPolygons( | |
52 Graphics2D graphics, | 81 Graphics2D graphics, |
53 Rectangle2D rectangle, | 82 Rectangle2D rectangle, |
54 PolygonDataset dataset | 83 PolygonDataset dataset |
55 ) { | 84 ) { |
56 Rectangle2D bbox = getBoundingBox(dataset); | 85 Rectangle2D bbox = getBoundingBox(dataset); |
63 // XXX: Little hack to draw correctly if data is | 92 // XXX: Little hack to draw correctly if data is |
64 // below 0 in y direction. | 93 // below 0 in y direction. |
65 if (bbox.getMinY() <= 0d && bbox.getMaxY() <= 0d) { | 94 if (bbox.getMinY() <= 0d && bbox.getMaxY() <= 0d) { |
66 sy = -sy; // mirror | 95 sy = -sy; // mirror |
67 } | 96 } |
97 | |
98 AffineTransform xform = graphics.getTransform(); | |
68 | 99 |
69 graphics.translate(tx, ty); | 100 graphics.translate(tx, ty); |
70 graphics.scale(sx, sy); | 101 graphics.scale(sx, sy); |
71 | 102 |
72 int seriesCount = dataset.getSeriesCount(); | 103 int seriesCount = dataset.getSeriesCount(); |
86 graphics.setStroke(stroke); | 117 graphics.setStroke(stroke); |
87 graphics.setPaint(Color.black); | 118 graphics.setPaint(Color.black); |
88 graphics.draw(constructShape(series, false)); | 119 graphics.draw(constructShape(series, false)); |
89 } | 120 } |
90 } | 121 } |
122 | |
123 graphics.setTransform(xform); | |
124 } | |
125 | |
126 public void drawLabels( | |
127 final Graphics2D graphics, | |
128 final PolygonPlot plot, | |
129 final Rectangle2D area, | |
130 PolygonDataset dataset | |
131 ) { | |
132 if (labelGenerator == null) { | |
133 return; | |
134 } | |
135 | |
136 final ArrayList<Rectangle2D> bboxes = new ArrayList<Rectangle2D>(); | |
137 | |
138 Font font = graphics.getFont(); | |
139 font = font.deriveFont(Font.PLAIN, Math.max(8, font.getSize()-3)); | |
140 graphics.setFont(font); | |
141 FontMetrics metrics = graphics.getFontMetrics(font); | |
142 | |
143 for (int i = dataset.getSeriesCount()-1; i >= 0; --i) { | |
144 PolygonSeries series = dataset.getSeries(i); | |
145 | |
146 String label = labelGenerator.generateLabel(series); | |
147 if (label == null) { | |
148 continue; | |
149 } | |
150 | |
151 final Rectangle2D box = TextUtilities.getTextBounds( | |
152 label, graphics, metrics); | |
153 | |
154 for (int j = series.getItemCount()-1; j >= 0; --j) { | |
155 final CompactXYItems ring = series.getItem(j); | |
156 LevelOrderIndices loi = new LevelOrderIndices(ring.size()-1); | |
157 Rectangle2D r = (Rectangle2D)loi.visit( | |
158 new LevelOrderIndices.Visitor() | |
159 { | |
160 ValueAxis da = plot.getDomainAxis(); | |
161 ValueAxis ra = plot.getRangeAxis(); | |
162 RectangleEdge de = plot.getDomainAxisEdge(); | |
163 RectangleEdge re = plot.getRangeAxisEdge(); | |
164 Rectangle2D.Double r = new Rectangle2D.Double( | |
165 0d, 0d, box.getWidth(), box.getHeight()); | |
166 | |
167 public Object visit(int index) { | |
168 r.x = da.valueToJava2D(ring.getX(index), area, de) | |
169 - 0.5*box.getWidth(); | |
170 r.y = ra.valueToJava2D(ring.getY(index), area, re) | |
171 + 0.5*box.getHeight(); | |
172 | |
173 for (Rectangle2D b: bboxes) { | |
174 if (b.intersects(r)) { | |
175 return null; | |
176 } | |
177 } | |
178 return r; | |
179 } | |
180 }); | |
181 | |
182 if (r != null) { | |
183 bboxes.add(r); | |
184 graphics.drawString( | |
185 label, (float)r.getX(), (float)r.getY()); | |
186 } | |
187 } // for all items in series | |
188 } // for all series | |
91 } | 189 } |
92 | 190 |
93 protected Shape constructShape(PolygonSeries series, boolean close) { | 191 protected Shape constructShape(PolygonSeries series, boolean close) { |
94 CompactXYItems [] rings = series.getRings(); | 192 CompactXYItems [] rings = series.getRings(); |
95 GeneralPath path = new GeneralPath(); | 193 GeneralPath path = new GeneralPath(); |