Mercurial > dive4elements > river
comparison artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java @ 9496:d8e753d0fdb9
stripedArea introduced for Assessment Scheme/Bewertungsschema
author | gernotbelger |
---|---|
date | Wed, 26 Sep 2018 15:48:05 +0200 |
parents | eec4df8165a1 |
children | ef5754ba5573 |
comparison
equal
deleted
inserted
replaced
9495:bb278c927b66 | 9496:d8e753d0fdb9 |
---|---|
8 | 8 |
9 package org.dive4elements.river.jfree; | 9 package org.dive4elements.river.jfree; |
10 | 10 |
11 import java.awt.BasicStroke; | 11 import java.awt.BasicStroke; |
12 import java.awt.Color; | 12 import java.awt.Color; |
13 import java.awt.Font; | |
13 import java.awt.Paint; | 14 import java.awt.Paint; |
14 import java.awt.Stroke; | 15 import java.awt.Stroke; |
15 import java.awt.TexturePaint; | 16 import java.awt.TexturePaint; |
16 import java.awt.geom.Ellipse2D; | 17 import java.awt.geom.Ellipse2D; |
17 import java.awt.geom.Rectangle2D; | 18 import java.awt.geom.Rectangle2D; |
18 import java.awt.image.BufferedImage; | 19 import java.awt.image.BufferedImage; |
19 | 20 |
21 import org.apache.log4j.Logger; | |
22 import org.dive4elements.artifacts.CallMeta; | |
23 import org.dive4elements.river.artifacts.resources.Resources; | |
24 import org.dive4elements.river.java2d.ShapeUtils; | |
20 import org.dive4elements.river.themes.ThemeDocument; | 25 import org.dive4elements.river.themes.ThemeDocument; |
26 import org.dive4elements.river.utils.Formatter; | |
27 import org.jfree.chart.LegendItem; | |
28 import org.jfree.chart.LegendItemCollection; | |
29 import org.jfree.chart.plot.XYPlot; | |
21 import org.jfree.data.xy.XYSeriesCollection; | 30 import org.jfree.data.xy.XYSeriesCollection; |
22 | 31 |
23 /** | 32 /** |
24 * One or more dataseries to draw a polygon (either "open up/downwards", or | 33 * One or more dataseries to draw a polygon (either "open up/downwards", or |
25 * the area between two curves), a theme-document and further display options. | 34 * the area between two curves), a theme-document and further display options. |
26 * The theme-document will later "style" the graphical representation. | 35 * The theme-document will later "style" the graphical representation. |
27 * The display options can be used to control the z-order and the axis of the | 36 * The display options can be used to control the z-order and the axis of the |
28 * dataset. | 37 * dataset. |
29 */ | 38 */ |
30 // FIXME: bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved similar to the XYSTyle. | 39 // FIXME: bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved |
31 public class StyledAreaSeriesCollection extends XYSeriesCollection { | 40 // similar to the XYSTyle. |
41 public class StyledAreaSeriesCollection extends XYSeriesCollection implements StyledXYDataset { | |
32 private static final long serialVersionUID = 5274940965666948237L; | 42 private static final long serialVersionUID = 5274940965666948237L; |
33 | 43 |
44 private static final Logger log = Logger.getLogger(StyledAreaSeriesCollection.class); | |
45 | |
34 /** Mode, how to draw/which areas to fill. */ | 46 /** Mode, how to draw/which areas to fill. */ |
35 public enum FILL_MODE {UNDER, ABOVE, BETWEEN} | 47 public enum FILL_MODE { |
48 UNDER, ABOVE, BETWEEN | |
49 } | |
36 | 50 |
37 /** MODE in use. */ | 51 /** MODE in use. */ |
38 private FILL_MODE mode; | 52 private FILL_MODE mode; |
39 | 53 |
40 /** Theme-document with attributes about actual visual representation. */ | 54 /** Theme-document with attributes about actual visual representation. */ |
41 private final ThemeDocument theme; | 55 private final ThemeDocument theme; |
42 | 56 |
43 /** | 57 /** |
44 * @param theme the theme-document. | 58 * @param theme |
59 * the theme-document. | |
45 */ | 60 */ |
46 public StyledAreaSeriesCollection(final ThemeDocument theme) { | 61 public StyledAreaSeriesCollection(final ThemeDocument theme) { |
47 this.theme = theme; | 62 this.theme = theme; |
48 this.mode = FILL_MODE.BETWEEN; | 63 this.mode = FILL_MODE.BETWEEN; |
49 } | 64 } |
50 | 65 |
51 | |
52 /** Gets the Fill mode. */ | 66 /** Gets the Fill mode. */ |
53 public FILL_MODE getMode() { | 67 private FILL_MODE getMode() { |
54 return this.mode; | 68 return this.mode; |
55 } | 69 } |
56 | |
57 | 70 |
58 /** Sets the Fill mode. */ | 71 /** Sets the Fill mode. */ |
59 public void setMode(final FILL_MODE fMode) { | 72 public void setMode(final FILL_MODE fMode) { |
60 this.mode = fMode; | 73 this.mode = fMode; |
61 } | 74 } |
62 | 75 |
76 @Override | |
77 public void applyTheme(final CallMeta callMeta, final XYPlot plot, final int datasetIndex, final Font legendFont) { | |
78 | |
79 final LegendItemCollection lic = new LegendItemCollection(); | |
80 final LegendItemCollection anno = plot.getFixedLegendItems(); | |
81 | |
82 log.debug("Registering an 'area'renderer at idx: " + datasetIndex); | |
83 | |
84 final StableXYDifferenceRenderer dRenderer = new StableXYDifferenceRenderer(); | |
85 | |
86 if (getMode() == StyledAreaSeriesCollection.FILL_MODE.UNDER) { | |
87 dRenderer.setPositivePaint(createTransparentPaint()); | |
88 } | |
89 | |
90 plot.setRenderer(datasetIndex, dRenderer); | |
91 | |
92 applyTheme(dRenderer); | |
93 | |
94 // i18n | |
95 dRenderer.setAreaLabelNumberFormat(Formatter.getFormatter(callMeta, 2, 4)); | |
96 | |
97 dRenderer.setAreaLabelTemplate(Resources.getMsg(callMeta, "area.label.template", "Area=%sm2")); | |
98 | |
99 final LegendItem legendItem = dRenderer.getLegendItem(datasetIndex, 0); | |
100 if (legendItem != null) { | |
101 legendItem.setLabelFont(legendFont); | |
102 lic.add(legendItem); | |
103 } else { | |
104 log.warn("Could not get LegentItem for renderer: " + datasetIndex + ", series-idx " + 0); | |
105 } | |
106 | |
107 if (anno != null) { | |
108 lic.addAll(anno); | |
109 } | |
110 | |
111 plot.setFixedLegendItems(lic); | |
112 } | |
113 | |
114 /** | |
115 * Returns a transparently textured paint. | |
116 * | |
117 * @return a transparently textured paint. | |
118 */ | |
119 private static Paint createTransparentPaint() { | |
120 // TODO why not use a transparent color? | |
121 final BufferedImage texture = new BufferedImage(1, 1, BufferedImage.TYPE_4BYTE_ABGR); | |
122 | |
123 return new TexturePaint(texture, new Rectangle2D.Double(0d, 0d, 0d, 0d)); | |
124 } | |
63 | 125 |
64 /** | 126 /** |
65 * Applies line color, size and type attributes to renderer, also | 127 * Applies line color, size and type attributes to renderer, also |
66 * whether to draw lines and/or points. | 128 * whether to draw lines and/or points. |
67 * @param renderer Renderer to apply theme to. | 129 * |
130 * @param renderer | |
131 * Renderer to apply theme to. | |
68 * @return \param renderer | 132 * @return \param renderer |
69 */ | 133 */ |
70 public StableXYDifferenceRenderer applyTheme( | 134 private StableXYDifferenceRenderer applyTheme(final StableXYDifferenceRenderer renderer) { |
71 final StableXYDifferenceRenderer renderer | |
72 ) { | |
73 applyFillColor(renderer); | 135 applyFillColor(renderer); |
74 applyShowBorder(renderer); | 136 applyShowBorder(renderer); |
75 applyShowArea(renderer); | 137 applyShowArea(renderer); |
76 applyOutlineColor(renderer); | 138 applyOutlineColor(renderer); |
77 applyOutlineStyle(renderer); | 139 applyOutlineStyle(renderer); |
79 applyShowAreaLabel(renderer); | 141 applyShowAreaLabel(renderer); |
80 applyShowLineLabel(renderer); | 142 applyShowLineLabel(renderer); |
81 applyPointStyle(renderer); | 143 applyPointStyle(renderer); |
82 applyShowMinimumMaximum(renderer); | 144 applyShowMinimumMaximum(renderer); |
83 if (this.mode == FILL_MODE.UNDER) { | 145 if (this.mode == FILL_MODE.UNDER) { |
84 renderer.setAreaCalculationMode( | 146 renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); |
85 StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA); | 147 } else if (this.mode == FILL_MODE.ABOVE) { |
86 } | 148 renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); |
87 else if (this.mode == FILL_MODE.ABOVE) { | 149 } else { |
88 renderer.setAreaCalculationMode( | 150 renderer.setAreaCalculationMode(StableXYDifferenceRenderer.CALCULATE_ALL_AREA); |
89 StableXYDifferenceRenderer.CALCULATE_POSITIVE_AREA); | |
90 } | |
91 else { | |
92 renderer.setAreaCalculationMode( | |
93 StableXYDifferenceRenderer.CALCULATE_ALL_AREA); | |
94 } | 151 } |
95 | 152 |
96 // Apply text style. | 153 // Apply text style. |
97 this.theme.parseComplexTextStyle().apply(renderer); | 154 this.theme.parseComplexTextStyle().apply(renderer); |
98 return renderer; | 155 return renderer; |
113 | 170 |
114 Paint paint = parseFillPaint(); | 171 Paint paint = parseFillPaint(); |
115 | 172 |
116 if (paint != null && this.getMode() == FILL_MODE.ABOVE) { | 173 if (paint != null && this.getMode() == FILL_MODE.ABOVE) { |
117 renderer.setPositivePaint(paint); | 174 renderer.setPositivePaint(paint); |
118 renderer.setNegativePaint(new Color(0,0,0,0)); | 175 renderer.setNegativePaint(new Color(0, 0, 0, 0)); |
119 } | 176 } else if (paint != null && this.getMode() == FILL_MODE.UNDER) { |
120 else if (paint != null && this.getMode() == FILL_MODE.UNDER) { | |
121 renderer.setNegativePaint(paint); | 177 renderer.setNegativePaint(paint); |
122 renderer.setPositivePaint(new Color(0,0,0,0)); | 178 renderer.setPositivePaint(new Color(0, 0, 0, 0)); |
123 } | 179 } else { |
124 else { | |
125 if (paint == null) | 180 if (paint == null) |
126 paint = new Color(177, 117, 102); | 181 paint = new Color(177, 117, 102); |
127 | 182 |
128 renderer.setPositivePaint(paint); | 183 renderer.setPositivePaint(paint); |
129 renderer.setNegativePaint(paint); | 184 renderer.setNegativePaint(paint); |
132 | 187 |
133 private Paint parseFillPaint() { | 188 private Paint parseFillPaint() { |
134 final Color paint = this.theme.parseAreaBackgroundColor(); | 189 final Color paint = this.theme.parseAreaBackgroundColor(); |
135 final int transparency = this.theme.parseAreaTransparency(); | 190 final int transparency = this.theme.parseAreaTransparency(); |
136 | 191 |
137 final Color alphaPaint = withAlpha(paint, transparency); | 192 final Color alphaPaint = ShapeUtils.withAlpha(paint, transparency); |
138 | 193 |
139 final AreaFillPattern pattern = this.theme.parseAreaBackgroundPattern(); | 194 final AreaFillPattern pattern = this.theme.parseAreaBackgroundPattern(); |
140 | 195 |
141 if( pattern == null || pattern == AreaFillPattern.patternFill ) | 196 if (pattern == null || pattern == AreaFillPattern.patternFill) |
142 return alphaPaint; | 197 return alphaPaint; |
143 | 198 |
144 final BufferedImage image = pattern.getImage(alphaPaint); | 199 final BufferedImage image = pattern.getImage(alphaPaint); |
145 | 200 |
146 final Rectangle2D anchor = new Rectangle2D.Double(0,0, image.getWidth(), image.getHeight()); | 201 final Rectangle2D anchor = new Rectangle2D.Double(0, 0, image.getWidth(), image.getHeight()); |
147 return new TexturePaint(image, anchor); | 202 return new TexturePaint(image, anchor); |
148 } | |
149 | |
150 private Color withAlpha(final Color color, final int transparency) { | |
151 | |
152 if (transparency <= 0 || color == null) | |
153 return color; | |
154 | |
155 return new Color( | |
156 color.getRed(), | |
157 color.getGreen(), | |
158 color.getBlue(), | |
159 (int)((100 - transparency) * 2.55f)); | |
160 } | 203 } |
161 | 204 |
162 private void applyShowBorder(final StableXYDifferenceRenderer renderer) { | 205 private void applyShowBorder(final StableXYDifferenceRenderer renderer) { |
163 final boolean show = this.theme.parseAreaShowBorder(); | 206 final boolean show = this.theme.parseAreaShowBorder(); |
164 renderer.setDrawOutline(show); | 207 renderer.setDrawOutline(show); |
193 renderer.setShowTitleLabel(showLabelLine); | 236 renderer.setShowTitleLabel(showLabelLine); |
194 } | 237 } |
195 | 238 |
196 private void applyOutlineStyle(final StableXYDifferenceRenderer renderer) { | 239 private void applyOutlineStyle(final StableXYDifferenceRenderer renderer) { |
197 final float[] dashes = this.theme.parseLineStyle(); | 240 final float[] dashes = this.theme.parseLineStyle(); |
198 final int size = this.theme.parseLineWidth(); | 241 final int size = this.theme.parseLineWidth(); |
199 | 242 |
200 Stroke stroke = null; | 243 Stroke stroke = null; |
201 | 244 |
202 if (dashes.length <= 1) { | 245 if (dashes.length <= 1) { |
203 stroke = new BasicStroke(Integer.valueOf(size)); | 246 stroke = new BasicStroke(Integer.valueOf(size)); |
204 } | 247 } else { |
205 else { | 248 stroke = new BasicStroke(Integer.valueOf(size), BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND, 1.0f, dashes, 0.0f); |
206 stroke = new BasicStroke(Integer.valueOf(size), | |
207 BasicStroke.CAP_BUTT, | |
208 BasicStroke.JOIN_ROUND, | |
209 1.0f, | |
210 dashes, | |
211 0.0f); | |
212 } | 249 } |
213 | 250 |
214 renderer.setOutlineStroke(stroke); | 251 renderer.setOutlineStroke(stroke); |
215 } | 252 } |
216 | 253 |
217 private void applyPointStyle(final StableXYDifferenceRenderer renderer) { | 254 private void applyPointStyle(final StableXYDifferenceRenderer renderer) { |
218 | 255 |
219 final boolean showPoints = this.theme.parseShowPoints(); | 256 final boolean showPoints = this.theme.parseShowPoints(); |
220 renderer.setShapesVisible(showPoints); | 257 renderer.setShapesVisible(showPoints); |
221 | 258 |
222 if( showPoints ) | 259 if (showPoints) { |
223 { | |
224 final int size = this.theme.parsePointWidth(); | 260 final int size = this.theme.parsePointWidth(); |
225 final int dim = 2 * size; | 261 final int dim = 2 * size; |
226 | 262 |
227 final Ellipse2D pointShape = new Ellipse2D.Double(-size, -size, dim, dim); | 263 final Ellipse2D pointShape = new Ellipse2D.Double(-size, -size, dim, dim); |
228 final Color pointColor = this.theme.parsePointColor(); | 264 final Color pointColor = this.theme.parsePointColor(); |
229 | 265 |
230 renderer.setSeriesPaint(0, pointColor); | 266 renderer.setSeriesPaint(0, pointColor); |