view flys-artifacts/src/main/java/de/intevation/flys/exports/EnhancedLineAndShapeRenderer.java @ 2072:4cdd9c4896f6

#393 Added a new Renderer and Options in Themes that allow displaying minimum and maximum of a chart series. flys-artifacts/trunk@3581 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Ingo Weinzierl <ingo.weinzierl@intevation.de>
date Wed, 04 Jan 2012 12:24:35 +0000
parents
children 27ada2e4243d
line wrap: on
line source
package de.intevation.flys.exports;

import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;

import org.apache.log4j.Logger;

import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.entity.EntityCollection;
import org.jfree.chart.plot.CrosshairState;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.RectangleEdge;
import org.jfree.util.BooleanList;
import org.jfree.util.ShapeUtilities;


public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer {

    private static final Logger logger =
        Logger.getLogger(EnhancedLineAndShapeRenderer.class);

    protected BooleanList isMinimumShapeVisible;
    protected BooleanList isMaximumShapeVisible;


    public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) {
        super(lines, shapes);
        this.isMinimumShapeVisible = new BooleanList();
        this.isMaximumShapeVisible = new BooleanList();
    }


    public boolean getItemShapeVisible(XYDataset dataset, int series, int item){
        if (super.getItemShapeVisible(series, item)) {
            logger.debug("Items are visible.");
            return true;
        }

        if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) {
            logger.debug("Minimum is visible for series: " + series);
            return true;
        }

        if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) {
            logger.debug("Maximum is visible for series: " + series);
            return true;
        }

        logger.debug("Nothing is visible at all.");

        return false;
    }


    /**
     * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted
     * method getItemShapeVisible() which now takes an XYDataset. So, 99% of
     * code equal the code in XYLineAndShapeRenderer.
     */
    @Override
    protected void drawSecondaryPass(
        Graphics2D       g2,
        XYPlot           plot,
        XYDataset        dataset,
        int              pass,
        int              series,
        int              item,
        ValueAxis        domainAxis,
        Rectangle2D      dataArea,
        ValueAxis        rangeAxis,
        CrosshairState   crosshairState,
        EntityCollection entities
    ) {
        logger.debug("Draw secondary pass");
        Shape entityArea = null;

        // get the data point...
        double x1 = dataset.getXValue(series, item);
        double y1 = dataset.getYValue(series, item);
        if (Double.isNaN(y1) || Double.isNaN(x1)) {
            return;
        }

        PlotOrientation orientation = plot.getOrientation();
        RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
        RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
        double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
        double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);

        if (getItemShapeVisible(dataset, series, item)) {
            Shape shape = getItemShape(series, item);
            if (orientation == PlotOrientation.HORIZONTAL) {
                shape = ShapeUtilities.createTranslatedShape(shape, transY1,
                        transX1);
            }
            else if (orientation == PlotOrientation.VERTICAL) {
                shape = ShapeUtilities.createTranslatedShape(shape, transX1,
                        transY1);
            }
            entityArea = shape;
            if (shape.intersects(dataArea)) {
                if (getItemShapeFilled(series, item)) {
                    if (getUseFillPaint()) {
                        g2.setPaint(getItemFillPaint(series, item));
                    }
                    else {
                        g2.setPaint(getItemPaint(series, item));
                    }
                    g2.fill(shape);
                }
                if (getDrawOutlines()) {
                    if (getUseOutlinePaint()) {
                        g2.setPaint(getItemOutlinePaint(series, item));
                    }
                    else {
                        g2.setPaint(getItemPaint(series, item));
                    }
                    g2.setStroke(getItemOutlineStroke(series, item));
                    g2.draw(shape);
                }
            }
        }

        double xx = transX1;
        double yy = transY1;
        if (orientation == PlotOrientation.HORIZONTAL) {
            xx = transY1;
            yy = transX1;
        }

        // draw the item label if there is one...
        if (isItemLabelVisible(series, item)) {
            drawItemLabel(g2, orientation, dataset, series, item, xx, yy,
                    (y1 < 0.0));
        }

        int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
        int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
        updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex,
                rangeAxisIndex, transX1, transY1, orientation);

        // add an entity for the item, but only if it falls within the data
        // area...
        if (entities != null && isPointInRect(dataArea, xx, yy)) {
            addEntity(entities, entityArea, dataset, series, item, xx, yy);
        }
    }


    public void setIsMinimumShapeVisisble(int series, boolean isVisible) {
        this.isMinimumShapeVisible.setBoolean(series, isVisible);
    }


    public boolean isMinimumShapeVisible(int series) {
        return isMinimumShapeVisible.getBoolean(series);
    }


    public void setIsMaximumShapeVisible(int series, boolean isVisible) {
        this.isMaximumShapeVisible.setBoolean(series, isVisible);
    }


    public boolean isMaximumShapeVisible(int series) {
        return isMaximumShapeVisible.getBoolean(series);
    }


    public static boolean isMinimum(XYDataset dataset, int series, int item) {
        return dataset.getYValue(series, item) == getMinimum(dataset, series);
    }


    public static double getMinimum(XYDataset dataset, int series) {
        double min = Double.MAX_VALUE;

        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
            double tmpValue = dataset.getYValue(series, i);

            if (tmpValue < min) {
                min = tmpValue;
            }
        }

        return min;
    }


    public static boolean isMaximum(XYDataset dataset, int series, int item) {
        return dataset.getYValue(series, item) == getMaximum(dataset, series);
    }


    public static double getMaximum(XYDataset dataset, int series) {
        double max = -Double.MAX_VALUE;

        for (int i = 0, n = dataset.getItemCount(series); i < n; i++) {
            double tmpValue = dataset.getYValue(series, i);

            if (tmpValue > max) {
                max = tmpValue;
            }
        }

        return max;
    }
}
// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org