Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/exports/ChartGenerator.java @ 3242:1dca41dba135
Move annotation code to base class ChartGenerator
flys-artifacts/trunk@4874 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Christian Lins <christian.lins@intevation.de> |
---|---|
date | Wed, 04 Jul 2012 22:28:44 +0000 |
parents | ed07dd55f487 |
children | dd3ddc8ecb14 |
comparison
equal
deleted
inserted
replaced
3241:da3e58694cae | 3242:1dca41dba135 |
---|---|
27 import org.w3c.dom.Element; | 27 import org.w3c.dom.Element; |
28 | 28 |
29 import org.jfree.chart.JFreeChart; | 29 import org.jfree.chart.JFreeChart; |
30 import org.jfree.chart.LegendItem; | 30 import org.jfree.chart.LegendItem; |
31 import org.jfree.chart.LegendItemCollection; | 31 import org.jfree.chart.LegendItemCollection; |
32 import org.jfree.chart.annotations.XYBoxAnnotation; | |
33 import org.jfree.chart.annotations.XYLineAnnotation; | |
34 import org.jfree.chart.annotations.XYTextAnnotation; | |
32 import org.jfree.chart.axis.NumberAxis; | 35 import org.jfree.chart.axis.NumberAxis; |
33 import org.jfree.chart.plot.XYPlot; | 36 import org.jfree.chart.plot.XYPlot; |
34 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; | 37 import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; |
35 import org.jfree.data.Range; | 38 import org.jfree.data.Range; |
36 import org.jfree.data.general.Series; | 39 import org.jfree.data.general.Series; |
37 import org.jfree.data.xy.XYDataset; | 40 import org.jfree.data.xy.XYDataset; |
38 import org.jfree.ui.RectangleInsets; | 41 import org.jfree.ui.RectangleInsets; |
42 import org.jfree.ui.TextAnchor; | |
39 | 43 |
40 import de.intevation.artifacts.Artifact; | 44 import de.intevation.artifacts.Artifact; |
45 import de.intevation.artifacts.ArtifactNamespaceContext; | |
41 import de.intevation.artifacts.CallContext; | 46 import de.intevation.artifacts.CallContext; |
42 import de.intevation.artifacts.CallMeta; | 47 import de.intevation.artifacts.CallMeta; |
43 import de.intevation.artifacts.PreferredLocale; | 48 import de.intevation.artifacts.PreferredLocale; |
44 | 49 |
45 import de.intevation.artifacts.ArtifactNamespaceContext; | |
46 import de.intevation.artifacts.common.utils.XMLUtils; | 50 import de.intevation.artifacts.common.utils.XMLUtils; |
47 | 51 |
48 import de.intevation.artifactdatabase.state.ArtifactAndFacet; | 52 import de.intevation.artifactdatabase.state.ArtifactAndFacet; |
53 import de.intevation.artifactdatabase.state.Facet; | |
49 import de.intevation.artifactdatabase.state.Settings; | 54 import de.intevation.artifactdatabase.state.Settings; |
50 | 55 |
51 import de.intevation.flys.model.River; | 56 import de.intevation.flys.model.River; |
52 | 57 |
53 import de.intevation.flys.artifacts.FLYSArtifact; | 58 import de.intevation.flys.artifacts.FLYSArtifact; |
59 | |
54 import de.intevation.flys.artifacts.resources.Resources; | 60 import de.intevation.flys.artifacts.resources.Resources; |
61 | |
62 import de.intevation.flys.artifacts.model.HYKFactory; | |
63 | |
55 import de.intevation.flys.jfree.Bounds; | 64 import de.intevation.flys.jfree.Bounds; |
65 import de.intevation.flys.jfree.CollisionFreeXYTextAnnotation; | |
56 import de.intevation.flys.jfree.DoubleBounds; | 66 import de.intevation.flys.jfree.DoubleBounds; |
57 import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer; | 67 import de.intevation.flys.jfree.EnhancedLineAndShapeRenderer; |
58 import de.intevation.flys.jfree.FLYSAnnotation; | 68 import de.intevation.flys.jfree.FLYSAnnotation; |
59 import de.intevation.flys.jfree.StableXYDifferenceRenderer; | 69 import de.intevation.flys.jfree.StableXYDifferenceRenderer; |
70 import de.intevation.flys.jfree.StickyAxisAnnotation; | |
60 import de.intevation.flys.jfree.StyledAreaSeriesCollection; | 71 import de.intevation.flys.jfree.StyledAreaSeriesCollection; |
61 import de.intevation.flys.jfree.Style; | 72 import de.intevation.flys.jfree.Style; |
62 import de.intevation.flys.jfree.StyledSeries; | 73 import de.intevation.flys.jfree.StyledSeries; |
74 | |
63 import de.intevation.flys.themes.ThemeAccess; | 75 import de.intevation.flys.themes.ThemeAccess; |
76 import de.intevation.flys.utils.ThemeUtil; | |
77 | |
64 import de.intevation.flys.utils.FLYSUtils; | 78 import de.intevation.flys.utils.FLYSUtils; |
65 | 79 |
66 | 80 |
67 /** | 81 /** |
68 * The base class for chart creation. It should provide some basic things that | 82 * The base class for chart creation. It should provide some basic things that |
80 public static final Color DEFAULT_GRID_COLOR = Color.GRAY; | 94 public static final Color DEFAULT_GRID_COLOR = Color.GRAY; |
81 public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f; | 95 public static final float DEFAULT_GRID_LINE_WIDTH = 0.3f; |
82 public static final int DEFAULT_FONT_SIZE = 12; | 96 public static final int DEFAULT_FONT_SIZE = 12; |
83 public static final String DEFAULT_FONT_NAME = "Tahoma"; | 97 public static final String DEFAULT_FONT_NAME = "Tahoma"; |
84 | 98 |
99 protected static float ANNOTATIONS_AXIS_OFFSET = 0.02f; | |
85 | 100 |
86 public static final String XPATH_CHART_SIZE = | 101 public static final String XPATH_CHART_SIZE = |
87 "/art:action/art:attributes/art:size"; | 102 "/art:action/art:attributes/art:size"; |
88 | 103 |
89 public static final String XPATH_CHART_FORMAT = | 104 public static final String XPATH_CHART_FORMAT = |
168 annotations = new ArrayList<FLYSAnnotation>(); | 183 annotations = new ArrayList<FLYSAnnotation>(); |
169 } | 184 } |
170 | 185 |
171 annotations.add(annotation); | 186 annotations.add(annotation); |
172 } | 187 } |
173 | 188 |
189 /** | |
190 * Add a text and a line annotation. | |
191 * @param area convenience to determine positions in plot. | |
192 * @param theme (optional) theme document | |
193 */ | |
194 protected void addStickyAnnotation( | |
195 StickyAxisAnnotation annotation, | |
196 XYPlot plot, | |
197 ChartArea area, | |
198 ThemeAccess.LineStyle lineStyle, | |
199 ThemeAccess.TextStyle textStyle, | |
200 Document theme | |
201 ) { | |
202 // OPTIMIZE pre-calculate area-related values | |
203 final float TEXT_OFF = 0.03f; | |
204 | |
205 XYLineAnnotation lineAnnotation = null; | |
206 XYTextAnnotation textAnnotation = null; | |
207 | |
208 int rendererIndex = 0; | |
209 | |
210 if (annotation.atX()) { | |
211 textAnnotation = new CollisionFreeXYTextAnnotation( | |
212 annotation.getText(), annotation.getPos(), area.ofGround(TEXT_OFF)); | |
213 // OPTIMIZE externalize the calculation involving PI. | |
214 //textAnnotation.setRotationAngle(270f*Math.PI/180f); | |
215 lineAnnotation = createGroundStickAnnotation( | |
216 area, annotation.getPos(), lineStyle); | |
217 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); | |
218 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); | |
219 } | |
220 else { | |
221 // Do the more complicated case where we stick to the Y-Axis. | |
222 // There is one nasty case (duration curves, where annotations | |
223 // might stick to the second y-axis). | |
224 // FIXME: Remove dependency to XYChartGenerator here | |
225 AxisDataset dataset = (XYChartGenerator.XYAxisDataset) getAxisDataset( | |
226 new Integer(annotation.getAxisSymbol())); | |
227 if (dataset == null) { | |
228 logger.warn("Annotation should stick to unfindable y-axis: " | |
229 + annotation.getAxisSymbol()); | |
230 rendererIndex = 0; | |
231 } | |
232 else { | |
233 rendererIndex = dataset.getPlotAxisIndex(); | |
234 } | |
235 | |
236 // Stick to the "right" (opposed to left) Y-Axis. | |
237 if (rendererIndex != 0) { | |
238 // OPTIMIZE: Pass a different area to this function, | |
239 // do the adding to renderer outside (let this | |
240 // function return the annotations). | |
241 // Note that this path is travelled rarely. | |
242 ChartArea area2 = new ChartArea(plot.getDomainAxis(), plot.getRangeAxis(rendererIndex)); | |
243 textAnnotation = new CollisionFreeXYTextAnnotation( | |
244 annotation.getText(), area2.ofRight(TEXT_OFF), annotation.getPos()); | |
245 textAnnotation.setRotationAnchor(TextAnchor.CENTER_RIGHT); | |
246 textAnnotation.setTextAnchor(TextAnchor.CENTER_RIGHT); | |
247 lineAnnotation = createRightStickAnnotation( | |
248 area2, annotation.getPos(), lineStyle); | |
249 if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { | |
250 // New line annotation to hit curve. | |
251 if (ThemeUtil.parseShowVerticalLine(theme)) { | |
252 XYLineAnnotation hitLineAnnotation = | |
253 createStickyLineAnnotation( | |
254 StickyAxisAnnotation.SimpleAxis.X_AXIS, | |
255 annotation.getHitPoint(), annotation.getPos(),// annotation.getHitPoint(), | |
256 area2, lineStyle); | |
257 plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, | |
258 org.jfree.ui.Layer.BACKGROUND); | |
259 } | |
260 if (ThemeUtil.parseShowHorizontalLine(theme)) { | |
261 XYLineAnnotation lineBackAnnotation = | |
262 createStickyLineAnnotation( | |
263 StickyAxisAnnotation.SimpleAxis.Y_AXIS2, | |
264 annotation.getPos(), annotation.getHitPoint(), | |
265 area2, lineStyle); | |
266 plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, | |
267 org.jfree.ui.Layer.BACKGROUND); | |
268 } | |
269 } | |
270 } | |
271 else { // Stick to the left y-axis. | |
272 textAnnotation = new CollisionFreeXYTextAnnotation( | |
273 annotation.getText(), area.ofLeft(TEXT_OFF), annotation.getPos()); | |
274 textAnnotation.setRotationAnchor(TextAnchor.CENTER_LEFT); | |
275 textAnnotation.setTextAnchor(TextAnchor.CENTER_LEFT); | |
276 lineAnnotation = createLeftStickAnnotation(area, annotation.getPos(), lineStyle); | |
277 if (!Float.isNaN(annotation.getHitPoint()) && theme != null) { | |
278 // New line annotation to hit curve. | |
279 if (ThemeUtil.parseShowHorizontalLine(theme)) { | |
280 XYLineAnnotation hitLineAnnotation = | |
281 createStickyLineAnnotation( | |
282 StickyAxisAnnotation.SimpleAxis.Y_AXIS, | |
283 annotation.getPos(), annotation.getHitPoint(), | |
284 area, lineStyle); | |
285 plot.getRenderer(rendererIndex).addAnnotation(hitLineAnnotation, | |
286 org.jfree.ui.Layer.BACKGROUND); | |
287 } | |
288 if (ThemeUtil.parseShowVerticalLine(theme)) { | |
289 XYLineAnnotation lineBackAnnotation = | |
290 createStickyLineAnnotation( | |
291 StickyAxisAnnotation.SimpleAxis.X_AXIS, | |
292 annotation.getHitPoint(), annotation.getPos(), | |
293 area, lineStyle); | |
294 plot.getRenderer(rendererIndex).addAnnotation(lineBackAnnotation, | |
295 org.jfree.ui.Layer.BACKGROUND); | |
296 } | |
297 } | |
298 } | |
299 } | |
300 | |
301 // Style the text. | |
302 if (textStyle != null) { | |
303 textStyle.apply(textAnnotation); | |
304 } | |
305 | |
306 // Add the Annotations to renderer. | |
307 plot.getRenderer(rendererIndex).addAnnotation(textAnnotation, | |
308 org.jfree.ui.Layer.FOREGROUND); | |
309 plot.getRenderer(rendererIndex).addAnnotation(lineAnnotation, | |
310 org.jfree.ui.Layer.FOREGROUND); | |
311 } | |
312 | |
313 /** | |
314 * Create annotation that sticks to "ground" (X) axis. | |
315 * @param area helper to calculate coordinates | |
316 * @param pos one-dimensional position (distance from axis) | |
317 * @param lineStyle the line style to use for the line. | |
318 */ | |
319 protected static XYLineAnnotation createGroundStickAnnotation( | |
320 ChartArea area, float pos, ThemeAccess.LineStyle lineStyle | |
321 ) { | |
322 // Style the line. | |
323 if (lineStyle != null) { | |
324 return new XYLineAnnotation( | |
325 pos, area.atGround(), | |
326 pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET), | |
327 new BasicStroke(lineStyle.getWidth()),lineStyle.getColor()); | |
328 } | |
329 else { | |
330 return new XYLineAnnotation( | |
331 pos, area.atGround(), | |
332 pos, area.ofGround(ANNOTATIONS_AXIS_OFFSET)); | |
333 } | |
334 } | |
335 | |
336 | |
337 /** | |
338 * Create annotation that sticks to the second Y axis ("right"). | |
339 * @param area helper to calculate coordinates | |
340 * @param pos one-dimensional position (distance from axis) | |
341 * @param lineStyle the line style to use for the line. | |
342 */ | |
343 protected static XYLineAnnotation createRightStickAnnotation( | |
344 ChartArea area, float pos, ThemeAccess.LineStyle lineStyle | |
345 ) { | |
346 // Style the line. | |
347 if (lineStyle != null) { | |
348 return new XYLineAnnotation( | |
349 area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos, | |
350 area.atRight(), pos, | |
351 new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); | |
352 } | |
353 else { | |
354 return new XYLineAnnotation( | |
355 area.atRight(), pos, | |
356 area.ofRight(ANNOTATIONS_AXIS_OFFSET), pos); | |
357 } | |
358 } | |
359 | |
360 | |
361 /** | |
362 * Create annotation that sticks to the first Y axis ("left"). | |
363 * @param area helper to calculate coordinates | |
364 * @param pos one-dimensional position (distance from axis) | |
365 * @param lineStyle the line style to use for the line. | |
366 */ | |
367 protected static XYLineAnnotation createLeftStickAnnotation( | |
368 ChartArea area, float pos, ThemeAccess.LineStyle lineStyle | |
369 ) { | |
370 // Style the line. | |
371 if (lineStyle != null) { | |
372 return new XYLineAnnotation( | |
373 area.atLeft(), pos, | |
374 area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos, | |
375 new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); | |
376 } | |
377 else { | |
378 return new XYLineAnnotation( | |
379 area.atLeft(), pos, | |
380 area.ofLeft(ANNOTATIONS_AXIS_OFFSET), pos); | |
381 } | |
382 } | |
383 | |
384 | |
385 /** | |
386 * Create a line from a axis to a given point. | |
387 * @param axis The "simple" axis. | |
388 * @param fromD1 from-location in first dimension. | |
389 * @param toD2 to-location in second dimension. | |
390 * @param area helper to calculate offsets. | |
391 * @param lineStyle optional line style. | |
392 */ | |
393 protected static XYLineAnnotation createStickyLineAnnotation( | |
394 StickyAxisAnnotation.SimpleAxis axis, float fromD1, float toD2, | |
395 ChartArea area, ThemeAccess.LineStyle lineStyle | |
396 ) { | |
397 double anchorX1 = 0d, anchorX2 = 0d, anchorY1 = 0d, anchorY2 = 0d; | |
398 switch(axis) { | |
399 case X_AXIS: | |
400 anchorX1 = fromD1; | |
401 anchorX2 = fromD1; | |
402 anchorY1 = area.atGround(); | |
403 anchorY2 = toD2; | |
404 break; | |
405 case Y_AXIS: | |
406 anchorX1 = area.atLeft(); | |
407 anchorX2 = toD2; | |
408 anchorY1 = fromD1; | |
409 anchorY2 = fromD1; | |
410 break; | |
411 case Y_AXIS2: | |
412 anchorX1 = area.atRight(); | |
413 anchorX2 = toD2; | |
414 anchorY1 = fromD1; | |
415 anchorY2 = fromD1; | |
416 break; | |
417 } | |
418 // Style the line. | |
419 if (lineStyle != null) { | |
420 return new XYLineAnnotation( | |
421 anchorX1, anchorY1, | |
422 anchorX2, anchorY2, | |
423 new BasicStroke(lineStyle.getWidth()), lineStyle.getColor()); | |
424 } | |
425 else { | |
426 return new XYLineAnnotation( | |
427 anchorX1, anchorY1, | |
428 anchorX2, anchorY2); | |
429 } | |
430 } | |
431 | |
432 /** | |
433 * Add the annotations (Sticky, Text and hyk zones) stored | |
434 * in the annotations field. | |
435 */ | |
436 protected void addAnnotationsToRenderer(XYPlot plot) { | |
437 logger.debug("addAnnotationsToRenderer"); | |
438 | |
439 if (annotations == null || annotations.size() == 0) { | |
440 logger.debug("addAnnotationsToRenderer: no annotations."); | |
441 return; | |
442 } | |
443 | |
444 // Paints for the boxes/lines. | |
445 Stroke basicStroke = new BasicStroke(1.0f); | |
446 | |
447 Paint linePaint = new Color(255, 0,0,60); | |
448 Paint fillPaint = new Color(0, 255,0,60); | |
449 Paint tranPaint = new Color(0, 0,0, 0); | |
450 | |
451 // OPTMIMIZE: Pre-calculate positions | |
452 ChartArea area = new ChartArea( | |
453 plot.getDomainAxis(0).getRange(), | |
454 plot.getRangeAxis().getRange()); | |
455 | |
456 // Walk over all Annotation sets. | |
457 for (FLYSAnnotation fa: annotations) { | |
458 | |
459 // Access text styling, if any. | |
460 Document theme = fa.getTheme(); | |
461 ThemeAccess.TextStyle textStyle = null; | |
462 ThemeAccess.LineStyle lineStyle = null; | |
463 | |
464 // Get Themeing information and add legend item. | |
465 if (theme != null) { | |
466 ThemeAccess themeAccess = new ThemeAccess(theme); | |
467 textStyle = themeAccess.parseTextStyle(); | |
468 lineStyle = themeAccess.parseLineStyle(); | |
469 if (fa.getLabel() != null) { | |
470 LegendItemCollection lic = new LegendItemCollection(); | |
471 LegendItemCollection old = plot.getFixedLegendItems(); | |
472 lic.add(createLegendItem(theme, fa.getLabel())); | |
473 // (Re-)Add prior legend entries. | |
474 if (old != null) { | |
475 old.addAll(lic); | |
476 } | |
477 else { | |
478 old = lic; | |
479 } | |
480 plot.setFixedLegendItems(old); | |
481 } | |
482 } | |
483 | |
484 // The 'Sticky' Annotations (at axis, with line and text). | |
485 for (StickyAxisAnnotation sta: fa.getAxisTextAnnotations()) { | |
486 addStickyAnnotation( | |
487 sta, plot, area, lineStyle, textStyle, theme); | |
488 } | |
489 | |
490 // Other Text Annotations (e.g. labels of (manual) points). | |
491 for (XYTextAnnotation ta: fa.getTextAnnotations()) { | |
492 // Style the text. | |
493 if (textStyle != null) { | |
494 textStyle.apply(ta); | |
495 } | |
496 ta.setY(area.above(0.05d, ta.getY())); | |
497 plot.getRenderer().addAnnotation(ta, org.jfree.ui.Layer.FOREGROUND); | |
498 } | |
499 | |
500 // Hyks. | |
501 for (HYKFactory.Zone zone: fa.getBoxes()) { | |
502 // For each zone, create a box to fill with color, a box to draw | |
503 // the lines and a text to display the type. | |
504 fillPaint = colorForHYKZone(zone.getName()); | |
505 | |
506 XYBoxAnnotation boxA = new XYBoxAnnotation(zone.getFrom(), area.atGround(), | |
507 zone.getTo(), area.ofGround(0.03f), basicStroke, tranPaint, fillPaint); | |
508 XYBoxAnnotation boxB = new XYBoxAnnotation(zone.getFrom(), area.atGround(), | |
509 zone.getTo(), area.atTop(), basicStroke, fillPaint, tranPaint); | |
510 | |
511 XYTextAnnotation tex = new XYTextAnnotation(zone.getName(), | |
512 zone.getFrom() + (zone.getTo() - zone.getFrom()) / 1.0d, | |
513 area.ofGround(0.015f)); | |
514 if (textStyle != null) { | |
515 textStyle.apply(tex); | |
516 } | |
517 | |
518 plot.getRenderer().addAnnotation(boxA, org.jfree.ui.Layer.BACKGROUND); | |
519 plot.getRenderer().addAnnotation(boxB, org.jfree.ui.Layer.BACKGROUND); | |
520 plot.getRenderer().addAnnotation(tex, org.jfree.ui.Layer.BACKGROUND); | |
521 } | |
522 } | |
523 } | |
524 | |
174 | 525 |
175 /** | 526 /** |
176 * This method needs to be implemented by concrete subclasses to create new | 527 * This method needs to be implemented by concrete subclasses to create new |
177 * instances of JFreeChart. | 528 * instances of JFreeChart. |
178 * | 529 * |
273 * @param chart The JFreeChart chart object. | 624 * @param chart The JFreeChart chart object. |
274 */ | 625 */ |
275 protected void addSubtitles(JFreeChart chart) { | 626 protected void addSubtitles(JFreeChart chart) { |
276 // do nothing | 627 // do nothing |
277 } | 628 } |
278 | 629 |
630 | |
631 /** Get color for hyk zones by their type (which is the name). */ | |
632 protected Paint colorForHYKZone(String zoneName) { | |
633 if (zoneName.startsWith("R")) { | |
634 // Brownish. | |
635 return new Color(153, 60, 0); | |
636 } | |
637 else if (zoneName.startsWith("V")) { | |
638 // Greenish. | |
639 return new Color(0, 255, 0); | |
640 } | |
641 else if (zoneName.startsWith("B")) { | |
642 // Grayish. | |
643 return new Color(128, 128, 128); | |
644 } | |
645 else if (zoneName.startsWith("H")) { | |
646 // Blueish. | |
647 return new Color(0, 0, 255); | |
648 } | |
649 else { | |
650 // Default. | |
651 logger.debug("Unknown zone type found."); | |
652 return new Color(255, 0, 0); | |
653 } | |
654 } | |
655 | |
656 | |
657 /** | |
658 * Register annotations like MainValues for later plotting | |
659 * | |
660 * @param annotations list of annotations (data of facet). | |
661 * @param aandf Artifact and the facet. | |
662 * @param theme Theme document for given annotations. | |
663 * @param visible The visibility of the annotations. | |
664 */ | |
665 protected void doAnnotations( | |
666 FLYSAnnotation annotations, | |
667 ArtifactAndFacet aandf, | |
668 Document theme, | |
669 boolean visible | |
670 ){ | |
671 // Running into trouble here. | |
672 logger.debug("doAnnotations"); | |
673 | |
674 // Add all annotations to our annotation pool. | |
675 annotations.setTheme(theme); | |
676 if (aandf != null) { | |
677 Facet facet = aandf.getFacet(); | |
678 annotations.setLabel(aandf.getFacetDescription()); | |
679 } | |
680 else { | |
681 logger.debug( | |
682 "Art/Facet for Annotations is null. " + | |
683 "This should never happen!"); | |
684 } | |
685 | |
686 if (visible) { | |
687 addAnnotations(annotations); | |
688 } | |
689 } | |
690 | |
279 | 691 |
280 /** | 692 /** |
281 * Generate chart. | 693 * Generate chart. |
282 */ | 694 */ |
283 @Override | 695 @Override |