ingo@2072: package de.intevation.flys.exports; ingo@2072: ingo@2072: import java.awt.Graphics2D; ingo@2072: import java.awt.Shape; ingo@2072: import java.awt.geom.Rectangle2D; ingo@2072: ingo@2072: import org.apache.log4j.Logger; ingo@2072: ingo@2072: import org.jfree.chart.axis.ValueAxis; ingo@2072: import org.jfree.chart.entity.EntityCollection; ingo@2072: import org.jfree.chart.plot.CrosshairState; ingo@2072: import org.jfree.chart.plot.PlotOrientation; ingo@2072: import org.jfree.chart.plot.XYPlot; ingo@2072: import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; ingo@2072: import org.jfree.data.xy.XYDataset; ingo@2072: import org.jfree.ui.RectangleEdge; ingo@2072: import org.jfree.util.BooleanList; ingo@2072: import org.jfree.util.ShapeUtilities; ingo@2072: ingo@2072: ingo@2072: public class EnhancedLineAndShapeRenderer extends XYLineAndShapeRenderer { ingo@2072: ingo@2072: private static final Logger logger = ingo@2072: Logger.getLogger(EnhancedLineAndShapeRenderer.class); ingo@2072: ingo@2072: protected BooleanList isMinimumShapeVisible; ingo@2072: protected BooleanList isMaximumShapeVisible; ingo@2072: ingo@2072: ingo@2072: public EnhancedLineAndShapeRenderer(boolean lines, boolean shapes) { ingo@2072: super(lines, shapes); ingo@2072: this.isMinimumShapeVisible = new BooleanList(); ingo@2072: this.isMaximumShapeVisible = new BooleanList(); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public boolean getItemShapeVisible(XYDataset dataset, int series, int item){ ingo@2072: if (super.getItemShapeVisible(series, item)) { ingo@2072: logger.debug("Items are visible."); ingo@2072: return true; ingo@2072: } ingo@2072: ingo@2072: if (isMinimumShapeVisible(series) && isMinimum(dataset, series, item)) { ingo@2072: logger.debug("Minimum is visible for series: " + series); ingo@2072: return true; ingo@2072: } ingo@2072: ingo@2072: if (isMaximumShapeVisible(series) && isMaximum(dataset, series, item)) { ingo@2072: logger.debug("Maximum is visible for series: " + series); ingo@2072: return true; ingo@2072: } ingo@2072: ingo@2072: logger.debug("Nothing is visible at all."); ingo@2072: ingo@2072: return false; ingo@2072: } ingo@2072: ingo@2072: ingo@2072: /** ingo@2072: * Overrides XYLineAndShapeRenderer.drawSecondaryPass() to call an adapted ingo@2072: * method getItemShapeVisible() which now takes an XYDataset. So, 99% of ingo@2072: * code equal the code in XYLineAndShapeRenderer. ingo@2072: */ ingo@2072: @Override ingo@2072: protected void drawSecondaryPass( ingo@2072: Graphics2D g2, ingo@2072: XYPlot plot, ingo@2072: XYDataset dataset, ingo@2072: int pass, ingo@2072: int series, ingo@2072: int item, ingo@2072: ValueAxis domainAxis, ingo@2072: Rectangle2D dataArea, ingo@2072: ValueAxis rangeAxis, ingo@2072: CrosshairState crosshairState, ingo@2072: EntityCollection entities ingo@2072: ) { ingo@2072: logger.debug("Draw secondary pass"); ingo@2072: Shape entityArea = null; ingo@2072: ingo@2072: // get the data point... ingo@2072: double x1 = dataset.getXValue(series, item); ingo@2072: double y1 = dataset.getYValue(series, item); ingo@2072: if (Double.isNaN(y1) || Double.isNaN(x1)) { ingo@2072: return; ingo@2072: } ingo@2072: ingo@2072: PlotOrientation orientation = plot.getOrientation(); ingo@2072: RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); ingo@2072: RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); ingo@2072: double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); ingo@2072: double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); ingo@2072: ingo@2072: if (getItemShapeVisible(dataset, series, item)) { ingo@2072: Shape shape = getItemShape(series, item); ingo@2072: if (orientation == PlotOrientation.HORIZONTAL) { ingo@2072: shape = ShapeUtilities.createTranslatedShape(shape, transY1, ingo@2072: transX1); ingo@2072: } ingo@2072: else if (orientation == PlotOrientation.VERTICAL) { ingo@2072: shape = ShapeUtilities.createTranslatedShape(shape, transX1, ingo@2072: transY1); ingo@2072: } ingo@2072: entityArea = shape; ingo@2072: if (shape.intersects(dataArea)) { ingo@2072: if (getItemShapeFilled(series, item)) { ingo@2072: if (getUseFillPaint()) { ingo@2072: g2.setPaint(getItemFillPaint(series, item)); ingo@2072: } ingo@2072: else { ingo@2072: g2.setPaint(getItemPaint(series, item)); ingo@2072: } ingo@2072: g2.fill(shape); ingo@2072: } ingo@2072: if (getDrawOutlines()) { ingo@2072: if (getUseOutlinePaint()) { ingo@2072: g2.setPaint(getItemOutlinePaint(series, item)); ingo@2072: } ingo@2072: else { ingo@2072: g2.setPaint(getItemPaint(series, item)); ingo@2072: } ingo@2072: g2.setStroke(getItemOutlineStroke(series, item)); ingo@2072: g2.draw(shape); ingo@2072: } ingo@2072: } ingo@2072: } ingo@2072: ingo@2072: double xx = transX1; ingo@2072: double yy = transY1; ingo@2072: if (orientation == PlotOrientation.HORIZONTAL) { ingo@2072: xx = transY1; ingo@2072: yy = transX1; ingo@2072: } ingo@2072: ingo@2072: // draw the item label if there is one... ingo@2072: if (isItemLabelVisible(series, item)) { ingo@2072: drawItemLabel(g2, orientation, dataset, series, item, xx, yy, ingo@2072: (y1 < 0.0)); ingo@2072: } ingo@2072: ingo@2072: int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); ingo@2072: int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); ingo@2072: updateCrosshairValues(crosshairState, x1, y1, domainAxisIndex, ingo@2072: rangeAxisIndex, transX1, transY1, orientation); ingo@2072: ingo@2072: // add an entity for the item, but only if it falls within the data ingo@2072: // area... ingo@2072: if (entities != null && isPointInRect(dataArea, xx, yy)) { ingo@2072: addEntity(entities, entityArea, dataset, series, item, xx, yy); ingo@2072: } ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public void setIsMinimumShapeVisisble(int series, boolean isVisible) { ingo@2072: this.isMinimumShapeVisible.setBoolean(series, isVisible); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public boolean isMinimumShapeVisible(int series) { ingo@2072: return isMinimumShapeVisible.getBoolean(series); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public void setIsMaximumShapeVisible(int series, boolean isVisible) { ingo@2072: this.isMaximumShapeVisible.setBoolean(series, isVisible); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public boolean isMaximumShapeVisible(int series) { ingo@2072: return isMaximumShapeVisible.getBoolean(series); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public static boolean isMinimum(XYDataset dataset, int series, int item) { ingo@2072: return dataset.getYValue(series, item) == getMinimum(dataset, series); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public static double getMinimum(XYDataset dataset, int series) { ingo@2072: double min = Double.MAX_VALUE; ingo@2072: ingo@2072: for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { ingo@2072: double tmpValue = dataset.getYValue(series, i); ingo@2072: ingo@2072: if (tmpValue < min) { ingo@2072: min = tmpValue; ingo@2072: } ingo@2072: } ingo@2072: ingo@2072: return min; ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public static boolean isMaximum(XYDataset dataset, int series, int item) { ingo@2072: return dataset.getYValue(series, item) == getMaximum(dataset, series); ingo@2072: } ingo@2072: ingo@2072: ingo@2072: public static double getMaximum(XYDataset dataset, int series) { ingo@2072: double max = -Double.MAX_VALUE; ingo@2072: ingo@2072: for (int i = 0, n = dataset.getItemCount(series); i < n; i++) { ingo@2072: double tmpValue = dataset.getYValue(series, i); ingo@2072: ingo@2072: if (tmpValue > max) { ingo@2072: max = tmpValue; ingo@2072: } ingo@2072: } ingo@2072: ingo@2072: return max; ingo@2072: } ingo@2072: } ingo@2072: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :