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);

http://dive4elements.wald.intevation.org