[PATCH 1 of 2] Factor out annotation handling code
Wald Commits
scm-commit at wald.intevation.org
Wed Sep 18 17:13:20 CEST 2013
# HG changeset patch
# User Andre Heinecke <aheinecke at intevation.de>
# Date 1379517133 -7200
# Branch generator-refactoring
# Node ID 06a9a241faac9c2ca3b1bfba60d654c357692598
# Parent 599d3c48474c837dcbe4dcef117267caad27a98c
Factor out annotation handling code
diff -r 599d3c48474c -r 06a9a241faac artifacts/src/main/java/org/dive4elements/river/exports/ChartGenerator2.java
--- 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 at 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.
*/
diff -r 599d3c48474c -r 06a9a241faac artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java
--- a/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java Wed Sep 18 16:26:12 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/LongitudinalSectionGenerator.java Wed Sep 18 17:12:13 2013 +0200
@@ -23,6 +23,7 @@
import org.dive4elements.river.exports.process.BedheightProcessor;
import org.dive4elements.river.exports.process.QOutProcessor;
import org.dive4elements.river.exports.process.WOutProcessor;
+import org.dive4elements.river.exports.process.AnnotationProcessor;
import org.dive4elements.river.jfree.RiverAnnotation;
import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
@@ -340,11 +341,12 @@
return;
}
- WOutProcessor wProcessor = new WOutProcessor();
- QOutProcessor qProcessor = new QOutProcessor();
+ Processor wProcessor = new WOutProcessor();
+ Processor qProcessor = new QOutProcessor();
Processor bedp = new BedheightProcessor();
Processor bdyProcessor = new BedDiffYearProcessor();
Processor bdhyProcessor = new BedDiffHeightYearProcessor();
+ Processor annotationProcessor = new AnnotationProcessor();
if (wProcessor.canHandle(name)) {
wProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx);
@@ -361,12 +363,8 @@
else if (bdhyProcessor.canHandle(name)) {
bdhyProcessor.doOut(this, artifactAndFacet, attr, visible, YAXIS.W.idx);
}
- else if (name.equals(LONGITUDINAL_ANNOTATION)) {
- doAnnotations(
- (RiverAnnotation) artifactAndFacet.getData(context),
- artifactAndFacet,
- attr,
- visible);
+ else if (annotationProcessor.canHandle(name)) {
+ annotationProcessor.doOut(this, artifactAndFacet, attr, visible, 0);
}
else if (name.equals(W_DIFFERENCES)) {
doWDifferencesOut(
diff -r 599d3c48474c -r 06a9a241faac artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java
--- a/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Wed Sep 18 16:26:12 2013 +0200
+++ b/artifacts/src/main/java/org/dive4elements/river/exports/XYChartGenerator.java Wed Sep 18 17:12:13 2013 +0200
@@ -47,6 +47,7 @@
import org.dive4elements.river.jfree.StyledAreaSeriesCollection;
import org.dive4elements.river.jfree.StyledXYSeries;
import org.dive4elements.river.jfree.AxisDataset;
+import org.dive4elements.river.jfree.AnnotationHelper;
import org.dive4elements.river.themes.ThemeDocument;
@@ -150,7 +151,8 @@
//debugAxis(plot);
// These have to go after the autozoom.
- addAnnotationsToRenderer(plot);
+ AnnotationHelper.addAnnotationsToRenderer(annotations, plot,
+ getChartSettings(), datasets);
// Add a logo (maybe).
addLogo(plot);
diff -r 599d3c48474c -r 06a9a241faac artifacts/src/main/java/org/dive4elements/river/jfree/AnnotationHelper.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/artifacts/src/main/java/org/dive4elements/river/jfree/AnnotationHelper.java Wed Sep 18 17:12:13 2013 +0200
@@ -0,0 +1,366 @@
+/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde
+ * Software engineering by Intevation GmbH
+ *
+ * This file is Free Software under the GNU AGPL (>=v3)
+ * and comes with ABSOLUTELY NO WARRANTY! Check out the
+ * documentation coming with Dive4Elements River for details.
+ */
+package org.dive4elements.river.jfree;
+
+import org.dive4elements.river.artifacts.model.HYKFactory;
+import org.dive4elements.river.themes.ThemeDocument;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+
+import org.jfree.ui.TextAnchor;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.LegendItem;
+import org.jfree.chart.LegendItemCollection;
+import org.jfree.chart.annotations.XYTextAnnotation;
+import org.jfree.chart.annotations.XYLineAnnotation;
+
+import org.dive4elements.river.themes.LineStyle;
+import org.dive4elements.river.themes.TextStyle;
+import org.dive4elements.river.exports.ChartSettings;
+import org.dive4elements.river.exports.LegendSection;
+import org.dive4elements.river.exports.ChartArea;
+
+import org.apache.log4j.Logger;
+
+/** Annotation helper class, handles plotting of annotations. */
+public class AnnotationHelper {
+ private static final Logger logger = Logger.getLogger(AnnotationHelper.class);
+
+ protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f;
+
+ /* arr this would be better in chartsettings */
+ public static final int DEFAULT_FONT_SIZE = 12;
+ public static final String DEFAULT_FONT_NAME = "Tahoma";
+
+ /**
+ * Add annotations (Sticky, Text and hyk zones) to a plot.
+ * @param annotations Annotations to add
+ * @param plot Plot to add annotations to.
+ * @param settings ChartSettings object for settings.
+ */
+ public static void addAnnotationsToRenderer(List<RiverAnnotation> annotations,
+ XYPlot plot, ChartSettings settings, Map<Integer, AxisDataset> datasets) {
+ 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) {
+ // Legend handling, maybe misplaced?
+ LegendItemCollection lic = new LegendItemCollection();
+ LegendItemCollection old = plot.getFixedLegendItems();
+
+ Color color = theme.parseLineColorField();
+ if (color == null) {
+ color = Color.BLACK;
+ }
+
+ LegendItem newItem = new LegendItem(fa.getLabel(), color);
+ LegendSection ls = settings.getLegendSection();
+ newItem.setLabelFont (new Font(
+ DEFAULT_FONT_NAME,
+ Font.PLAIN,
+ ls != null ? ls.getFontSize() : null)
+ );
+
+ lic.add(newItem);
+ // (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,
+ datasets.get(new Integer(sta.getAxisSymbol())));
+ }
+
+ // 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);
+ }
+ }
+ }
+
+ /**
+ * Add a text and a line annotation.
+ * @param area convenience to determine positions in plot.
+ * @param theme (optional) theme document
+ */
+ public static void addStickyAnnotation(
+ StickyAxisAnnotation annotation,
+ XYPlot plot,
+ ChartArea area,
+ LineStyle lineStyle,
+ TextStyle textStyle,
+ ThemeDocument theme,
+ AxisDataset dataset
+ ) {
+ // 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).
+ 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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.
+ */
+ public 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);
+ }
+ }
+
+};
More information about the Dive4elements-commits
mailing list