changeset 8910:d9c89651bd67

Area chart layers may now have an 'arebgpattern'. Real pattern yet to be defined.
author gernotbelger
date Thu, 22 Feb 2018 18:46:37 +0100
parents 31dff17c6828
children 37ff7f435912
files artifacts/src/main/java/org/dive4elements/river/jfree/AreaFillPattern.java artifacts/src/main/java/org/dive4elements/river/jfree/ColorMapper.java artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java artifacts/src/main/resources/images/areapatterns/pattern1.png gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties gwt-client/src/main/java/org/dive4elements/river/client/client/ui/StyleEditorWindow.java gwt-client/src/main/webapp/images/areapattern-pattern1.png gwt-client/src/main/webapp/images/areapattern-x.png
diffstat 13 files changed, 264 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AreaFillPattern.java	Thu Feb 22 18:46:37 2018 +0100
@@ -0,0 +1,75 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.jfree;
+
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.LookupOp;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Fill patterns for area styles.
+ * REMARK: if this enum is changed, probably the ui in StyleEditorWindow must be changed too
+ *
+ * @author Gernot Belger
+ */
+public enum AreaFillPattern {
+
+    pattern1("/images/areapatterns/pattern1.png");
+
+    private static Logger log = Logger.getLogger(AreaFillPattern.class);
+
+    private static final BufferedImage MISSING_IMAGE = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
+
+    private final String imagePath;
+
+    private BufferedImage image = null;
+
+    AreaFillPattern(final String imagePath) {
+        this.imagePath = imagePath;
+    }
+
+    public BufferedImage getImage(final Color color) {
+
+        if (this.image == null)
+            this.image = loadImage();
+
+        if (color == null)
+            return this.image;
+
+        /*
+         * apply color and transparency, the .png must be encoded as 32bit images (rgba), with only black as non transparent
+         * color
+         */
+        final int numComponents = this.image.getColorModel().getNumComponents();
+        if (numComponents != 4) {
+            log.warn(String.format("Pattern image must be a 32bit image (rgba): %s", this.imagePath));
+            return this.image;
+        }
+
+        final BufferedImageOp lookup = new LookupOp(new ColorMapper(Color.black, color), null);
+        return lookup.filter(this.image, null);
+    }
+
+    private BufferedImage loadImage() {
+        try {
+            return ImageIO.read(getClass().getResource(this.imagePath));
+        }
+        catch (final IOException e) {
+            log.error(String.format("failed ot load pattern: %s", this.imagePath), e);
+            return MISSING_IMAGE;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/ColorMapper.java	Thu Feb 22 18:46:37 2018 +0100
@@ -0,0 +1,43 @@
+/** Copyright (C) 2017 by Bundesanstalt für Gewässerkunde
+ * Software engineering by
+ *  Björnsen Beratende Ingenieure GmbH
+ *  Dr. Schumacher Ingenieurbüro für Wasser und Umwelt
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.jfree;
+
+import java.awt.Color;
+import java.awt.image.LookupTable;
+
+final class ColorMapper extends LookupTable {
+
+    private final int[] from;
+    private final int[] to;
+
+    public ColorMapper(final Color from, final Color to) {
+        super(0, 4);
+
+        this.from = new int[] { from.getRed(), from.getGreen(), from.getBlue(), from.getAlpha(), };
+        this.to = new int[] { to.getRed(), to.getGreen(), to.getBlue(), to.getAlpha(), };
+    }
+
+    @Override
+    public int[] lookupPixel(final int[] src, final int[] dest) {
+        final int[] out = dest == null ? new int[src.length] : dest;
+
+        // REMARK: only compare rgb, so we even keep the transparency level
+        if (src[0] == this.from[0] && src[1] == this.from[1] && src[2] == this.from[2]) {
+            out[0] = this.to[0];
+            out[1] = this.to[1];
+            out[2] = this.to[2];
+            out[2] = src[3];
+        } else {
+            System.arraycopy(src, 0, out, 0, src.length);
+        }
+
+        return out;
+    }
+}
\ No newline at end of file
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java	Thu Feb 22 18:44:28 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StableXYDifferenceRenderer.java	Thu Feb 22 18:46:37 2018 +0100
@@ -407,9 +407,6 @@
      * @see #getPositivePaint()
      */
     public void setPositivePaint(Paint paint) {
-        if (paint == null) {
-            throw new IllegalArgumentException("Null 'paint' argument.");
-        }
         this.positivePaint = paint;
         fireChangeEvent();
     }
@@ -433,9 +430,6 @@
      * @see #getNegativePaint()
      */
     public void setNegativePaint(Paint paint) {
-        if (paint == null) {
-            throw new IllegalArgumentException("Null 'paint' argument.");
-        }
         this.negativePaint = paint;
         notifyListeners(new RendererChangeEvent(this));
     }
@@ -1774,9 +1768,13 @@
         }
 
         if (l_path.intersects(x_dataArea)) {
-            x_graphics.setPaint(x_positive ? getPositivePaint()
-                    : getNegativePaint());
+            
+            final Paint paint = x_positive ? getPositivePaint(): getNegativePaint();
+            if( paint != null ) {
+            x_graphics.setPaint(paint);
             x_graphics.fill(l_path);
+            }
+            
             if (drawOutline) {
                 x_graphics.setStroke(this.outlineStroke);
                 x_graphics.setPaint(this.outlinePaint);
--- a/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java	Thu Feb 22 18:44:28 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/StyledAreaSeriesCollection.java	Thu Feb 22 18:46:37 2018 +0100
@@ -10,7 +10,12 @@
 
 import java.awt.BasicStroke;
 import java.awt.Color;
+import java.awt.Paint;
 import java.awt.Stroke;
+import java.awt.TexturePaint;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
 
 import org.jfree.data.xy.XYSeriesCollection;
 
@@ -23,6 +28,7 @@
  * The display options can be used to control the z-order and the axis of the
  * dataset.
  */
+// FIXME:  bad abstraction: the only purpose of this derivation is to apply specific styles. This should rather be solved similar to the XYSTyle.
 public class StyledAreaSeriesCollection extends XYSeriesCollection {
     private static final long serialVersionUID = 5274940965666948237L;
 
@@ -71,6 +77,7 @@
         applyOutlineStyle(renderer);
         applyShowLine(renderer);
         applyShowAreaLabel(renderer);
+        applyPointStyle(renderer);
         if (mode == FILL_MODE.UNDER) {
             renderer.setAreaCalculationMode(
                 StableXYDifferenceRenderer.CALCULATE_NEGATIVE_AREA);
@@ -89,19 +96,17 @@
         return renderer;
     }
 
-
-    private void applyFillColor(StableXYDifferenceRenderer renderer) {
-        Color paint = theme.parseAreaBackgroundColor();
-
-        int transparency = theme.parseAreaTransparency();
-        if (transparency > 0 && paint != null) {
-            paint = new Color(
-                        paint.getRed(),
-                        paint.getGreen(),
-                        paint.getBlue(),
-                        (int)((100 - transparency) * 2.55f));
+    private void applyFillColor(final StableXYDifferenceRenderer renderer) {
+        
+        final boolean showArea = theme.parseShowArea();
+        if( !showArea ) {
+            renderer.setPositivePaint(null);
+            renderer.setNegativePaint(null);
+            return;
         }
 
+        Paint paint = parseFillPaint();
+        
         if (paint != null && this.getMode() == FILL_MODE.ABOVE) {
             renderer.setPositivePaint(paint);
             renderer.setNegativePaint(new Color(0,0,0,0));
@@ -113,11 +118,40 @@
         else {
             if (paint == null)
                 paint = new Color(177, 117, 102);
+                
             renderer.setPositivePaint(paint);
             renderer.setNegativePaint(paint);
         }
     }
 
+    private Paint parseFillPaint() {
+        final Color paint = this.theme.parseAreaBackgroundColor();
+        final int transparency = theme.parseAreaTransparency();
+        
+        final Color alphaPaint = withAlpha(paint, transparency);
+        
+        final AreaFillPattern pattern = this.theme.parseAreaBackgroundPattern();
+
+        if( pattern == null )
+            return alphaPaint;
+        
+        final BufferedImage image = pattern.getImage(alphaPaint);
+        
+        final Rectangle2D anchor = new Rectangle2D.Double(0,0, image.getWidth(), image.getHeight());
+        return new TexturePaint(image, anchor);
+    }
+
+    private Color withAlpha(final Color color, final int transparency) {
+
+        if (transparency <= 0 || color == null)
+            return color;
+        
+        return new Color(
+                color.getRed(),
+                color.getGreen(),
+                color.getBlue(),
+                (int)((100 - transparency) * 2.55f));
+    }
 
     private void applyShowShape(StableXYDifferenceRenderer renderer) {
         boolean show = theme.parseAreaShowBorder();
@@ -126,7 +160,9 @@
 
 
     private void applyShowLine(StableXYDifferenceRenderer renderer) {
-        boolean show = theme.parseShowLine();
+        /* FIXME: strange: this will enable/disable showing the 'point' shapes at each vertex. */
+        /* FIXME: this will also now be overridden by the option 'showpoints' */
+        final boolean show = theme.parseShowLine();
         renderer.setShapesVisible(show);
     }
 
@@ -161,6 +197,27 @@
         renderer.setOutlineStroke(stroke);
     }
 
+    private void applyPointStyle(final StableXYDifferenceRenderer renderer) {
+
+        final boolean showPoints = this.theme.parseShowPoints();
+        renderer.setShapesVisible(showPoints);
+
+        if( showPoints )
+        {        
+            final int size = theme.parsePointWidth();
+            final int dim  = 2 * size;
+
+            final Ellipse2D pointShape = new Ellipse2D.Double(-size, -size, dim, dim);
+            final Color pointColor = theme.parsePointColor();
+
+            renderer.setSeriesPaint(0, pointColor);
+            renderer.setSeriesPaint(1, pointColor);
+
+            renderer.setSeriesShape(0, pointShape);
+            renderer.setSeriesShape(1, pointShape);
+        }
+    }
+
     public boolean shouldCalculateRange() {
         return theme.parseCalculateRange();
     }
--- a/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java	Thu Feb 22 18:44:28 2018 +0100
+++ b/artifacts/src/main/java/org/dive4elements/river/themes/ThemeDocument.java	Thu Feb 22 18:46:37 2018 +0100
@@ -13,6 +13,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.dive4elements.artifacts.CallMeta;
 import org.dive4elements.river.artifacts.model.MapserverStyle;
@@ -21,6 +22,7 @@
 import org.dive4elements.river.artifacts.model.MapserverStyle.Label;
 import org.dive4elements.river.artifacts.model.MapserverStyle.Style;
 import org.dive4elements.river.artifacts.resources.Resources;
+import org.dive4elements.river.jfree.AreaFillPattern;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
@@ -102,6 +104,8 @@
 
     public final static String AREA_BACKGROUND_COLOR = "areabgcolor";
 
+    private static final String AREA_BACKGROUND_PATTERN = "areabgpattern";
+
     public final static String SYMBOL = "symbol";
 
     public final static String SHOW_MINIMUM = "showminimum";
@@ -825,5 +829,19 @@
     private String getCalculateRangeString() {
         return getValue(CALCULATE_RANGE);
     }
+
+    public AreaFillPattern parseAreaBackgroundPattern() {
+        final String patternName = getValue(AREA_BACKGROUND_PATTERN);
+        if( StringUtils.isBlank(patternName) )
+            return null;
+        
+        try {
+            return AreaFillPattern.valueOf(patternName);
+        }
+        catch (Exception e) {
+            log.error(String.format("%s: invalid pattern name: %s", AREA_BACKGROUND_PATTERN, patternName), e);
+            return null;
+        }
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
Binary file artifacts/src/main/resources/images/areapatterns/pattern1.png has changed
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Thu Feb 22 18:44:28 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.java	Thu Feb 22 18:46:37 2018 +0100
@@ -1178,6 +1178,8 @@
 
     String areabgcolor();
 
+    String areabgpattern();
+
     String areashowborder();
 
     String areashowbg();
@@ -1423,13 +1425,17 @@
     String error_no_sedimentloadinfo_data();
 
     String sinfo();
-    
+
     String sinfo_flowdepth_export();
 
     String sinfo_flowdepth_report();
 
     String sinfo_flow_depth();
 
-	String sinfo_flowdepth_twinpanel_no_pair_selected();
+    String sinfo_flowdepth_twinpanel_no_pair_selected();
+
+    String sinfo_flow_depths();
+
+    String sinfo_tkhs();
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Thu Feb 22 18:44:28 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants.properties	Thu Feb 22 18:46:37 2018 +0100
@@ -636,6 +636,7 @@
 showmiddleheight = Show middle depth
 fillcolor = Fill Color
 areabgcolor = Fill Color
+areabgpattern = Fill Pattern
 areashowborder = Show area border
 areashowbg = Show area background
 areabordercolor = Border color
@@ -761,4 +762,6 @@
 sinfo_flowdepth_export = Flie\u00dftiefen Export
 sinfo_flowdepth_report = Flie\u00dftiefen Bericht
 sinfo_flow_depth = Flie\u00dftiefen
-sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
\ No newline at end of file
+sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
+sinfo_flow_depths = Flie\u00dftiefen
+sinfo_tkhs = Transportk\u00f6rperh\u00f6hen
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Thu Feb 22 18:44:28 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_de.properties	Thu Feb 22 18:46:37 2018 +0100
@@ -635,11 +635,12 @@
 showborder = Linie anzeigen
 transparent = Transparent
 transparency = Transparenz
-showarea = Show area
+showarea = Fl\u00e4che anzeigen
 showarealabel = Fl\u00e4che beschriften
 showmiddleheight = Mittlere Tiefe anzeigen
 fillcolor = F\u00fcllfarbe
 areabgcolor = F\u00fcllfarbe
+areabgpattern = Fl\u00e4chentyp
 areashowborder = Fl\u00e4chenumrandung
 areashowbg = Fl\u00e4chenhintergrund
 areabordercolor = Umrandungsfarbe
@@ -753,4 +754,6 @@
 sinfo_flowdepth_export = Flie\u00dftiefen Export
 sinfo_flowdepth_report = Flie\u00dftiefen Bericht
 sinfo_flow_depth = Flie\u00dftiefen
-sinfo_flowdepth_twinpanel_no_pair_selected = Fehler - kein Paar zur Differenzenbildung gew\u00e4hlt.
\ No newline at end of file
+sinfo_flowdepth_twinpanel_no_pair_selected = Fehler - kein Paar zur Differenzenbildung gew\u00e4hlt.
+sinfo_flow_depths = Flie\u00dftiefen
+sinfo_tkhs = Transportk\u00f6rperh\u00f6hen
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Thu Feb 22 18:44:28 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/FLYSConstants_en.properties	Thu Feb 22 18:46:37 2018 +0100
@@ -615,6 +615,7 @@
 showmiddleheight = Show middle depth
 fillcolor = Fill Color
 areabgcolor = Fill Color
+areabgpattern = Fill Pattern
 areashowborder = Show area border
 areashowbg = Show area background
 areabordercolor = Border color
@@ -790,4 +791,6 @@
 sinfo_flowdepth_export = Flie\u00dftiefen Export
 sinfo_flowdepth_report = Flie\u00dftiefen Bericht
 sinfo_flow_depth = Flie\u00dftiefen
-sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
\ No newline at end of file
+sinfo_flowdepth_twinpanel_no_pair_selected = Error - at least one input pair must be selected
+sinfo_flow_depths = Flie\u00dftiefen
+sinfo_tkhs = Transportk\u00f6rperh\u00f6hen
\ No newline at end of file
--- a/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/StyleEditorWindow.java	Thu Feb 22 18:44:28 2018 +0100
+++ b/gwt-client/src/main/java/org/dive4elements/river/client/client/ui/StyleEditorWindow.java	Thu Feb 22 18:46:37 2018 +0100
@@ -294,6 +294,7 @@
 
         // Done via array to keep the order.
         String[] sets = {"showlines",
+                         "showborder",
                          "showpoints",
                          "linetype",
                          "linesize",
@@ -372,6 +373,7 @@
      * @return The dynamic form for the attribute property.
      */
     protected DynamicForm createPropertyUI(
+        // FIXME: display name (which comes from the server side) is not used but i10n happens on client side,, 
         String dname,
         String name,
         String type,
@@ -535,6 +537,9 @@
             f.setValueMap(valueMap);
             f.setValue(value);
         }
+        else if (type.equals("areapattern")) {
+            f = createAreaPetternUi(name, value);
+        }
         else if (type.equals("font")) {
             f = new SelectItem(name, MSG.getString(name));
             LinkedHashMap<String, String> valueMap =
@@ -587,6 +592,33 @@
     }
 
 
+    private FormItem createAreaPetternUi(String name, String value) {
+        final FormItem f = new SelectItem(name, MSG.getString(name));
+        
+        f.setImageURLPrefix(GWT.getHostPageBaseURL() + "images/areapattern-");
+        f.setImageURLSuffix(".png");
+        f.setValueIconHeight(20);
+        f.setValueIconWidth(80);
+
+        final LinkedHashMap<String, String> valueMap = new LinkedHashMap<String, String>();
+        final Map<String, String> valueIcons = new LinkedHashMap<String, String>();
+
+        // FIXME: ugly, using knowledge of available patterns at this point, creating redundancy with AreaFillPattern enum.
+        // But the whole code does it like that, so this is 'flys style'
+        final String[] patterns = new String[] {"pattern1", "x"};
+        for (int i = 0; i < patterns.length; i++) {
+            final String pattern = patterns[i];
+
+            valueMap.put(pattern, "");
+            valueIcons.put(pattern, pattern);
+        }
+
+        f.setValueIcons(valueIcons);
+        f.setValueMap(valueMap);
+        f.setValue(value);
+        return f;
+    }
+
     protected FormItem createLineSizeUI(FormItem f) {
         LinkedHashMap<String, String> valueIcons =
             new LinkedHashMap<String, String>();
Binary file gwt-client/src/main/webapp/images/areapattern-pattern1.png has changed
Binary file gwt-client/src/main/webapp/images/areapattern-x.png has changed

http://dive4elements.wald.intevation.org