/[schmitzm]/trunk/src/skrueger/geotools/LegendIconFeatureRenderer.java
ViewVC logotype

Diff of /trunk/src/skrueger/geotools/LegendIconFeatureRenderer.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 244 by alfonx, Wed Jul 29 09:33:33 2009 UTC revision 1231 by alfonx, Thu Nov 4 00:53:20 2010 UTC
# Line 2  Line 2 
2   * Copyright (c) 2009 Martin O. J. Schmitz.   * Copyright (c) 2009 Martin O. J. Schmitz.
3   *   *
4   * This file is part of the SCHMITZM library - a collection of utility   * This file is part of the SCHMITZM library - a collection of utility
5   * classes based on Java 1.6, focussing (not only) on Java Swing   * classes based on Java 1.6, focusing (not only) on Java Swing
6   * and the Geotools library.   * and the Geotools library.
7   *   *
8   * The SCHMITZM project is hosted at:   * The SCHMITZM project is hosted at:
# Line 25  Line 25 
25   *   *
26   * Contributors:   * Contributors:
27   *     Martin O. J. Schmitz - initial API and implementation   *     Martin O. J. Schmitz - initial API and implementation
28   *     Stefan A. Krüger - additional utility classes   *     Stefan A. Tzeggai - additional utility classes
29   ******************************************************************************/   ******************************************************************************/
30  /**  /**
31   Copyright 2008 Stefan Alfons Krüger and parts from some Geotools code     Copyright 2008 Stefan Alfons Tzeggai and parts from some Geotools code  
32    
33   atlas-framework - This file is part of the Atlas Framework   atlas-framework - This file is part of the Atlas Framework
34    
35   This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.   This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
# Line 42  Line 42 
42   **/   **/
43  package skrueger.geotools;  package skrueger.geotools;
44    
 import java.awt.Canvas;  
45  import java.awt.Color;  import java.awt.Color;
46  import java.awt.Dimension;  import java.awt.Dimension;
 import java.awt.FontMetrics;  
 import java.awt.Graphics;  
47  import java.awt.Graphics2D;  import java.awt.Graphics2D;
48  import java.awt.RenderingHints;  import java.awt.RenderingHints;
49  import java.awt.image.BufferedImage;  import java.awt.image.BufferedImage;
 import java.awt.image.ImageObserver;  
 import java.util.ArrayList;  
 import java.util.List;  
50    
51  import javax.swing.tree.DefaultTreeCellRenderer;  import javax.swing.tree.DefaultTreeCellRenderer;
52    
53  import org.apache.log4j.Logger;  import org.apache.log4j.Logger;
54  import org.geotools.factory.GeoTools;  import org.geotools.factory.GeoTools;
55  import org.geotools.factory.Hints;  import org.geotools.factory.Hints;
 import org.geotools.feature.AttributeType;  
 import org.geotools.feature.Feature;  
 import org.geotools.feature.FeatureType;  
56  import org.geotools.feature.IllegalAttributeException;  import org.geotools.feature.IllegalAttributeException;
57  import org.geotools.geometry.jts.LiteShape2;  import org.geotools.geometry.jts.LiteShape2;
58  import org.geotools.renderer.lite.StyledShapePainter;  import org.geotools.renderer.lite.StyledShapePainter;
# Line 76  import org.geotools.styling.Style; Line 67  import org.geotools.styling.Style;
67  import org.geotools.styling.Symbolizer;  import org.geotools.styling.Symbolizer;
68  import org.geotools.styling.TextSymbolizer;  import org.geotools.styling.TextSymbolizer;
69  import org.geotools.util.NumberRange;  import org.geotools.util.NumberRange;
70    import org.opengis.feature.simple.SimpleFeature;
71    import org.opengis.feature.simple.SimpleFeatureType;
72    import org.opengis.feature.type.AttributeDescriptor;
73    
74  import schmitzm.geotools.feature.FeatureUtil;  import schmitzm.geotools.feature.FeatureUtil;
75    
# Line 92  import com.vividsolutions.jts.geom.Polyg Line 86  import com.vividsolutions.jts.geom.Polyg
86   * <br>   * <br>
87   * <ul>   * <ul>
88   * <li>07.02.2008:<br>   * <li>07.02.2008:<br>
89   * Determining the default values of a {@link FeatureType} by   * Determining the default values of a {@link SimpleFeatureType} by
90   * {@link FeatureUtil#getDefaultAttributeValues(FeatureType)} instead of using   * {@link FeatureUtil#getDefaultAttributeValues(SimpleFeatureType)} instead of
91   * {@link AttributeType#createDefaultValue()} directly, because the latter   * using {@link AttributeDescriptor#createDefaultValue()} directly, because the
92   * returns {@code null} even though the attribut is not nillable.</li>   * latter returns {@code null} even though the attribut is not nillable.</li>
93   * </ul>   * </ul>
94   *   *
95   * @author Stefan Alfons Krüger   * @author Stefan Alfons Tzeggai
96   */   */
97  public class LegendIconFeatureRenderer extends DefaultTreeCellRenderer {  public class LegendIconFeatureRenderer extends DefaultTreeCellRenderer {
98          private static final Dimension SIZE = new Dimension(30,20);          // private static final Dimension SIZE = new Dimension(30,20);
99    
100          Logger LOGGER = Logger.getLogger(LegendIconFeatureRenderer.class);          Logger LOGGER = Logger.getLogger(LegendIconFeatureRenderer.class);
101    
# Line 115  public class LegendIconFeatureRenderer e Line 109  public class LegendIconFeatureRenderer e
109    
110          public static LegendIconFeatureRenderer getInstance() {          public static LegendIconFeatureRenderer getInstance() {
111                  // In GT 2.4.5 it we have to create a new one all the time!                  // In GT 2.4.5 it we have to create a new one all the time!
112    
113                    // TODO TEST, whether we still need to recreate the renderer here....
114                    // TODO TEST, whether we still need to recreate the renderer here....
115                    // TODO TEST, whether we still need to recreate the renderer here....
116                    // TODO TEST, whether we still need to recreate the renderer here....
117                    // TODO TEST, whether we still need to recreate the renderer here....
118                    // TODO TEST, whether we still need to recreate the renderer here....
119                    // TODO TEST, whether we still need to recreate the renderer here....
120                    // TODO TEST, whether we still need to recreate the renderer here....
121                  return new LegendIconFeatureRenderer();                  return new LegendIconFeatureRenderer();
122  //               return instance;                  // return instance;
123          }          }
124    
         /** The image produced at <code>produceLegendGraphic</code> */  
         private BufferedImage legendGraphic;  
   
125          /**          /**
126           * used to create sample point shapes with LiteShape (not lines nor           * used to create sample point shapes with LiteShape (not lines nor
127           * polygons)           * polygons)
128           */           */
129          private static final GeometryFactory geomFac = new GeometryFactory();          private static final GeometryFactory geomFac = FeatureUtil.GEOMETRY_FACTORY;
130    
131          /** padding percentage factor at both sides of the legend. */          /** padding percentage factor at both sides of the legend. */
132          private static final float hpaddingFactor = 0.11f; // was 0.15          private static final float hpaddingFactor = 0.11f; // was 0.15
# Line 135  public class LegendIconFeatureRenderer e Line 135  public class LegendIconFeatureRenderer e
135          private static final float vpaddingFactor = 0.08f; // was 0.15          private static final float vpaddingFactor = 0.08f; // was 0.15
136    
137          /**          /**
          * Image observer to help in creating the stack like legend graphic from the  
          * images created for each rule  
          */  
         private static final ImageObserver imgObs = new Canvas();  
   
         /**  
138           * Just a holder to avoid creating many polygon shapes from inside           * Just a holder to avoid creating many polygon shapes from inside
139           * <code>getSampleShape()</code>           * <code>getSampleShape()</code>
140           */           */
# Line 228  public class LegendIconFeatureRenderer e Line 222  public class LegendIconFeatureRenderer e
222                                                  legendHeight / 2);                                                  legendHeight / 2);
223    
224                                  try {                                  try {
225                                          this.samplePoint = new LiteShape2(geomFac                                          this.samplePoint = new LiteShape2(
226                                                          .createPoint(coord), null, null, false);                                                          geomFac.createPoint(coord), null, null, false);
227                                  } catch (Exception e) {                                  } catch (Exception e) {
228                                          this.samplePoint = null;                                          this.samplePoint = null;
229                                  }                                  }
# Line 240  public class LegendIconFeatureRenderer e Line 234  public class LegendIconFeatureRenderer e
234                          throw new IllegalArgumentException("Unknown symbolizer: "                          throw new IllegalArgumentException("Unknown symbolizer: "
235                                          + symbolizer);                                          + symbolizer);
236                  }                  }
   
237                  return sampleShape;                  return sampleShape;
238          }          }
239    
240          /**          /**
          * Puts a BufferedImage into this.legendGraphic  
          */  
         public void produceLegendGraphic(FeatureType featureType, Style gt2Style,  
                         Rule[] applicableRules) {  
   
                 // final FeatureTypeStyle[] ftStyles = gt2Style.getFeatureTypeStyles();  
   
                 // if (request.getRule() != null) {  
                 // applicableRules = new Rule[] { request.getRule() };  
                 // } else {  
                 // applicableRules = getApplicableRules(ftStyles, scaleDenominator);  
                 // }  
   
                 final int ruleCount = applicableRules.length;  
   
                 /**  
                  * A legend graphic is produced for each applicable rule. They're being  
                  * holded here until the process is done and then painted on a "stack"  
                  * like legend.  
                  */  
                 final List<BufferedImage> legendsStack = new ArrayList<BufferedImage>(  
                                 ruleCount);  
   
                 for (int i = 0; i < ruleCount; i++) {  
                         BufferedImage image = createImageForRule(applicableRules[i],  
                                         featureType, SIZE);  
                         legendsStack.add(image);  
                 }  
   
                 // this.legendGraphic =  
                 // scaleImage(mergeLegends(legendsStack,applicableRules), request);  
                 this.legendGraphic = mergeLegends(legendsStack, applicableRules);  
         }  
   
         /**  
          * Recieves a list of <code>BufferedImages</code> and produces a new one  
          * which holds all the images in <code>imageStack</code> one above the  
          * other.  
          *  
          * @param imageStack  
          *            the list of BufferedImages, one for each applicable Rule  
          * @param rules  
          *            The applicable rules, one for each image in the stack  
          * @param request  
          *            The request.  
          *  
          * @return the stack image with all the images on the argument list.  
          *  
          * @throws IllegalArgumentException  
          *             if the list is empty  
          */  
         private static BufferedImage mergeLegends(List<BufferedImage> imageStack,  
                         Rule[] rules) {  
                 if (imageStack.size() == 0) {  
                         throw new IllegalArgumentException("No legend graphics passed");  
                 }  
   
                 BufferedImage finalLegend = null;  
   
                 if (imageStack.size() == 1) {  
                         finalLegend = (BufferedImage) imageStack.get(0);  
                 } else {  
                         final int imgCount = imageStack.size();  
                         final String[] labels = new String[imgCount];  
   
                         BufferedImage img = ((BufferedImage) imageStack.get(0));  
                         FontMetrics fontMetrics = img.getGraphics().getFontMetrics();  
   
                         final int rowHeight = Math.max(fontMetrics.getHeight(), img  
                                         .getHeight());  
   
                         // calculate the total dimensions of the image  
                         int totalHeight = rowHeight * imgCount;  
                         int totalWidth = 0;  
   
                         for (int i = 0; i < imgCount; i++) {  
                                 img = (BufferedImage) imageStack.get(i);  
   
                                 Rule rule = rules[i];  
   
                                 // does this rule have a label  
                                 labels[i] = rule.getTitle();  
   
                                 if (labels[i] == null) {  
                                         labels[i] = rule.getName();  
                                 }  
   
                                 int w = img.getWidth();  
   
                                 if (labels[i] != null) {  
                                         Graphics g = img.getGraphics();  
                                         w += g.getFontMetrics().stringWidth(labels[i]);  
                                 }  
   
                                 totalWidth = Math.max(w, totalWidth);  
                         }  
   
                         // create the final image  
                         finalLegend = new BufferedImage(totalWidth, totalHeight,  
                                         BufferedImage.TYPE_INT_ARGB);  
   
                         Graphics2D finalGraphics = finalLegend.createGraphics();  
   
                         finalGraphics.setColor(Color.white);  
                         finalGraphics.fillRect(0, 0, totalWidth, totalHeight);  
   
                         int h = 0;  
   
                         for (int i = 0; i < imgCount; i++) {  
                                 img = (BufferedImage) imageStack.get(i);  
   
                                 // draw the image  
                                 int y = h;  
   
                                 if (img.getHeight() < rowHeight) {  
                                         // move the image to the center of the row  
                                         y += (int) ((rowHeight - img.getHeight()) / 2d);  
                                 }  
   
                                 finalGraphics.drawImage(img, 0, y, imgObs);  
   
                                 // draw the label  
                                 if (labels[i] != null) {  
                                         finalGraphics.setColor(Color.BLACK);  
   
                                         y = (h + rowHeight) - fontMetrics.getDescent();  
   
                                         if (fontMetrics.getHeight() < rowHeight) {  
                                                 // move the baseline to the center of the row  
                                                 y -= (int) ((rowHeight - fontMetrics.getHeight()) / 2d);  
                                         }  
   
                                         finalGraphics.drawString(labels[i], img.getWidth(), y);  
                                 }  
   
                                 h += rowHeight;  
                         }  
                 }  
   
                 return finalLegend;  
         }  
   
         /**  
          * DOCUMENT ME!  
          *  
          * @return  
          *  
          * @throws IllegalStateException  
          *             DOCUMENT ME!  
          */  
         public BufferedImage getLegendGraphic() {  
                 if (this.legendGraphic == null) {  
                         throw new IllegalStateException();  
                 }  
                 return this.legendGraphic;  
         }  
   
         // /**  
         // * Paints a little rectangle in the color defined by the  
         // * {@link ColorMapEntry}  
         // *  
         // * unused  
         // *  
         // * @param cme  
         // * {@link ColorMapEntry}  
         // * @param cm  
         // * {@link ColorMap} to determine type (VALUES, INTERVALL )  
         // * @param iconWidth  
         // * Size of the rectangle  
         // * @param iconHeight  
         // * Size of the rectangle  
         // * @return {@link ImageIcon} of that color, maybe with a white border  
         // * @author Stefan Alfons Krüger  
         // */  
         // public static ImageIcon createImageForColorMapEntry(ColorMapEntry cme,  
         // ColorMap cm, Integer iconWidth, Integer iconHeight) {  
         //  
         // BufferedImage imageForRule = new BufferedImage(iconWidth, iconHeight,  
         // BufferedImage.TYPE_INT_ARGB);  
         //  
         // final Color color = StylingUtil.getColorFromColorMapEntry(cme);  
         //  
         // // Paint a block  
         // for (int x = 0; x < iconWidth; x++) {  
         // for (int y = 0; y < iconHeight; y++) {  
         // int rgb = color.getRGB();  
         // int rand = 2;  
         //  
         // // Paint a white border if the type is VALUES  
         // if ((x < rand) || (x > iconWidth - rand) || (y < rand)  
         // || (y > iconHeight - rand)) {  
         // if (cm.getType() == ColorMap.TYPE_VALUES) {  
         // rgb = Color.white.getRGB();  
         // }  
         // }  
         // imageForRule.setRGB(x, y, rgb);  
         // }  
         // }  
         // return new ImageIcon(imageForRule);  
         // }  
   
         /**  
241           * Creates a little BufferedImage that presents the Style/Symbols used by           * Creates a little BufferedImage that presents the Style/Symbols used by
242           * the {@link MapLegend} to show a legend for the {@link FeatureType}           * the {@link MapLegend} to show a legend for the {@link SimpleFeatureType}
243           *           *
244           * @param rule           * @param rule
245           *            {@link Rule} that provides the text and the style to present           *            {@link Rule} that provides the text and the style to present
246           * @param featureType           * @param featureType
247           *            Schema that describes the kind of the sample {@link Feature}           *            Schema that describes the kind of the sample
248           *            that will be rendered with the {@link Style}           *            {@link SimpleFeature} that will be rendered with the
249             *            {@link Style}
250           * @param bg           * @param bg
251           *            Background {@link Color} or <code>null</code>           *            Background {@link Color} or <code>null</code>
252           *           *
253           * @throws IllegalAttributeException           * @throws IllegalAttributeException
254           */           */
255          public BufferedImage createImageForRule(Rule rule, FeatureType featureType,          public BufferedImage createImageForRule(Rule rule,
256                          Dimension size, Color bg) {                          SimpleFeatureType featureType, Dimension size, Color bg) {
257    
258                  Symbolizer[] symbolizers = rule.getSymbolizers();                  Symbolizer[] symbolizers = rule.getSymbolizers();
259    
# Line 471  public class LegendIconFeatureRenderer e Line 263  public class LegendIconFeatureRenderer e
263    
264                  if (bg != null) {                  if (bg != null) {
265                          // ****************************************************************************                          // ****************************************************************************
266                          // The following lines define the backgroup color for the rendered                          // The following lines define the background color for the rendered
267                          // images                          // images
268                          // ****************************************************************************                          // ****************************************************************************
269                          graphics.setBackground(bg);                          graphics.setBackground(bg);
# Line 482  public class LegendIconFeatureRenderer e Line 274  public class LegendIconFeatureRenderer e
274                  // Enable anti-aliasing for the legend symbols                  // Enable anti-aliasing for the legend symbols
275                  graphics.setRenderingHints(getHints());                  graphics.setRenderingHints(getHints());
276    
277                  // TODO scaleDenominator = 100000000000000000000000000000d; Was ist das                  final NumberRange<Integer> scaleRange = NumberRange.create(
278                  // fuer ein Quatsch?                                  Integer.MAX_VALUE, Integer.MAX_VALUE);
                 final double scaleDenominator = 100000000000000000000000000000d;  
                 final NumberRange scaleRange = new NumberRange(scaleDenominator,  
                                 scaleDenominator);  
279    
280                  try {                  try {
281    
# Line 494  public class LegendIconFeatureRenderer e Line 283  public class LegendIconFeatureRenderer e
283                                  Symbolizer symbolizer = symbolizers[sIdx];                                  Symbolizer symbolizer = symbolizers[sIdx];
284    
285                                  if (symbolizer instanceof TextSymbolizer) {                                  if (symbolizer instanceof TextSymbolizer) {
                                         LOGGER  
                                                         .warn("createImageForRule for a TextSymbolizer. Sure we want that?");  
286                                          continue;                                          continue;
287                                  }                                  }
288    
# Line 504  public class LegendIconFeatureRenderer e Line 291  public class LegendIconFeatureRenderer e
291                                  // RasterSymbolizers..");                                  // RasterSymbolizers..");
292                                  // }                                  // }
293                                  // else                                  // else
294                                  final Feature sampleFeature = FeatureUtil.createSampleFeature(featureType);                                  final SimpleFeature sampleFeature = FeatureUtil
295                                                    .createSampleFeature(featureType);
296    
297                                    if (sampleFeature == null)
298                                            LOGGER.debug("sampleFeature " + sampleFeature);
299    
300                                  // The SLDStyleFactory has to be recreated, as it seams to cache                                  // The SLDStyleFactory has to be recreated, as it seams to cache
301                                  // some stuff.                                  // some stuff.
# Line 516  public class LegendIconFeatureRenderer e Line 307  public class LegendIconFeatureRenderer e
307                                                  size.height);                                                  size.height);
308    
309                                  if (style2d != null) {                                  if (style2d != null) {
310                                          new StyledShapePainter(null).paint(graphics, shape,                                          StyledShapePainter styledShapePainter = new StyledShapePainter(null);
311                                                          style2d, scaleDenominator);                                          styledShapePainter.paint(graphics, shape,
312                                                            style2d, Integer.MAX_VALUE);
313                                  }                                  }
314                          }                          }
315                  } catch (Exception e) {                  } catch (Exception e) {
316                          LOGGER                          LOGGER.error(
317                                          .error(                                          "Error during createImageForRule, returning empty Image", e);
                                                         "Error during createImageForRule, returning empty Image",  
                                                         e);  
318                  }                  }
319                  return buffImage;                  return buffImage;
320          }          }
# Line 533  public class LegendIconFeatureRenderer e Line 323  public class LegendIconFeatureRenderer e
323           * Define Java2D and other Hints           * Define Java2D and other Hints
324           *           *
325           * @param hints           * @param hints
326           * @author <a href="mailto:[email protected]">Stefan Alfons           * @author <a href="mailto:[email protected]">Stefan Alfons Tzeggai</a>
          *         Kr&uuml;ger</a>  
327           */           */
328          public void setHints(Hints hints) {          public void setHints(Hints hints) {
329                  getHints().add(hints);                  getHints().add(hints);
# Line 559  public class LegendIconFeatureRenderer e Line 348  public class LegendIconFeatureRenderer e
348    
349          /**          /**
350           * Creates a little BufferedImage that presents the Style/Symbols used by           * Creates a little BufferedImage that presents the Style/Symbols used by
351           * the {@link MapLegend} to show a legend for the {@link FeatureType}           * the {@link MapLegend} to show a legend for the {@link SimpleFeatureType}
352           *           *
353           * @param rule           * @param rule
354           *            {@link Rule} that provides the text and the style to present           *            {@link Rule} that provides the text and the style to present
355           * @param featureType           * @param featureType
356           *            Schema that describes the kind of the sample {@link Feature}           *            Schema that describes the kind of the sample
357           *            that will be rendered with the {@link Style}           *            {@link SimpleFeature} that will be rendered with the
358             *            {@link Style}
359           *           *
360           * @throws IllegalAttributeException           * @throws IllegalAttributeException
361           */           */
362          public BufferedImage createImageForRule(final Rule rule,          public BufferedImage createImageForRule(final Rule rule,
363                          final FeatureType featureType, final Dimension size) {                          final SimpleFeatureType featureType, final Dimension size) {
364                  return createImageForRule(rule, featureType, size, null);                  return createImageForRule(rule, featureType, size, null);
365          }          }
366    

Legend:
Removed from v.244  
changed lines
  Added in v.1231

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26