sascha@3162: package de.intevation.flys.artifacts.services;
sascha@3162: 
sascha@3729: import de.intevation.flys.artifacts.model.fixings.QWI;
sascha@3162: 
sascha@3162: import de.intevation.flys.java2d.ShapeUtils;
sascha@3162: 
sascha@3162: import de.intevation.flys.jfree.ShapeRenderer;
sascha@3162: 
sascha@3162: import java.awt.BasicStroke;
sascha@3162: import java.awt.Color;
sascha@3162: import java.awt.Paint;
sascha@3162: import java.awt.Shape;
sascha@3162: 
sascha@3162: import java.awt.geom.Rectangle2D;
sascha@3162: 
sascha@3162: import java.text.DateFormat;
sascha@3162: import java.text.SimpleDateFormat;
sascha@3162: 
sascha@3162: import java.util.ArrayList;
sascha@3162: import java.util.Date;
sascha@3162: import java.util.HashMap;
sascha@3162: import java.util.List;
sascha@3162: import java.util.Map;
sascha@3162: 
sascha@3162: import org.jfree.chart.LegendItem;
sascha@3162: import org.jfree.chart.LegendItemCollection;
sascha@3162: 
sascha@3162: import org.jfree.chart.labels.XYItemLabelGenerator;
sascha@3162: 
sascha@3162: import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
sascha@3162: 
sascha@3162: import org.jfree.data.xy.XYDataset;
sascha@3162: import org.jfree.data.xy.XYSeries;
sascha@3162: import org.jfree.data.xy.XYSeriesCollection;
sascha@3162: 
sascha@3162: public class QWSeriesCollection
sascha@3162: extends      XYSeriesCollection
sascha@3162: implements   XYItemLabelGenerator
sascha@3162: {
sascha@3162:     public interface LabelGenerator {
sascha@3729:         String createLabel(QWI qw);
sascha@3162:     } // interface LabelGenerator
sascha@3162: 
sascha@3162:     public static class DateFormatLabelGenerator
sascha@3162:     implements          LabelGenerator
sascha@3162:     {
sascha@3162:         protected DateFormat format;
sascha@3162: 
sascha@3162:         public DateFormatLabelGenerator() {
sascha@3170:             this("dd.MM.yyyy");
sascha@3170:         }
sascha@3170: 
sascha@3170:         public DateFormatLabelGenerator(String format) {
sascha@3170:             this(new SimpleDateFormat(format));
sascha@3162:         }
sascha@3162: 
sascha@3162:         public DateFormatLabelGenerator(DateFormat format) {
sascha@3162:             this.format = format;
sascha@3162:         }
sascha@3162: 
sascha@3162:         @Override
sascha@3729:         public String createLabel(QWI qw) {
sascha@3162:             Date date = qw.getDate();
sascha@3162:             return date != null ? format.format(date) : "";
sascha@3162:         }
sascha@3162:     } // class DateFormatLabelGenerator
sascha@3162: 
sascha@3162:     public static final LabelGenerator SIMPLE_GENERATOR =
sascha@3162:         new DateFormatLabelGenerator();
sascha@3162: 
sascha@3162:     protected Date minDate;
sascha@3162:     protected Date maxDate;
sascha@3162: 
sascha@3729:     protected List<List<QWI>> labels;
sascha@3162: 
sascha@3162:     protected Rectangle2D area;
sascha@3162: 
sascha@3162:     protected LabelGenerator labelGenerator;
sascha@3162: 
sascha@3162:     protected Map<ShapeRenderer.Entry, Integer> knownShapes =
sascha@3162:         new HashMap<ShapeRenderer.Entry, Integer>();
sascha@3162: 
sascha@3162:     public QWSeriesCollection() {
sascha@3729:         labels = new ArrayList<List<QWI>>();
sascha@3162:         labelGenerator = SIMPLE_GENERATOR;
sascha@3162:     }
sascha@3162: 
sascha@3162:     public QWSeriesCollection(LabelGenerator labelGenerator) {
sascha@3162:         this();
sascha@3162:         this.labelGenerator = labelGenerator;
sascha@3162:     }
sascha@3162: 
sascha@3729:     protected static ShapeRenderer.Entry classify(QWI qw) {
sascha@3164:         boolean interpolated = qw.getInterpolated();
sascha@3164: 
sascha@3164:         Shape shape = interpolated
sascha@3162:             ? ShapeUtils.INTERPOLATED_SHAPE
sascha@3162:             : ShapeUtils.MEASURED_SHAPE;
sascha@3162: 
sascha@3164:         boolean filled = !interpolated;
sascha@3403:         Color color = Color.blue;
sascha@3162: 
sascha@3164:         return new ShapeRenderer.Entry(shape, color, filled);
sascha@3162:     }
sascha@3162: 
sascha@3729:     public void add(QWI qw) {
sascha@3162: 
sascha@3162:         ShapeRenderer.Entry key = classify(qw);
sascha@3162: 
sascha@3162:         Integer seriesNo = knownShapes.get(key);
sascha@3162: 
sascha@3162:         XYSeries series;
sascha@3162: 
sascha@3162:         if (seriesNo == null) {
sascha@3162:             seriesNo = Integer.valueOf(getSeriesCount());
sascha@3162:             knownShapes.put(key, seriesNo);
sascha@3162:             series = new XYSeries(seriesNo, false);
sascha@3162:             addSeries(series);
sascha@3729:             labels.add(new ArrayList<QWI>());
sascha@3162:         }
sascha@3162:         else {
sascha@3162:             series = getSeries(seriesNo);
sascha@3162:         }
sascha@3162: 
sascha@3162:         series.add(qw.getQ(), qw.getW());
sascha@3162: 
sascha@3162:         labels.get(seriesNo).add(qw);
sascha@3162: 
sascha@3162:         extendDateRange(qw);
sascha@3162:         extendArea(qw);
sascha@3162:     }
sascha@3162: 
sascha@3729:     protected void extendDateRange(QWI qw) {
sascha@3162:         Date date = qw.getDate();
sascha@3162:         if (date != null) {
sascha@3162:             if (minDate == null) {
sascha@3162:                 minDate = maxDate = date;
sascha@3162:             }
sascha@3162:             else {
sascha@3162:                 if (date.compareTo(minDate) < 0) {
sascha@3162:                     minDate = date;
sascha@3162:                 }
sascha@3162:                 if (date.compareTo(maxDate) > 0) {
sascha@3162:                     maxDate = date;
sascha@3162:                 }
sascha@3162:             }
sascha@3162:         }
sascha@3162:     }
sascha@3162: 
sascha@3729:     protected void extendArea(QWI qw) {
sascha@3162:         if (area == null) {
sascha@3162:             area = new Rectangle2D.Double(
sascha@3162:                 qw.getQ(), qw.getW(), 0d, 0d);
sascha@3162:         }
sascha@3162:         else {
sascha@3162:             area.add(qw.getQ(), qw.getW());
sascha@3162:         }
sascha@3162:     }
sascha@3162: 
sascha@3162:     public Rectangle2D getArea() {
sascha@3162:         return area;
sascha@3162:     }
sascha@3162: 
sascha@3162:     public Date getMinDate() {
sascha@3162:         return minDate;
sascha@3162:     }
sascha@3162: 
sascha@3162:     public Date getMaxDate() {
sascha@3162:         return maxDate;
sascha@3162:     }
sascha@3162: 
sascha@3162:     public LabelGenerator getLabelGenerator() {
sascha@3162:         return labelGenerator;
sascha@3162:     }
sascha@3162: 
sascha@3162:     @Override
sascha@3162:     public String generateLabel(XYDataset dataset, int series, int item) {
sascha@3162:         return labelGenerator.createLabel(labels.get(series).get(item));
sascha@3162:     }
sascha@3162: 
sascha@3162:     public StandardXYItemRenderer createRenderer() {
sascha@3162:         StandardXYItemRenderer renderer = new ShapeRenderer(knownShapes);
sascha@3162:         renderer.setBaseItemLabelGenerator(this);
sascha@3162:         renderer.setBaseSeriesVisibleInLegend(false);
sascha@3162:         renderer.setBaseItemLabelsVisible(true);
sascha@3162:         return renderer;
sascha@3162:     }
sascha@3162: 
sascha@3162:     public static final LegendItem legendItem(
sascha@3162:         String  label,
sascha@3162:         Paint   paint,
sascha@3162:         Shape   shape,
sascha@3162:         boolean filled
sascha@3162:     ) {
sascha@3162:         BasicStroke stroke = new BasicStroke();
sascha@3162:         return new LegendItem(
sascha@3162:             label,  // label
sascha@3162:             null,   // description
sascha@3162:             null,   // tooltip
sascha@3162:             null,   // url
sascha@3162:             true,   // shape visible
sascha@3162:             shape,  // shape
sascha@3162:             filled, // shape filled
sascha@3162:             filled ? paint : Color.white, // fill paint
sascha@3162:             true,   // shape outline
sascha@3162:             paint,  // outline paint
sascha@3162:             stroke, // outline stroke
sascha@3162:             false,  // line visible
sascha@3162:             shape,  // line
sascha@3162:             stroke, // line stroke
sascha@3162:             Color.white);
sascha@3162:     }
sascha@3162: 
sascha@3173:     public void addLegendItems(
sascha@3173:         LegendItemCollection         lic,
sascha@3173:         ShapeRenderer.LabelGenerator lg
sascha@3173:     ) {
sascha@3162:         for (ShapeRenderer.Entry entry: knownShapes.keySet()) {
sascha@3162:             lic.add(legendItem(
sascha@3173:                 lg.createLabel(entry),
sascha@3162:                 entry.getPaint(),
sascha@3162:                 entry.getShape(),
sascha@3162:                 entry.getFilled()));
sascha@3162:         }
sascha@3162:     }
sascha@3162: }
sascha@3162: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :