Merge commit '42b2e5ca519766e37ce6941ba4faecc9691cc403' into upstream
[debian/openrocket] / android-libraries / achartengine / src / org / achartengine / chart / BarChart.java
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/BarChart.java b/android-libraries/achartengine/src/org/achartengine/chart/BarChart.java
new file mode 100644 (file)
index 0000000..d5d0fb2
--- /dev/null
@@ -0,0 +1,329 @@
+/**\r
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL\r
+ *  \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *  \r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *  \r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.achartengine.chart;\r
+\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Color;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.RectF;\r
+import android.graphics.drawable.GradientDrawable;\r
+import android.graphics.drawable.GradientDrawable.Orientation;\r
+\r
+/**\r
+ * The bar chart rendering class.\r
+ */\r
+public class BarChart extends XYChart {\r
+  /** The constant to identify this chart type. */\r
+  public static final String TYPE = "Bar";\r
+  /** The legend shape width. */\r
+  private static final int SHAPE_WIDTH = 12;\r
+  /** The chart type. */\r
+  protected Type mType = Type.DEFAULT;\r
+\r
+  /**\r
+   * The bar chart type enum.\r
+   */\r
+  public enum Type {\r
+    DEFAULT, STACKED;\r
+  }\r
+\r
+  BarChart() {\r
+  }\r
+\r
+  BarChart(Type type) {\r
+    mType = type;\r
+  }\r
+\r
+  /**\r
+   * Builds a new bar chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   * @param type the bar chart type\r
+   */\r
+  public BarChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type) {\r
+    super(dataset, renderer);\r
+    mType = type;\r
+  }\r
+\r
+  @Override\r
+  protected ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex) {\r
+    int seriesNr = mDataset.getSeriesCount();\r
+    int length = points.length;\r
+    ClickableArea[] ret = new ClickableArea[length / 2];\r
+    float halfDiffX = getHalfDiffX(points, length, seriesNr);\r
+    for (int i = 0; i < length; i += 2) {\r
+      float x = points[i];\r
+      float y = points[i + 1];\r
+      if (mType == Type.STACKED) {\r
+        ret[i / 2] = new ClickableArea(new RectF(x - halfDiffX, y, x + halfDiffX, yAxisValue),\r
+            values[i], values[i + 1]);\r
+      } else {\r
+        float startX = x - seriesNr * halfDiffX + seriesIndex * 2 * halfDiffX;\r
+        ret[i / 2] = new ClickableArea(new RectF(startX, y, startX + 2 * halfDiffX, yAxisValue),\r
+            values[i], values[i + 1]);\r
+      }\r
+    }\r
+    return ret;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a series.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param points the array of points to be used for drawing the series\r
+   * @param seriesRenderer the series renderer\r
+   * @param yAxisValue the minimum value of the y axis\r
+   * @param seriesIndex the index of the series currently being drawn\r
+   * @param startIndex the start index of the rendering points\r
+   */\r
+  public void drawSeries(Canvas canvas, Paint paint, float[] points,\r
+      SimpleSeriesRenderer seriesRenderer, float yAxisValue, int seriesIndex, int startIndex) {\r
+    int seriesNr = mDataset.getSeriesCount();\r
+    int length = points.length;\r
+    paint.setColor(seriesRenderer.getColor());\r
+    paint.setStyle(Style.FILL);\r
+    float halfDiffX = getHalfDiffX(points, length, seriesNr);\r
+    for (int i = 0; i < length; i += 2) {\r
+      float x = points[i];\r
+      float y = points[i + 1];\r
+      drawBar(canvas, x, yAxisValue, x, y, halfDiffX, seriesNr, seriesIndex, paint);\r
+    }\r
+    paint.setColor(seriesRenderer.getColor());\r
+  }\r
+\r
+  /**\r
+   * Draws a bar.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param xMin the X axis minimum\r
+   * @param yMin the Y axis minimum\r
+   * @param xMax the X axis maximum\r
+   * @param yMax the Y axis maximum\r
+   * @param halfDiffX half the size of a bar\r
+   * @param seriesNr the total number of series\r
+   * @param seriesIndex the current series index\r
+   * @param paint the paint\r
+   */\r
+  protected void drawBar(Canvas canvas, float xMin, float yMin, float xMax, float yMax,\r
+      float halfDiffX, int seriesNr, int seriesIndex, Paint paint) {\r
+    int scale = mDataset.getSeriesAt(seriesIndex).getScaleNumber();\r
+    if (mType == Type.STACKED) {\r
+      drawBar(canvas, xMin - halfDiffX, yMax, xMax + halfDiffX, yMin, scale, seriesIndex, paint);\r
+    } else {\r
+      float startX = xMin - seriesNr * halfDiffX + seriesIndex * 2 * halfDiffX;\r
+      drawBar(canvas, startX, yMax, startX + 2 * halfDiffX, yMin, scale, seriesIndex, paint);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Draws a bar.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param xMin the X axis minimum\r
+   * @param yMin the Y axis minimum\r
+   * @param xMax the X axis maximum\r
+   * @param yMax the Y axis maximum\r
+   * @param scale the scale index\r
+   * @param seriesIndex the current series index\r
+   * @param paint the paint\r
+   */\r
+  private void drawBar(Canvas canvas, float xMin, float yMin, float xMax, float yMax, int scale,\r
+      int seriesIndex, Paint paint) {\r
+    SimpleSeriesRenderer renderer = mRenderer.getSeriesRendererAt(seriesIndex);\r
+    if (renderer.isGradientEnabled()) {\r
+      float minY = (float) toScreenPoint(new double[] { 0, renderer.getGradientStopValue() }, scale)[1];\r
+      float maxY = (float) toScreenPoint(new double[] { 0, renderer.getGradientStartValue() },\r
+          scale)[1];\r
+      float gradientMinY = Math.max(minY, Math.min(yMin, yMax));\r
+      float gradientMaxY = Math.min(maxY, Math.max(yMin, yMax));\r
+      int gradientMinColor = renderer.getGradientStopColor();\r
+      int gradientMaxColor = renderer.getGradientStartColor();\r
+      int gradientStartColor = gradientMaxColor;\r
+      int gradientStopColor = gradientMinColor;\r
+\r
+      if (yMin < minY) {\r
+        paint.setColor(gradientMinColor);\r
+        canvas.drawRect(Math.round(xMin), Math.round(yMin), Math.round(xMax),\r
+            Math.round(gradientMinY), paint);\r
+      } else {\r
+        gradientStopColor = getGradientPartialColor(gradientMinColor, gradientMaxColor,\r
+            (maxY - gradientMinY) / (maxY - minY));\r
+      }\r
+      if (yMax > maxY) {\r
+        paint.setColor(gradientMaxColor);\r
+        canvas.drawRect(Math.round(xMin), Math.round(gradientMaxY), Math.round(xMax),\r
+            Math.round(yMax), paint);\r
+      } else {\r
+        gradientStartColor = getGradientPartialColor(gradientMaxColor, gradientMinColor,\r
+            (gradientMaxY - minY) / (maxY - minY));\r
+      }\r
+      GradientDrawable gradient = new GradientDrawable(Orientation.BOTTOM_TOP, new int[] {\r
+          gradientStartColor, gradientStopColor });\r
+      gradient.setBounds(Math.round(xMin), Math.round(gradientMinY), Math.round(xMax),\r
+          Math.round(gradientMaxY));\r
+      gradient.draw(canvas);\r
+    } else {\r
+      if (Math.abs(yMin - yMax) < 1) {\r
+        if (yMin < yMax) {\r
+          yMax = yMin + 1;\r
+        } else {\r
+          yMax = yMin - 1;\r
+        }\r
+      }\r
+      canvas\r
+          .drawRect(Math.round(xMin), Math.round(yMin), Math.round(xMax), Math.round(yMax), paint);\r
+    }\r
+  }\r
+\r
+  private int getGradientPartialColor(int minColor, int maxColor, float fraction) {\r
+    int alpha = Math.round(fraction * Color.alpha(minColor) + (1 - fraction)\r
+        * Color.alpha(maxColor));\r
+    int r = Math.round(fraction * Color.red(minColor) + (1 - fraction) * Color.red(maxColor));\r
+    int g = Math.round(fraction * Color.green(minColor) + (1 - fraction) * Color.green(maxColor));\r
+    int b = Math.round(fraction * Color.blue(minColor) + (1 - fraction) * Color.blue((maxColor)));\r
+    return Color.argb(alpha, r, g, b);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the series values as text.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param series the series to be painted\r
+   * @param renderer the series renderer\r
+   * @param paint the paint to be used for drawing\r
+   * @param points the array of points to be used for drawing the series\r
+   * @param seriesIndex the index of the series currently being drawn\r
+   * @param startIndex the start index of the rendering points\r
+   */\r
+  protected void drawChartValuesText(Canvas canvas, XYSeries series, SimpleSeriesRenderer renderer,\r
+      Paint paint, float[] points, int seriesIndex, int startIndex) {\r
+    int seriesNr = mDataset.getSeriesCount();\r
+    float halfDiffX = getHalfDiffX(points, points.length, seriesNr);\r
+    for (int i = 0; i < points.length; i += 2) {\r
+      int index = startIndex + i / 2;\r
+      double value = series.getY(index);\r
+      if (!isNullValue(value)) {\r
+        float x = points[i];\r
+        if (mType == Type.DEFAULT) {\r
+          x += seriesIndex * 2 * halfDiffX - (seriesNr - 1.5f) * halfDiffX;\r
+        }\r
+        if (value >= 0) {\r
+          drawText(canvas, getLabel(value), x, points[i + 1] - renderer.getChartValuesSpacing(),\r
+              paint, 0);\r
+        } else {\r
+          drawText(canvas, getLabel(value), x, points[i + 1] + renderer.getChartValuesTextSize()\r
+              + renderer.getChartValuesSpacing() - 3, paint, 0);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the legend shape width.\r
+   * \r
+   * @param seriesIndex the series index\r
+   * @return the legend shape width\r
+   */\r
+  public int getLegendShapeWidth(int seriesIndex) {\r
+    return SHAPE_WIDTH;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the legend shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param renderer the series renderer\r
+   * @param x the x value of the point the shape should be drawn at\r
+   * @param y the y value of the point the shape should be drawn at\r
+   * @param seriesIndex the series index\r
+   * @param paint the paint to be used for drawing\r
+   */\r
+  public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x, float y,\r
+      int seriesIndex, Paint paint) {\r
+    float halfShapeWidth = SHAPE_WIDTH / 2;\r
+    canvas.drawRect(x, y - halfShapeWidth, x + SHAPE_WIDTH, y + halfShapeWidth, paint);\r
+  }\r
+\r
+  /**\r
+   * Calculates and returns the half-distance in the graphical representation of\r
+   * 2 consecutive points.\r
+   * \r
+   * @param points the points\r
+   * @param length the points length\r
+   * @param seriesNr the series number\r
+   * @return the calculated half-distance value\r
+   */\r
+  protected float getHalfDiffX(float[] points, int length, int seriesNr) {\r
+    int div = length;\r
+    if (length > 2) {\r
+      div = length - 2;\r
+    }\r
+    float halfDiffX = (points[length - 2] - points[0]) / div;\r
+    if (halfDiffX == 0) {\r
+      halfDiffX = 10;\r
+    }\r
+\r
+    if (mType != Type.STACKED) {\r
+      halfDiffX /= seriesNr;\r
+    }\r
+    return (float) (halfDiffX / (getCoeficient() * (1 + mRenderer.getBarSpacing())));\r
+  }\r
+\r
+  /**\r
+   * Returns the value of a constant used to calculate the half-distance.\r
+   * \r
+   * @return the constant value\r
+   */\r
+  protected float getCoeficient() {\r
+    return 1f;\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart should display the null values.\r
+   * \r
+   * @return if null values should be rendered\r
+   */\r
+  protected boolean isRenderNullValues() {\r
+    return true;\r
+  }\r
+\r
+  /**\r
+   * Returns the default axis minimum.\r
+   * \r
+   * @return the default axis minimum\r
+   */\r
+  public double getDefaultMinimum() {\r
+    return 0;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart type identifier.\r
+   * \r
+   * @return the chart type\r
+   */\r
+  public String getChartType() {\r
+    return TYPE;\r
+  }\r
+}\r