Mercurial > dive4elements > river
diff artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java @ 7043:06a9a241faac generator-refactoring
Factor out annotation handling code
author | Andre Heinecke <aheinecke@intevation.de> |
---|---|
date | Wed, 18 Sep 2013 17:12:13 +0200 |
parents | 557cb3a3d772 |
children | 726d998dce29 |
line wrap: on
line diff
--- a/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java Wed Sep 18 16:26:12 2013 +0200 +++ b/artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java Wed Sep 18 17:12:13 2013 +0200 @@ -21,12 +21,10 @@ import org.dive4elements.river.artifacts.resources.Resources; import org.dive4elements.river.collections.D4EArtifactCollection; import org.dive4elements.river.jfree.Bounds; -import org.dive4elements.river.jfree.CollisionFreeXYTextAnnotation; import org.dive4elements.river.jfree.DoubleBounds; import org.dive4elements.river.jfree.EnhancedLineAndShapeRenderer; import org.dive4elements.river.jfree.RiverAnnotation; import org.dive4elements.river.jfree.StableXYDifferenceRenderer; -import org.dive4elements.river.jfree.StickyAxisAnnotation; import org.dive4elements.river.jfree.Style; import org.dive4elements.river.jfree.StyledAreaSeriesCollection; import org.dive4elements.river.jfree.StyledSeries; @@ -60,8 +58,6 @@ import org.jfree.chart.JFreeChart; import org.jfree.chart.LegendItem; import org.jfree.chart.LegendItemCollection; -import org.jfree.chart.annotations.XYLineAnnotation; -import org.jfree.chart.annotations.XYTextAnnotation; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; @@ -77,15 +73,9 @@ import org.dive4elements.river.utils.Formatter; /** - * The base class for chart creation. It should provide some basic things that - * equal in all chart types. + * Implementation of the OutGenerator interface for charts. + * It should provide some basic things that equal in all chart types. * - * Annotations are added as RiverAnnotations and come in mutliple basic forms: - * TextAnnotations are labels somewhere in data space, StickyAnnotations are - * labels of a slice or line in one data dimension (i.e. visualized as label - * on a single axis). - * - * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> */ public abstract class ChartGenerator2 implements OutGenerator { @@ -99,7 +89,6 @@ public static final int DEFAULT_FONT_SIZE = 12; public static final String DEFAULT_FONT_NAME = "Tahoma"; - protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f; public static final String XPATH_CHART_SIZE = "/art:action/art:attributes/art:size"; @@ -155,7 +144,6 @@ datasets = new TreeMap<Integer, AxisDataset>(); } - /** * Adds annotations to list. The given annotation will be visible. */ @@ -164,313 +152,6 @@ } /** - * Add a text and a line annotation. - * @param area convenience to determine positions in plot. - * @param theme (optional) theme document - */ - protected void addStickyAnnotation( - StickyAxisAnnotation annotation, - XYPlot plot, - ChartArea area, - LineStyle lineStyle, - TextStyle textStyle, - ThemeDocument theme - ) { - // OPTIMIZE pre-calculate area-related values - final float TEXT_OFF = 0.03f; - - XYLineAnnotation lineAnnotation = null; - XYTextAnnotation textAnnotation = null; - - int rendererIndex = 0; - - if (annotation.atX()) { - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); - // OPTIMIZE externalize the calculation involving PI. - //textAnnotation.setRotationAngle(270f*Math.PI/180f); - lineAnnotation = createGroundStickAnnotation( - area, annotation.getPos(), lineStyle); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); - } - else { - // Do the more complicated case where we stick to the Y-Axis. - // There is one nasty case (duration curves, where annotations - // might stick to the second y-axis). - // FIXME: Remove dependency to XYChartGenerator2 here - AxisDataset dataset = getAxisDataset( - new Integer(annotation.getAxisSymbol())); - if (dataset == null) { - logger.warn("Annotation should stick to unfindable y-axis: " - + annotation.getAxisSymbol()); - rendererIndex = 0; - } - else { - rendererIndex = dataset.getPlotAxisIndex(); - } - - // Stick to the "right" (opposed to left) Y-Axis. - if (rendererIndex != 0) { - // OPTIMIZE: Pass a different area to this function, - // do the adding to renderer outside (let this - // function return the annotations). - // Note that this path is travelled rarely. - ChartArea area2 = new ChartArea(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex)); - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos()); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT); - lineAnnotation = createRightStickAnnotation( - area2, annotation.getPos(), lineStyle); - if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { - // New line annotation to hit curve. - if (theme.parseShowVerticalLine()) { - XYLineAnnotation hitLineAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.X_AXIS, - annotation.getHitPoint(), annotation.getPos(),// annotation.getHitPoint(), - area2, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - if (theme.parseShowHorizontalLine()) { - XYLineAnnotation lineBackAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.Y_AXIS2, - annotation.getPos(), annotation.getHitPoint(), - area2, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - } - } - else { // Stick to the left y-axis. - textAnnotation = new CollisionFreeXYTextAnnotation( - annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); - textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); - textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); - lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle); - if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { - // New line annotation to hit curve. - if (theme.parseShowHorizontalLine()) { - XYLineAnnotation hitLineAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.Y_AXIS, - annotation.getPos(), annotation.getHitPoint(), - area, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - if (theme.parseShowVerticalLine()) { - XYLineAnnotation lineBackAnnotation = - createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis.X_AXIS, - annotation.getHitPoint(), annotation.getPos(), - area, lineStyle); - plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, - org.jfree.ui.Layer.BACKGROUND); - } - } - } - } - - // Style the text. - if (textStyle != null) { - textStyle.apply(textAnnotation); - } - - // Add the Annotations to renderer. - plot.getRenderer(rendererIndex).addAnnotation(textAnnotation, - org.jfree.ui.Layer.FOREGROUND); - plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation, - org.jfree.ui.Layer.FOREGROUND); - } - - /** - * Create annotation that sticks to "ground" (X) axis. - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createGroundStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - pos, area.atGround(), - pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET), - new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - pos, area.atGround(), - pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET)); - } - } - - - /** - * Create annotation that sticks to the second Y axis ("right"). - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createRightStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos, - area.atRight(), pos, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - area.atRight(), pos, - area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos); - } - } - - - /** - * Create annotation that sticks to the first Y axis ("left"). - * @param area helper to calculate coordinates - * @param pos one-dimensional position (distance from axis) - * @param lineStyle the line style to use for the line. - */ - protected static XYLineAnnotation createLeftStickAnnotation( - ChartArea area, float pos, LineStyle lineStyle - ) { - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - area.atLeft(), pos, - area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - area.atLeft(), pos, - area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos); - } - } - - - /** - * Create a line from a axis to a given point. - * @param axis The "simple" axis. - * @param fromD1 from-location in first dimension. - * @param toD2 to-location in second dimension. - * @param area helper to calculate offsets. - * @param lineStyle optional line style. - */ - protected static XYLineAnnotation createStickyLineAnnotation( - StickyAxisAnnotation.SimpleAxis axis, float fromD1, float toD2, - ChartArea area, LineStyle lineStyle - ) { - double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d; - switch(axis) { - case X_AXIS: - anchorX1 = fromD1; - anchorX2 = fromD1; - anchorY1 = area.atGround(); - anchorY2 = toD2; - break; - case Y_AXIS: - anchorX1 = area.atLeft(); - anchorX2 = toD2; - anchorY1 = fromD1; - anchorY2 = fromD1; - break; - case Y_AXIS2: - anchorX1 = area.atRight(); - anchorX2 = toD2; - anchorY1 = fromD1; - anchorY2 = fromD1; - break; - } - // Style the line. - if (lineStyle != null) { - return new XYLineAnnotation( - anchorX1, anchorY1, - anchorX2, anchorY2, - new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); - } - else { - return new XYLineAnnotation( - anchorX1, anchorY1, - anchorX2, anchorY2); - } - } - - /** - * Add the annotations (Sticky, Text and hyk zones) stored - * in the annotations field. - * @param plot Plot to add annotations to. - */ - protected void addAnnotationsToRenderer(XYPlot plot) { - logger.debug("addAnnotationsToRenderer"); - - if (annotations == null || annotations.isEmpty()) { - logger.debug("addAnnotationsToRenderer: no annotations."); - return; - } - - // OPTMIMIZE: Pre-calculate positions - ChartArea area = new ChartArea( - plot.getDomainAxis(0).getRange(), - plot.getRangeAxis().getRange()); - - // Walk over all Annotation sets. - for (RiverAnnotation fa: annotations) { - - // Access text styling, if any. - ThemeDocument theme = fa.getTheme(); - TextStyle textStyle = null; - LineStyle lineStyle = null; - - // Get Themeing information and add legend item. - if (theme != null) { - textStyle = theme.parseComplexTextStyle(); - lineStyle = theme.parseComplexLineStyle(); - if (fa.getLabel() != null) { - LegendItemCollection lic = new LegendItemCollection(); - LegendItemCollection old = plot.getFixedLegendItems(); - lic.add(createLegendItem(theme, fa.getLabel())); - // (Re-)Add prior legend entries. - if (old != null) { - old.addAll(lic); - } - else { - old = lic; - } - plot.setFixedLegendItems(old); - } - } - - // The 'Sticky' Annotations (at axis, with line and text). - for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) { - addStickyAnnotation( - sta, plot, area, lineStyle, textStyle, theme); - } - - // Other Text Annotations (e.g. labels of (manual) points). - for (XYTextAnnotation ta: fa.getTextAnnotations()) { - // Style the text. - if (textStyle != null) { - textStyle.apply(ta); - } - ta.setY(area.above(0.05d, ta.getY())); - plot.getRenderer().addAnnotation(ta, org.jfree.ui.Layer.FOREGROUND); - } - } - } - - - /** * This method needs to be implemented by concrete subclasses to create new * instances of JFreeChart. * @@ -585,40 +266,6 @@ } } - - /** - * Register annotations like MainValues for later plotting - * - * @param annotations list of annotations (data of facet). - * @param aandf Artifact and the facet. - * @param theme Theme document for given annotations. - * @param visible The visibility of the annotations. - */ - public void doAnnotations( - RiverAnnotation annotations, - ArtifactAndFacet aandf, - ThemeDocument theme, - boolean visible - ){ - logger.debug("doAnnotations"); - - // Add all annotations to our annotation pool. - annotations.setTheme(theme); - if (aandf != null) { - annotations.setLabel(aandf.getFacetDescription()); - } - else { - logger.error( - "Art/Facet for Annotations is null. " + - "This should never happen!"); - } - - if (visible) { - addAnnotations(annotations); - } - } - - /** * Generate chart. */