sascha@446: package de.intevation.gnv.chart;
sascha@446:
sascha@521: import de.intevation.gnv.jfreechart.PolygonDataset;
sascha@521: import de.intevation.gnv.jfreechart.PolygonPlot;
sascha@521: import de.intevation.gnv.jfreechart.PolygonRenderer;
sascha@521: import de.intevation.gnv.jfreechart.PolygonSeries;
sascha@446:
sascha@521: import de.intevation.gnv.math.AttributedXYColumns;
sascha@521:
sascha@521: import de.intevation.gnv.raster.Palette;
sascha@450:
sascha@446: import java.awt.Color;
sascha@446: import java.awt.Paint;
sascha@446:
sascha@521: import java.text.NumberFormat;
sascha@446:
sascha@521: import java.util.HashSet;
sascha@521: import java.util.Locale;
sascha@521: import java.util.Map;
sascha@446:
sascha@446: import org.jfree.chart.JFreeChart;
sascha@446:
sascha@521: import org.jfree.chart.axis.NumberAxis;
sascha@521: import org.jfree.chart.axis.SymbolAxis;
sascha@521: import org.jfree.chart.axis.ValueAxis;
sascha@521:
sascha@446: import org.jfree.chart.plot.PlotOrientation;
sascha@446:
sascha@521: import org.jfree.chart.renderer.LookupPaintScale;
sascha@446:
sascha@446: import org.jfree.chart.title.PaintScaleLegend;
ingo@492: import org.jfree.chart.title.TextTitle;
sascha@446:
sascha@446: import org.jfree.ui.RectangleEdge;
sascha@446: import org.jfree.ui.RectangleInsets;
sascha@446:
sascha@446: /**
ingo@767: * @author Ingo Weinzierl
ingo@767: * @author Sascha L. Teichmann
sascha@446: */
sascha@446: public class VerticalCrossSectionChart
sascha@446: implements Chart
sascha@446: {
ingo@767: /**
ingo@767: * Lookup class for retrieving a color which corresponds to a specific
ingo@767: * integer value.
ingo@767: */
sascha@446: public static final class PalettePaintLookup
sascha@446: implements PolygonRenderer.PaintLookup
sascha@446: {
ingo@767: /**
ingo@767: * Object storing information about value ranges and its coresponding
ingo@767: * colors and descriptions.
ingo@767: */
sascha@521: private Palette palette;
ingo@767:
ingo@767: /**
ingo@767: * Map containing some special Paint
like ground fillcolor.
ingo@767: */
sascha@521: private Map special;
sascha@446:
ingo@767: /**
ingo@767: * Constructor
ingo@767: *
ingo@767: * @param palette See {@link #palette}
ingo@767: */
sascha@446: public PalettePaintLookup(Palette palette) {
sascha@521: this(palette, null);
sascha@521: }
sascha@521:
ingo@767: /**
ingo@767: * Constructor
ingo@767: *
ingo@767: * @param palette See {@link #palette}
ingo@767: * @param special See {@link #special}
ingo@767: */
sascha@521: public PalettePaintLookup(
sascha@521: Palette palette,
sascha@521: Map special
sascha@521: ) {
sascha@446: this.palette = palette;
sascha@521: this.special = special;
sascha@446: }
sascha@446:
ingo@767: /**
ingo@767: * @param index Index of a Paint
ingo@767: *
ingo@767: * @return Paint
object for a given index.
ingo@767: */
sascha@446: public Paint getPaint(int index) {
sascha@521: if (special != null) {
sascha@521: Paint paint = special.get(index);
sascha@521: if (paint != null) {
sascha@521: return paint;
sascha@521: }
sascha@521: }
sascha@446: return index < 0
sascha@446: ? Color.black
sascha@446: : palette.getColor(index);
sascha@446: }
sascha@446: } // class PalettePaintLookup
sascha@446:
ingo@767: /**
ingo@767: * This class is used to turn labels which represent a number into a
ingo@767: * specific format.
ingo@767: */
sascha@450: public static class LocalizedLabelGenerator
sascha@450: extends PolygonRenderer.DefaultLabelGenerator
sascha@450: {
ingo@767: /**
ingo@767: * NumberFormat
which is used to turn a number into a
ingo@767: * specific format.
ingo@767: */
sascha@450: protected NumberFormat format;
sascha@450:
ingo@767: /**
ingo@767: * Constructor
ingo@767: */
sascha@450: public LocalizedLabelGenerator() {
sascha@450: }
sascha@450:
ingo@767: /**
ingo@767: * Constructor
ingo@767: *
ingo@767: * @param format See {@link #format}
ingo@767: */
sascha@450: public LocalizedLabelGenerator(NumberFormat format) {
sascha@450: this.format = format;
sascha@450: }
sascha@450:
ingo@767: /**
ingo@767: * If label is a Number
, it is turned into a format
ingo@767: * specified by {@link #format}.
ingo@767: *
ingo@767: * @param label Label to format.
ingo@767: *
ingo@767: * @return String representation of label.
ingo@767: */
ingo@767: @Override
sascha@450: protected String toString(Object label) {
sascha@450: return label instanceof Number
sascha@450: ? format.format(((Number)label).doubleValue())
sascha@450: : super.toString(label);
sascha@450: }
sascha@450: } // class LocalizedLabelGenerator
sascha@450:
ingo@767: /**
ingo@767: * JFreeChart object stored at this place after chart creation.
ingo@767: */
sascha@446: protected JFreeChart chart;
sascha@446:
ingo@767: /**
ingo@767: * Stores {@link de.intevation.gnv.jfreechart.PolygonDataset} which is used
ingo@767: * to create a vertical cross chart.
ingo@767: */
sascha@446: protected AttributedXYColumns columns;
ingo@767:
ingo@767: /**
ingo@767: * Map which contains colors to fill polygons draw by this chart.
ingo@767: */
sascha@521: protected Map special;
ingo@767:
ingo@767: /**
ingo@767: * Object used to map value intervals to specific colors and descriptions.
ingo@767: */
sascha@446: protected Palette palette;
ingo@767:
ingo@767: /**
ingo@767: * Locale object used for i18n support.
ingo@767: */
sascha@446: protected Locale locale;
ingo@767:
ingo@767: /**
ingo@767: * Labels for decorating the chart.
ingo@767: */
ingo@492: protected ChartLabels labels;
sascha@446:
ingo@767: /**
ingo@767: * Default Constructor
ingo@767: */
sascha@446: public VerticalCrossSectionChart() {
sascha@446: }
sascha@446:
ingo@767: /**
ingo@767: * Constructor for VerticalCrossSectionChart creation.
ingo@767: *
ingo@767: * @param columns See {@link #columns}
ingo@767: * @param palette See {@link #palette}
ingo@767: * @param locale See {@link #locale}
ingo@767: * @param labels See {@link #labels}
ingo@767: */
sascha@446: public VerticalCrossSectionChart(
sascha@446: AttributedXYColumns columns,
sascha@446: Palette palette,
ingo@492: Locale locale,
ingo@492: ChartLabels labels
sascha@446: ) {
sascha@521: this(columns, palette, null, locale, labels);
sascha@521: }
sascha@521:
ingo@767: /**
ingo@767: * Constructor for VerticalCrossSectionChart creation.
ingo@767: *
ingo@767: * @param columns See {@link #columns}
ingo@767: * @param palette See {@link #palette}
ingo@767: * @param special See {@link #special}
ingo@767: * @param locale See {@link #locale}
ingo@767: * @param labels See {@link #labels}
ingo@767: */
sascha@521: public VerticalCrossSectionChart(
sascha@521: AttributedXYColumns columns,
sascha@521: Palette palette,
sascha@521: Map special,
sascha@521: Locale locale,
sascha@521: ChartLabels labels
sascha@521: ) {
sascha@446: this.columns = columns;
sascha@446: this.palette = palette;
sascha@521: this.special = special;
sascha@446: this.locale = locale;
ingo@492: this.labels = labels;
sascha@446: }
sascha@446:
ingo@767: /**
ingo@767: * This method is used to create a JFreeChart from this object. A 2D plot is
ingo@767: * drawn and a legend panel is created containing each value range.
ingo@767: *
ingo@767: * @return JFreeChart object
ingo@767: */
sascha@446: protected JFreeChart createChart() {
sascha@446:
ingo@492: boolean legendB = false;
ingo@492: boolean tooltips = false;
ingo@492: boolean urls = false;
sascha@446:
sascha@446: PlotOrientation po = PlotOrientation.HORIZONTAL;
sascha@446: PolygonDataset data = columns.getPolygonDataset();
sascha@446:
sascha@449: HashSet usedColors = new HashSet();
sascha@449:
sascha@449: for (int i = data.getSeriesCount()-1; i >= 0; --i) {
sascha@449: PolygonSeries ps = data.getSeries(i);
sascha@449: Integer fill = (Integer)ps.getAttribute("fill");
sascha@521: if (fill != null
sascha@521: && (special != null && !special.containsKey(fill))) {
sascha@449: usedColors.add(fill);
sascha@449: }
sascha@449: }
sascha@449:
sascha@450: NumberFormat format = NumberFormat.getInstance(locale);
sascha@450: format.setMinimumFractionDigits(0);
sascha@450: format.setMaximumFractionDigits(2);
sascha@450:
sascha@446: PolygonRenderer renderer = new PolygonRenderer(
sascha@521: new PalettePaintLookup(palette, special),
sascha@450: new LocalizedLabelGenerator(format));
sascha@446:
ingo@492: ValueAxis domainAxis = new NumberAxis(this.labels.getDomainAxisLabel());
ingo@492: ValueAxis rangeAxis = new NumberAxis(this.labels.getRangeAxisLabel());
sascha@446:
sascha@446: PolygonPlot plot = new PolygonPlot(
sascha@446: data,
sascha@446: renderer,
sascha@446: domainAxis,
sascha@446: rangeAxis,
sascha@446: null);
sascha@446:
ingo@534: plot.setOutlinePaint(Color.WHITE);
ingo@534:
sascha@449: String [] labels = new String[usedColors.size()];
sascha@449:
sascha@446: int colors = palette.getSize();
sascha@446: LookupPaintScale lookupPaint =
sascha@449: new LookupPaintScale(-0.5d, labels.length-0.5d, Color.white);
sascha@446:
sascha@446: Color color = null;
sascha@446:
sascha@449: for (int i = 0, j = labels.length-1; i < colors && j >= 0; i++) {
sascha@449: if (usedColors.contains(i)) {
sascha@449: Palette.Entry entry = palette.getEntryByIndex(i);
sascha@449: color = entry.getColor();
sascha@449: labels[j] = entry.getDescription();
sascha@449: lookupPaint.add(j-0.5d, color);
sascha@449: --j;
sascha@449: }
sascha@446: }
sascha@446:
sascha@446: JFreeChart chart = new JFreeChart(
ingo@492: this.labels.getTitle(),
sascha@446: JFreeChart.DEFAULT_TITLE_FONT,
sascha@446: plot,
sascha@446: legendB);
sascha@446:
sascha@446: chart.removeLegend();
ingo@492: chart.addSubtitle(new TextTitle(this.labels.getSubtitle()));
sascha@446:
ingo@492: SymbolAxis scale = new SymbolAxis(this.labels.getParameterName(), labels);
sascha@449: scale.setRange(-1.5d, labels.length+0.5d);
sascha@446: scale.setGridBandsVisible(false);
sascha@446: scale.setPlot(plot);
sascha@446:
sascha@446: PaintScaleLegend legend = new PaintScaleLegend(
sascha@446: lookupPaint, scale);
sascha@446: legend.setMargin(new RectangleInsets(3d, 10d, 3d, 10d));
sascha@446: legend.setPosition(RectangleEdge.LEFT);
sascha@446: legend.setAxisOffset(5d);
sascha@446:
sascha@446: chart.addSubtitle(legend);
sascha@446:
sascha@446: return chart;
sascha@446: }
sascha@446:
ingo@767: /**
ingo@767: * @see de.intevation.gnv.chart.Chart#generateChart()
ingo@767: */
sascha@446: public JFreeChart generateChart() {
sascha@446: if (chart == null) {
sascha@446: chart = createChart();
sascha@446: }
ingo@527:
sascha@446: return chart;
sascha@446: }
ingo@527:
ingo@767: /**
ingo@767: * Set the background paint of {@link #chart}.
ingo@767: */
ingo@527: public void setBackgroundPaint(Paint paint) {
ingo@527: chart.setBackgroundPaint(paint);
ingo@527: }
sascha@446: }
sascha@446: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf-8 :