Coverage Report - net.sf.statcvs.charts.SymbolicNameAnnotation
 
Classes in this File Line Coverage Branch Coverage Complexity
SymbolicNameAnnotation
0%
0/45
0%
0/12
2.5
 
 1  
 package net.sf.statcvs.charts;
 2  
 
 3  
 import java.awt.BasicStroke;
 4  
 import java.awt.Color;
 5  
 import java.awt.Font;
 6  
 import java.awt.Graphics2D;
 7  
 import java.awt.Stroke;
 8  
 import java.awt.geom.Line2D;
 9  
 import java.awt.geom.Rectangle2D;
 10  
 import java.util.ArrayList;
 11  
 import java.util.Collection;
 12  
 import java.util.Collections;
 13  
 import java.util.Iterator;
 14  
 import java.util.List;
 15  
 
 16  
 import net.sf.statcvs.model.SymbolicName;
 17  
 
 18  
 import org.jfree.chart.annotations.XYAnnotation;
 19  
 import org.jfree.chart.axis.ValueAxis;
 20  
 import org.jfree.chart.plot.Plot;
 21  
 import org.jfree.chart.plot.PlotOrientation;
 22  
 import org.jfree.chart.plot.PlotRenderingInfo;
 23  
 import org.jfree.chart.plot.XYPlot;
 24  
 import org.jfree.text.TextUtilities;
 25  
 import org.jfree.ui.RectangleEdge;
 26  
 import org.jfree.ui.TextAnchor;
 27  
 
 28  
 /**
 29  
  * SymbolicNameAnnotation
 30  
  * 
 31  
  * Provides symbolic name annotations for XYPlots with java.util.Date
 32  
  * objects on the domain axis.
 33  
  * 
 34  
  * TODO: Move vertically to accommodate annotations that are close together 
 35  
  * 
 36  
  * @author Tammo van Lessen
 37  
  * @version $Id: SymbolicNameAnnotation.java,v 1.6 2008/04/02 11:22:15 benoitx Exp $
 38  
  */
 39  
 public class SymbolicNameAnnotation implements XYAnnotation {
 40  
     public static final int STYLE_DEFAULT = 0;
 41  
     public static final int STYLE_NO_LABELS = 1;
 42  
     public static final float MIN_LABEL_X_SPACING = 7.0f;
 43  
 
 44  
     public static List createAnnotations(final Collection symbolicNames) {
 45  0
         return createAnnotations(symbolicNames, STYLE_DEFAULT);
 46  
     }
 47  
 
 48  
     public static List createAnnotations(final Collection symbolicNames, final int style) {
 49  0
         final List annotations = new ArrayList();
 50  0
         for (final Iterator it = symbolicNames.iterator(); it.hasNext();) {
 51  0
             final SymbolicName sn = (SymbolicName) it.next();
 52  0
             annotations.add(new SymbolicNameAnnotation(sn, symbolicNames, style));
 53  0
         }
 54  0
         return annotations;
 55  
     }
 56  
 
 57  0
     private final Color linePaint = Color.GRAY;
 58  0
     private final Color textPaint = Color.DARK_GRAY;
 59  0
     private final Font font = new Font("Dialog", Font.PLAIN, 9);
 60  0
     private final static Stroke STROKE = new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, new float[] { 3.5f }, 0.0f);
 61  
 
 62  
     private final SymbolicName symbolicName;
 63  
     private final List allSymbolicNames;
 64  
     private final int style;
 65  
 
 66  
     /**
 67  
      * Creates an annotation for a symbolic name.
 68  
      * Paints a gray dashed vertical line at the symbolic names
 69  
      * date position and draws its name at the top left.
 70  
      * 
 71  
      * @param symbolicName
 72  
      * @param style {@link #STYLE_HEAVY} or {@link #STYLE_LIGHT}
 73  
      */
 74  0
     public SymbolicNameAnnotation(final SymbolicName symbolicName, final Collection all, final int style) {
 75  0
         this.symbolicName = symbolicName;
 76  0
         this.allSymbolicNames = new ArrayList(all);
 77  0
         Collections.sort(this.allSymbolicNames);
 78  0
         this.style = style;
 79  0
     }
 80  
 
 81  
     /**
 82  
      * @see org.jfree.chart.annotations.XYAnnotation#draw(java.awt.Graphics2D, org.jfree.chart.plot.XYPlot, java.awt.geom.Rectangle2D, org.jfree.chart.axis.ValueAxis, org.jfree.chart.axis.ValueAxis, int, org.jfree.chart.plot.PlotRenderingInfo)
 83  
      */
 84  
     public void draw(final Graphics2D g2d, final XYPlot xyPlot, final Rectangle2D dataArea, final ValueAxis domainAxis, final ValueAxis rangeAxis,
 85  
             final int rendererIndex, final PlotRenderingInfo info) {
 86  0
         final PlotOrientation orientation = xyPlot.getOrientation();
 87  
 
 88  
         // don't draw the annotation if symbolic names date is out of axis' bounds.
 89  0
         if (domainAxis.getUpperBound() < symbolicName.getDate().getTime() || domainAxis.getLowerBound() > symbolicName.getDate().getTime()) {
 90  
 
 91  0
             return;
 92  
         }
 93  
 
 94  0
         final RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(xyPlot.getDomainAxisLocation(), orientation);
 95  0
         final RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(xyPlot.getRangeAxisLocation(), orientation);
 96  
 
 97  0
         final float x = getNaturalX(symbolicName, dataArea, domainAxis, domainEdge);
 98  
 
 99  0
         final float y1 = (float) rangeAxis.valueToJava2D(rangeAxis.getUpperBound(), dataArea, rangeEdge);
 100  0
         final float y2 = (float) rangeAxis.valueToJava2D(rangeAxis.getLowerBound(), dataArea, rangeEdge);
 101  
 
 102  0
         g2d.setPaint(linePaint);
 103  0
         g2d.setStroke(STROKE);
 104  
 
 105  0
         final Line2D line = new Line2D.Float(x, y1, x, y2);
 106  0
         g2d.draw(line);
 107  
 
 108  0
         if (this.style == STYLE_NO_LABELS) {
 109  0
             return;
 110  
         }
 111  0
         g2d.setFont(font);
 112  0
         g2d.setPaint(textPaint);
 113  0
         TextUtilities.drawRotatedString(symbolicName.getName(), g2d, getArrangedLabelX(symbolicName, dataArea, domainAxis, domainEdge), y1 + 2,
 114  
                 TextAnchor.BOTTOM_RIGHT, -Math.PI / 2, TextAnchor.BOTTOM_RIGHT);
 115  0
     }
 116  
 
 117  
     private float getArrangedLabelX(final SymbolicName tag, final Rectangle2D dataArea, final ValueAxis domainAxis, final RectangleEdge domainEdge) {
 118  0
         final float naturalX = getNaturalX(tag, dataArea, domainAxis, domainEdge);
 119  0
         final int offset = this.allSymbolicNames.indexOf(tag);
 120  0
         if (offset == this.allSymbolicNames.size() - 1) {
 121  0
             return naturalX;
 122  
         }
 123  0
         final SymbolicName next = (SymbolicName) this.allSymbolicNames.get(offset + 1);
 124  0
         final float nextX = getArrangedLabelX(next, dataArea, domainAxis, domainEdge);
 125  0
         if (nextX > naturalX + MIN_LABEL_X_SPACING) {
 126  0
             return naturalX;
 127  
         }
 128  0
         return nextX - MIN_LABEL_X_SPACING;
 129  
     }
 130  
 
 131  
     private float getNaturalX(final SymbolicName tag, final Rectangle2D dataArea, final ValueAxis domainAxis, final RectangleEdge domainEdge) {
 132  0
         return (float) domainAxis.valueToJava2D(tag.getDate().getTime(), dataArea, domainEdge);
 133  
     }
 134  
 }