/** * * The MIT License * * Copyright (c) 2011 the original author or authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.googlecode.charts4j.parameters; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.List; import java.util.Locale; import com.googlecode.charts4j.Color; import com.googlecode.charts4j.Data; import com.googlecode.charts4j.Marker; import com.googlecode.charts4j.Priority; import com.googlecode.charts4j.ShapeMarker; import com.googlecode.charts4j.TextMarker; import com.googlecode.charts4j.collect.Lists; /** * Class for building chart markers parameter string for the Google Chart API. * * @author Julien Chastang (julien.c.chastang at gmail dot com) */ final class ChartMarkersParameter extends AbstractParameter { /** The Google Chart API chart markers parameter. */ private static final String URL_PARAMETER_KEY = "chm"; /** The markers. */ private final List<GoogleChartMarker> markers = Lists.newLinkedList(); /** * Adds the fill area marker. * * @param fillAreaType * the fill area type * @param color * the color * @param startLineIndex * the start line index * @param endLineIndex * the end line index */ void addFillAreaMarker(final FillAreaType fillAreaType, final Color color, final int startLineIndex, final int endLineIndex) { markers.add(new FillAreaMarker(fillAreaType, color, startLineIndex, endLineIndex)); } /** * Adds the line style marker. * * @param color * the color * @param dataSetIndex * the data set index * @param dataPoint * the data point * @param size * the size * @param priority * the priority */ void addLineStyleMarker(final Color color, final int dataSetIndex, final int dataPoint, final int size, final Priority priority) { markers.add(new LineStyleMarker(color, dataSetIndex, dataPoint, size, priority)); } /** * Adds the marker. * * @param marker * the marker * @param dataSetIndex * the data set index * @param startIndex * The start index for the marker range. * @param endIndex * The end index for the marker range. * @param n * Marker on every n-th data point. */ void addMarker(final Marker marker, final int dataSetIndex, final int startIndex, final int endIndex, final int n) { if (marker instanceof ShapeMarker) { markers.add(new ShapeMarkerParam((ShapeMarker) marker, dataSetIndex, startIndex, endIndex, n)); } else if (marker instanceof TextMarker) { markers.add(new TextMarkerParam((TextMarker) marker, dataSetIndex, startIndex, endIndex, n)); } } /** * Add marker to each point on the plot. * * @param marker * the marker * @param dataSetIndex * the data set index */ void addMarkers(final Marker marker, final int dataSetIndex) { //-1 adds the same shape marker to each point on the plot. addMarker(marker, dataSetIndex, -1, 0, 0); } /** * Adds the vertical range marker. * * @param color * the color * @param startPoint * the start point * @param endPoint * the end point */ void addVerticalRangeMarker(final Color color, final double startPoint, final double endPoint) { markers.add(new RangeMarker(RangeType.VERTICAL, color, startPoint, endPoint)); } /** * Adds the horizontal range marker. * * @param color * the color * @param startPoint * the start point * @param endPoint * the end point */ void addHorizontalRangeMarker(final Color color, final double startPoint, final double endPoint) { markers.add(new RangeMarker(RangeType.HORIZONTAL, color, startPoint, endPoint)); } /** * Adds the free marker. * * @param marker * the marker * @param xPos * the x pos * @param yPos * the y pos */ void addFreeMarker(final Marker marker, final double xPos, final double yPos) { markers.add(new FreeMarker(marker, xPos, yPos)); } /** * {@inheritDoc} */ @Override public String getKey() { return URL_PARAMETER_KEY; } /** * {@inheritDoc} */ @Override public String getValue() { final StringBuilder sb = new StringBuilder(); int cnt = 0; for (GoogleChartMarker m : markers) { sb.append(cnt++ > 0 ? "|" : "").append(m); } return !markers.isEmpty() ? sb.toString() : ""; } /** * The GoogleChartMarker tag interface. */ private interface GoogleChartMarker { } /** * The Class GMarker. */ private static class GMarker implements GoogleChartMarker { /** The marker. */ private final String marker; /** The color. */ private final Color color; /** The data set index. */ private final int dataSetIndex; /** The start index. */ private final int startIndex; /** The end index. */ private final int endIndex; /** The periodicity. */ private final int n; /** The size. */ private final int size; /** The priority. */ private final Priority priority; /** * Instantiates a new g marker. * * @param marker * the marker * @param color * the color * @param dataSetIndex * the data set index * @param startIndex * The start index for the marker range. * @param endIndex * The end index for the marker range. * @param n * Marker on every n-th data point. * @param size * the size * @param priority * the priority */ private GMarker(final String marker, final Color color, final int dataSetIndex, final int startIndex, final int endIndex, final int n, final int size, final Priority priority) { this.marker = marker; this.color = color; this.dataSetIndex = dataSetIndex; this.startIndex = startIndex; this.endIndex = endIndex; this.n = n; this.size = size; this.priority = priority; } /** * {@inheritDoc} */ @Override public String toString() { final String returnString; if (startIndex >= 0 && endIndex == startIndex + 1) { returnString = marker + "," + color + "," + dataSetIndex + "," + startIndex + "," + size + "," + priority; } else if (startIndex == -1) { returnString = marker + "," + color + "," + dataSetIndex + "," + startIndex + "," + size + "," + priority; } else {//(endIndex - 1) ---> The GCA is end point inclusive. returnString = marker + "," + color + "," + dataSetIndex + "," + startIndex + ":" + (endIndex - 1) + ":" + n + "," + size + "," + priority; } return returnString; } } /** * The Class LineStyleMarker. */ private static final class LineStyleMarker extends GMarker implements GoogleChartMarker { /** * Instantiates a new line style marker. * * @param color * the color * @param dataSetIndex * the data set index * @param dataPoint * the data point * @param size * the size * @param priority * the priority */ private LineStyleMarker(final Color color, final int dataSetIndex, final int dataPoint, final int size, final Priority priority) { super("D", color, dataSetIndex, dataPoint, dataPoint + 1, 1, size, priority); } } /** * The Class ShapeMarkerParam. */ private static final class ShapeMarkerParam extends GMarker implements GoogleChartMarker { /** * Instantiates a new shape marker param. * * @param shapeMarker * the shape marker * @param dataSetIndex * the data set index * @param startIndex * The start index for the marker range. * @param endIndex * The end index for the marker range. * @param n * Marker on every n-th data point. */ private ShapeMarkerParam(final ShapeMarker shapeMarker, final int dataSetIndex, final int startIndex, final int endIndex, final int n) { super(shapeMarker.getShape().toString(), shapeMarker.getColor(), dataSetIndex, startIndex, endIndex, n, shapeMarker.getSize(), shapeMarker.getPriority()); } } /** * The Class TextMarkerParam. */ private static final class TextMarkerParam extends GMarker implements GoogleChartMarker { /** * Instantiates a new text marker param. * * @param textMarker * the text marker * @param dataSetIndex * the data set index * @param startIndex * The start index for the marker range. * @param endIndex * The end index for the marker range. * @param n * Marker on every n-th data point. */ private TextMarkerParam(final TextMarker textMarker, final int dataSetIndex, final int startIndex, final int endIndex, final int n) { super((textMarker.isFlagged() ? "f" : "t") + ParameterUtil.utf8Encode(textMarker.getText()), textMarker.getColor(), dataSetIndex, startIndex, endIndex, n, textMarker.getSize(), textMarker.getPriority()); } } /** * The Class FillAreaMarker. */ private static final class FillAreaMarker implements GoogleChartMarker { /** The fill area type. */ private final FillAreaType fillAreaType; /** The color. */ private final Color color; /** The start line index. */ private final int startLineIndex; /** The end line index. */ private final int endLineIndex; /** * Instantiates a new fill area marker. * * @param fillAreaType * the fill area type * @param color * the color * @param startLineIndex * the start line index * @param endLineIndex * the end line index */ private FillAreaMarker(final FillAreaType fillAreaType, final Color color, final int startLineIndex, final int endLineIndex) { this.fillAreaType = fillAreaType; this.color = color; this.startLineIndex = startLineIndex; this.endLineIndex = endLineIndex; } /** * {@inheritDoc} */ @Override public String toString() { return fillAreaType + "," + color + "," + startLineIndex + "," + endLineIndex + ",0"; } } /** * The Class RangeMarker. */ private static final class RangeMarker implements GoogleChartMarker { /** The range type. */ private final RangeType rangeType; /** The color. */ private final Color color; /** The start point. */ private final double startPoint; /** The end point. */ private final double endPoint; /** The decimal formatter. */ private final DecimalFormat decimalFormatter = new DecimalFormat("0.00", new DecimalFormatSymbols(Locale.US)); /** * Instantiates a new range marker. * * @param rangeType * the range type * @param color * the color * @param startPoint * the start point * @param endPoint * the end point */ private RangeMarker(final RangeType rangeType, final Color color, final double startPoint, final double endPoint) { this.rangeType = rangeType; this.color = color; this.startPoint = startPoint; this.endPoint = endPoint; } /** * {@inheritDoc} */ @Override public String toString() { return rangeType + "," + color + ",0," + decimalFormatter.format(startPoint) + "," + decimalFormatter.format(endPoint); } } /** * Private static inner class to encapsulate a FreeMarker. */ private static class FreeMarker implements GoogleChartMarker { /** The marker. */ private final Marker marker; /** The x pos. */ private final double xPos; /** The y pos. */ private final double yPos; /** * Instantiates a new free marker. * * @param marker * the marker * @param xPos * the x pos * @param yPos * the y pos */ private FreeMarker(final Marker marker, final double xPos, final double yPos) { this.marker = marker; this.xPos = xPos; this.yPos = yPos; } /** * {@inheritDoc} */ @Override public String toString() { final String s; if (marker instanceof TextMarker) { final TextMarker m = (TextMarker) marker; s = "@" + (m.isFlagged() ? "f" : "t") + m.getText() + "," + m.getColor() + ",0," + xPos / Data.MAX_VALUE + ":" + yPos / Data.MAX_VALUE + "," + m.getSize() + "," + m.getPriority(); } else if (marker instanceof ShapeMarker) { final ShapeMarker m = (ShapeMarker) marker; s = "@" + m.getShape().toString() + "," + m.getColor() + ",0," + xPos / Data.MAX_VALUE + ":" + yPos / Data.MAX_VALUE + "," + m.getSize() + "," + m.getPriority(); } else { s = ""; } return s; } } }