/[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

trunk/src/skrueger/geotools/LegendIconFeatureRenderer.java revision 162 by alfonx, Mon Jun 22 21:05:20 2009 UTC branches/1.0-gt2-2.6/src/skrueger/geotools/LegendIconFeatureRenderer.java revision 377 by alfonx, Fri Sep 4 11:33:03 2009 UTC
# Line 1  Line 1 
1    /*******************************************************************************
2     * Copyright (c) 2009 Martin O. J. Schmitz.
3     *
4     * This file is part of the SCHMITZM library - a collection of utility
5     * classes based on Java 1.6, focusing (not only) on Java Swing
6     * and the Geotools library.
7     *
8     * The SCHMITZM project is hosted at:
9     * http://wald.intevation.org/projects/schmitzm/
10     *
11     * This program is free software; you can redistribute it and/or
12     * modify it under the terms of the GNU Lesser General Public License
13     * as published by the Free Software Foundation; either version 3
14     * of the License, or (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU Lesser General Public License (license.txt)
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
24     * or try this link: http://www.gnu.org/licenses/lgpl.html
25     *
26     * Contributors:
27     *     Martin O. J. Schmitz - initial API and implementation
28     *     Stefan A. Krüger - additional utility classes
29     ******************************************************************************/
30  /**  /**
31   Copyright 2008 Stefan Alfons Krüger and parts from some Geotools code     Copyright 2008 Stefan Alfons Krüger and parts from some Geotools code  
32    
# Line 13  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 47  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 63  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 using
91   * {@link AttributeType#createDefaultValue()} directly, because the latter   * {@link AttributeDescriptor#createDefaultValue()} directly, because the latter
92   * returns {@code null} even though the attribut is not nillable.</li>   * returns {@code null} even though the attribut is not nillable.</li>
93   * </ul>   * </ul>
94   *   *
95   * @author Stefan Alfons Krüger   * @author Stefan Alfons Krüger
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 86  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                  return new LegendIconFeatureRenderer();                  return new LegendIconFeatureRenderer();
115  //               return instance;  //               return instance;
116          }          }
117    
         /** The image produced at <code>produceLegendGraphic</code> */  
         private BufferedImage legendGraphic;  
   
118          /**          /**
119           * used to create sample point shapes with LiteShape (not lines nor           * used to create sample point shapes with LiteShape (not lines nor
120           * polygons)           * polygons)
121           */           */
122          private static final GeometryFactory geomFac = new GeometryFactory();          private static final GeometryFactory geomFac = FeatureUtil.GEOMETRY_FACTORY;
123    
124          /** padding percentage factor at both sides of the legend. */          /** padding percentage factor at both sides of the legend. */
125          private static final float hpaddingFactor = 0.11f; // was 0.15          private static final float hpaddingFactor = 0.11f; // was 0.15
# Line 106  public class LegendIconFeatureRenderer e Line 128  public class LegendIconFeatureRenderer e
128          private static final float vpaddingFactor = 0.08f; // was 0.15          private static final float vpaddingFactor = 0.08f; // was 0.15
129    
130          /**          /**
          * 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();  
   
         /**  
131           * Just a holder to avoid creating many polygon shapes from inside           * Just a holder to avoid creating many polygon shapes from inside
132           * <code>getSampleShape()</code>           * <code>getSampleShape()</code>
133           */           */
# Line 214  public class LegendIconFeatureRenderer e Line 230  public class LegendIconFeatureRenderer e
230    
231                  return sampleShape;                  return sampleShape;
232          }          }
233    //
234          /**  //      /**
235           * Puts a BufferedImage into this.legendGraphic  //       * Puts a BufferedImage into this.legendGraphic
236           */  //       */
237          public void produceLegendGraphic(FeatureType featureType, Style gt2Style,  //      public void produceLegendGraphic(SimpleFeatureType featureType, Style gt2Style,
238                          Rule[] applicableRules) {  //                      Rule[] applicableRules) {
239    //
240                  // final FeatureTypeStyle[] ftStyles = gt2Style.getFeatureTypeStyles();  //              // final FeatureTypeStyle[] ftStyles = gt2Style.getFeatureTypeStyles();
241    //
242                  // if (request.getRule() != null) {  //              // if (request.getRule() != null) {
243                  // applicableRules = new Rule[] { request.getRule() };  //              // applicableRules = new Rule[] { request.getRule() };
244                  // } else {  //              // } else {
245                  // applicableRules = getApplicableRules(ftStyles, scaleDenominator);  //              // applicableRules = getApplicableRules(ftStyles, scaleDenominator);
246                  // }  //              // }
247    //
248                  final int ruleCount = applicableRules.length;  //              final int ruleCount = applicableRules.length;
249    //
250                  /**  //              /**
251                   * A legend graphic is produced for each applicable rule. They're being  //               * A legend graphic is produced for each applicable rule. They're being
252                   * holded here until the process is done and then painted on a "stack"  //               * holded here until the process is done and then painted on a "stack"
253                   * like legend.  //               * like legend.
254                   */  //               */
255                  final List<BufferedImage> legendsStack = new ArrayList<BufferedImage>(  //              final List<BufferedImage> legendsStack = new ArrayList<BufferedImage>(
256                                  ruleCount);  //                              ruleCount);
257    //
258                  for (int i = 0; i < ruleCount; i++) {  //              for (int i = 0; i < ruleCount; i++) {
259                          BufferedImage image = createImageForRule(applicableRules[i],  //                      BufferedImage image = createImageForRule(applicableRules[i],
260                                          featureType, SIZE);  //                                      featureType, SIZE);
261                          legendsStack.add(image);  //                      legendsStack.add(image);
262                  }  //              }
263    //
264                  // this.legendGraphic =  //              // this.legendGraphic =
265                  // scaleImage(mergeLegends(legendsStack,applicableRules), request);  //              // scaleImage(mergeLegends(legendsStack,applicableRules), request);
266                  this.legendGraphic = mergeLegends(legendsStack, applicableRules);  //              this.legendGraphic = mergeLegends(legendsStack, applicableRules);
267          }  //      }
268    //
269          /**  //      /**
270           * Recieves a list of <code>BufferedImages</code> and produces a new one  //       * Recieves a list of <code>BufferedImages</code> and produces a new one
271           * which holds all the images in <code>imageStack</code> one above the  //       * which holds all the images in <code>imageStack</code> one above the
272           * other.  //       * other.
273           *  //       *
274           * @param imageStack  //       * @param imageStack
275           *            the list of BufferedImages, one for each applicable Rule  //       *            the list of BufferedImages, one for each applicable Rule
276           * @param rules  //       * @param rules
277           *            The applicable rules, one for each image in the stack  //       *            The applicable rules, one for each image in the stack
278           * @param request  //       * @param request
279           *            The request.  //       *            The request.
280           *  //       *
281           * @return the stack image with all the images on the argument list.  //       * @return the stack image with all the images on the argument list.
282           *  //       *
283           * @throws IllegalArgumentException  //       * @throws IllegalArgumentException
284           *             if the list is empty  //       *             if the list is empty
285           */  //       */
286          private static BufferedImage mergeLegends(List<BufferedImage> imageStack,  //      private static BufferedImage mergeLegends(List<BufferedImage> imageStack,
287                          Rule[] rules) {  //                      Rule[] rules) {
288                  if (imageStack.size() == 0) {  //              if (imageStack.size() == 0) {
289                          throw new IllegalArgumentException("No legend graphics passed");  //                      throw new IllegalArgumentException("No legend graphics passed");
290                  }  //              }
291    //
292                  BufferedImage finalLegend = null;  //              BufferedImage finalLegend = null;
293    //
294                  if (imageStack.size() == 1) {  //              if (imageStack.size() == 1) {
295                          finalLegend = (BufferedImage) imageStack.get(0);  //                      finalLegend = (BufferedImage) imageStack.get(0);
296                  } else {  //              } else {
297                          final int imgCount = imageStack.size();  //                      final int imgCount = imageStack.size();
298                          final String[] labels = new String[imgCount];  //                      final String[] labels = new String[imgCount];
299    //
300                          BufferedImage img = ((BufferedImage) imageStack.get(0));  //                      BufferedImage img = ((BufferedImage) imageStack.get(0));
301                          FontMetrics fontMetrics = img.getGraphics().getFontMetrics();  //                      FontMetrics fontMetrics = img.getGraphics().getFontMetrics();
302    //
303                          final int rowHeight = Math.max(fontMetrics.getHeight(), img  //                      final int rowHeight = Math.max(fontMetrics.getHeight(), img
304                                          .getHeight());  //                                      .getHeight());
305    //
306                          // calculate the total dimensions of the image  //                      // calculate the total dimensions of the image
307                          int totalHeight = rowHeight * imgCount;  //                      int totalHeight = rowHeight * imgCount;
308                          int totalWidth = 0;  //                      int totalWidth = 0;
309    //
310                          for (int i = 0; i < imgCount; i++) {  //                      for (int i = 0; i < imgCount; i++) {
311                                  img = (BufferedImage) imageStack.get(i);  //                              img = (BufferedImage) imageStack.get(i);
312    //
313                                  Rule rule = rules[i];  //                              Rule rule = rules[i];
314    //
315                                  // does this rule have a label  //                              // does this rule have a label
316                                  labels[i] = rule.getTitle();  //                              labels[i] = rule.getTitle();
317    //
318                                  if (labels[i] == null) {  //                              if (labels[i] == null) {
319                                          labels[i] = rule.getName();  //                                      labels[i] = rule.getName();
320                                  }  //                              }
321    //
322                                  int w = img.getWidth();  //                              int w = img.getWidth();
323    //
324                                  if (labels[i] != null) {  //                              if (labels[i] != null) {
325                                          Graphics g = img.getGraphics();  //                                      Graphics g = img.getGraphics();
326                                          w += g.getFontMetrics().stringWidth(labels[i]);  //                                      w += g.getFontMetrics().stringWidth(labels[i]);
327                                  }  //                              }
328    //
329                                  totalWidth = Math.max(w, totalWidth);  //                              totalWidth = Math.max(w, totalWidth);
330                          }  //                      }
331    //
332                          // create the final image  //                      // create the final image
333                          finalLegend = new BufferedImage(totalWidth, totalHeight,  //                      finalLegend = new BufferedImage(totalWidth, totalHeight,
334                                          BufferedImage.TYPE_INT_ARGB);  //                                      BufferedImage.TYPE_INT_ARGB);
335    //
336                          Graphics2D finalGraphics = finalLegend.createGraphics();  //                      Graphics2D finalGraphics = finalLegend.createGraphics();
337    //
338                          finalGraphics.setColor(Color.white);  //                      finalGraphics.setColor(Color.white);
339                          finalGraphics.fillRect(0, 0, totalWidth, totalHeight);  //                      finalGraphics.fillRect(0, 0, totalWidth, totalHeight);
340    //
341                          int h = 0;  //                      int h = 0;
342    //
343                          for (int i = 0; i < imgCount; i++) {  //                      for (int i = 0; i < imgCount; i++) {
344                                  img = (BufferedImage) imageStack.get(i);  //                              img = (BufferedImage) imageStack.get(i);
345    //
346                                  // draw the image  //                              // draw the image
347                                  int y = h;  //                              int y = h;
348    //
349                                  if (img.getHeight() < rowHeight) {  //                              if (img.getHeight() < rowHeight) {
350                                          // move the image to the center of the row  //                                      // move the image to the center of the row
351                                          y += (int) ((rowHeight - img.getHeight()) / 2d);  //                                      y += (int) ((rowHeight - img.getHeight()) / 2d);
352                                  }  //                              }
353    //
354                                  finalGraphics.drawImage(img, 0, y, imgObs);  //                              finalGraphics.drawImage(img, 0, y, imgObs);
355    //
356                                  // draw the label  //                              // draw the label
357                                  if (labels[i] != null) {  //                              if (labels[i] != null) {
358                                          finalGraphics.setColor(Color.BLACK);  //                                      finalGraphics.setColor(Color.BLACK);
359    //
360                                          y = (h + rowHeight) - fontMetrics.getDescent();  //                                      y = (h + rowHeight) - fontMetrics.getDescent();
361    //
362                                          if (fontMetrics.getHeight() < rowHeight) {  //                                      if (fontMetrics.getHeight() < rowHeight) {
363                                                  // move the baseline to the center of the row  //                                              // move the baseline to the center of the row
364                                                  y -= (int) ((rowHeight - fontMetrics.getHeight()) / 2d);  //                                              y -= (int) ((rowHeight - fontMetrics.getHeight()) / 2d);
365                                          }  //                                      }
366    //
367                                          finalGraphics.drawString(labels[i], img.getWidth(), y);  //                                      finalGraphics.drawString(labels[i], img.getWidth(), y);
368                                  }  //                              }
369    //
370                                  h += rowHeight;  //                              h += rowHeight;
371                          }  //                      }
372                  }  //              }
373    //
374                  return finalLegend;  //              return finalLegend;
375          }  //      }
376    //
377          /**  //      /**
378           * DOCUMENT ME!  //       * DOCUMENT ME!
379           *  //       *
380           * @return  //       * @return
381           *  //       *
382           * @throws IllegalStateException  //       * @throws IllegalStateException
383           *             DOCUMENT ME!  //       *             DOCUMENT ME!
384           */  //       */
385          public BufferedImage getLegendGraphic() {  //      public BufferedImage getLegendGraphic() {
386                  if (this.legendGraphic == null) {  //              if (this.legendGraphic == null) {
387                          throw new IllegalStateException();  //                      throw new IllegalStateException();
388                  }  //              }
389                  return this.legendGraphic;  //              return this.legendGraphic;
390          }  //      }
391    
392          // /**          // /**
393          // * Paints a little rectangle in the color defined by the          // * Paints a little rectangle in the color defined by the
# Line 419  public class LegendIconFeatureRenderer e Line 435  public class LegendIconFeatureRenderer e
435    
436          /**          /**
437           * Creates a little BufferedImage that presents the Style/Symbols used by           * Creates a little BufferedImage that presents the Style/Symbols used by
438           * the {@link MapLegend} to show a legend for the {@link FeatureType}           * the {@link MapLegend} to show a legend for the {@link SimpleFeatureType}
439           *           *
440           * @param rule           * @param rule
441           *            {@link Rule} that provides the text and the style to present           *            {@link Rule} that provides the text and the style to present
442           * @param featureType           * @param featureType
443           *            Schema that describes the kind of the sample {@link Feature}           *            Schema that describes the kind of the sample {@link SimpleFeature}
444           *            that will be rendered with the {@link Style}           *            that will be rendered with the {@link Style}
445           * @param bg           * @param bg
446           *            Background {@link Color} or <code>null</code>           *            Background {@link Color} or <code>null</code>
447           *           *
448           * @throws IllegalAttributeException           * @throws IllegalAttributeException
449           */           */
450          public BufferedImage createImageForRule(Rule rule, FeatureType featureType,          public BufferedImage createImageForRule(Rule rule, SimpleFeatureType featureType,
451                          Dimension size, Color bg) {                          Dimension size, Color bg) {
452    
453                  Symbolizer[] symbolizers = rule.getSymbolizers();                  Symbolizer[] symbolizers = rule.getSymbolizers();
# Line 475  public class LegendIconFeatureRenderer e Line 491  public class LegendIconFeatureRenderer e
491                                  // RasterSymbolizers..");                                  // RasterSymbolizers..");
492                                  // }                                  // }
493                                  // else                                  // else
494                                  final Feature sampleFeature = FeatureUtil.createSampleFeature(featureType);                                  final SimpleFeature sampleFeature = FeatureUtil.createSampleFeature(featureType);
495    
496                                  // The SLDStyleFactory has to be recreated, as it seams to cache                                  // The SLDStyleFactory has to be recreated, as it seams to cache
497                                  // some stuff.                                  // some stuff.
# Line 530  public class LegendIconFeatureRenderer e Line 546  public class LegendIconFeatureRenderer e
546    
547          /**          /**
548           * Creates a little BufferedImage that presents the Style/Symbols used by           * Creates a little BufferedImage that presents the Style/Symbols used by
549           * the {@link MapLegend} to show a legend for the {@link FeatureType}           * the {@link MapLegend} to show a legend for the {@link SimpleFeatureType}
550           *           *
551           * @param rule           * @param rule
552           *            {@link Rule} that provides the text and the style to present           *            {@link Rule} that provides the text and the style to present
553           * @param featureType           * @param featureType
554           *            Schema that describes the kind of the sample {@link Feature}           *            Schema that describes the kind of the sample {@link SimpleFeature}
555           *            that will be rendered with the {@link Style}           *            that will be rendered with the {@link Style}
556           *           *
557           * @throws IllegalAttributeException           * @throws IllegalAttributeException
558           */           */
559          public BufferedImage createImageForRule(final Rule rule,          public BufferedImage createImageForRule(final Rule rule,
560                          final FeatureType featureType, final Dimension size) {                          final SimpleFeatureType featureType, final Dimension size) {
561                  return createImageForRule(rule, featureType, size, null);                  return createImageForRule(rule, featureType, size, null);
562          }          }
563    

Legend:
Removed from v.162  
changed lines
  Added in v.377

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26