diff gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonRenderer.java @ 450:20a480753ff9

Render labels in vertical cross section charts. gnv-artifacts/trunk@498 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Mon, 04 Jan 2010 02:49:42 +0000
parents 92b7ccbf6163
children bc5901bb4525
line wrap: on
line diff
--- a/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonRenderer.java	Sun Jan 03 15:57:02 2010 +0000
+++ b/gnv-artifacts/src/main/java/de/intevation/gnv/jfreechart/PolygonRenderer.java	Mon Jan 04 02:49:42 2010 +0000
@@ -1,54 +1,83 @@
 package de.intevation.gnv.jfreechart;
 
+import java.util.ArrayList;
+
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.Paint;
 import java.awt.Shape;
 import java.awt.BasicStroke;
+import java.awt.FontMetrics;
+import java.awt.Font;
 
 import java.awt.geom.GeneralPath;
 import java.awt.geom.Rectangle2D;
 import java.awt.geom.Rectangle2D.Double;
+import java.awt.geom.AffineTransform;
 
 import org.jfree.data.Range;
 
+import org.jfree.chart.axis.ValueAxis;
+
+import org.jfree.ui.RectangleEdge;
+
 import org.apache.log4j.Logger;
 
+import org.jfree.text.TextUtilities;
+
+
 /**
- * @author Ingo Weinzierl <ingo.weinzierl@intevation.de>
+ * @author Ingo Weinzierl      (ingo.weinzierl@intevation.de)
+ * @author Sascha L. Teichmann (sascha.teichmann@intevation.de)
  */
 public class PolygonRenderer
 {
 	private static Logger log = Logger.getLogger(
 		PolygonRenderer.class);
 
-    public static final int AREA           = 1;
-    public static final int LINES          = 2;
-    public static final int AREA_AND_LINES = AREA | LINES;
-
     public interface PaintLookup {
 
         Paint getPaint(int index);
 
     } // interface PaintLookup
 
-    protected int type;
+    public static class DefaultLabelGenerator
+    implements          PolygonSeriesLabelGenerator
+    {
+        public DefaultLabelGenerator() {
+        }
 
-    protected PaintLookup lookup;
+        public String generateLabel(PolygonSeries series) {
+            Object label = series.getAttribute("label");
+            return label != null
+                ? toString(label)
+                : null;
+        }
 
-    protected PolygonPlot plot;
+        protected String toString(Object label) {
+            return label.toString();
+        }
+    } // class DefaultLabelGenerator
 
+    public static final PolygonSeriesLabelGenerator 
+        DEFAULT_LABEL_GENERATOR_INSTANCE = new DefaultLabelGenerator();
+
+    protected PaintLookup                 lookup;
+    protected PolygonSeriesLabelGenerator labelGenerator;
 
     public PolygonRenderer(PaintLookup lookup) {
-        this(lookup, AREA);
+        this(lookup, null);
     }
 
-    public PolygonRenderer(PaintLookup lookup, int type) {
-        this.lookup = lookup;
-        this.type   = type;
+    public PolygonRenderer(
+        PaintLookup                 lookup, 
+        PolygonSeriesLabelGenerator labelGenerator
+    ) {
+        this.lookup         = lookup;
+        this.labelGenerator = labelGenerator;
     }
 
-    public void draw(
+    public void drawPolygons(
         Graphics2D     graphics,
         Rectangle2D    rectangle,
         PolygonDataset dataset
@@ -66,6 +95,8 @@
             sy = -sy; // mirror
         }
 
+        AffineTransform xform = graphics.getTransform();
+
         graphics.translate(tx, ty);
         graphics.scale(sx, sy);
 
@@ -88,6 +119,73 @@
                 graphics.draw(constructShape(series, false));
             }
         }
+
+        graphics.setTransform(xform);
+    }
+
+    public void drawLabels(
+        final Graphics2D  graphics,
+        final PolygonPlot plot,
+        final Rectangle2D area,
+        PolygonDataset    dataset
+    ) {
+        if (labelGenerator == null) {
+            return;
+        }
+
+        final ArrayList<Rectangle2D> bboxes = new ArrayList<Rectangle2D>();
+
+        Font font = graphics.getFont();
+        font = font.deriveFont(Font.PLAIN, Math.max(8, font.getSize()-3));
+        graphics.setFont(font);
+        FontMetrics metrics = graphics.getFontMetrics(font);
+
+        for (int i = dataset.getSeriesCount()-1; i >= 0; --i) {
+            PolygonSeries series = dataset.getSeries(i);
+
+            String label = labelGenerator.generateLabel(series);
+            if (label == null) {
+                continue;
+            }
+
+            final Rectangle2D box = TextUtilities.getTextBounds(
+                label, graphics, metrics);
+
+            for (int j = series.getItemCount()-1; j >= 0; --j) {
+                final CompactXYItems ring = series.getItem(j);
+                LevelOrderIndices loi = new LevelOrderIndices(ring.size()-1);
+                Rectangle2D r = (Rectangle2D)loi.visit(
+                    new LevelOrderIndices.Visitor() 
+                {
+                    ValueAxis          da = plot.getDomainAxis();
+                    ValueAxis          ra = plot.getRangeAxis();
+                    RectangleEdge      de = plot.getDomainAxisEdge();
+                    RectangleEdge      re = plot.getRangeAxisEdge();
+                    Rectangle2D.Double r  = new Rectangle2D.Double(
+                        0d, 0d, box.getWidth(), box.getHeight());
+
+                    public Object visit(int index) {
+                        r.x = da.valueToJava2D(ring.getX(index), area, de) 
+                            - 0.5*box.getWidth();
+                        r.y = ra.valueToJava2D(ring.getY(index), area, re)
+                            + 0.5*box.getHeight();
+
+                        for (Rectangle2D b: bboxes) {
+                            if (b.intersects(r)) {
+                                return null;
+                            }
+                        }
+                        return r;
+                    }
+                });
+
+                if (r != null) {
+                    bboxes.add(r);
+                    graphics.drawString(
+                        label, (float)r.getX(), (float)r.getY());
+                }
+            } // for all items in series
+        } // for all series
     }
 
     protected Shape constructShape(PolygonSeries series, boolean close) {

http://dive4elements.wald.intevation.org