Added source code for achartengine 1.0.0 in order to apply patches to make it work...
authorkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 28 Jun 2012 13:32:57 +0000 (13:32 +0000)
committerkruland2607 <kruland2607@180e2498-e6e9-4542-8430-84ac67f01cd8>
Thu, 28 Jun 2012 13:32:57 +0000 (13:32 +0000)
git-svn-id: https://openrocket.svn.sourceforge.net/svnroot/openrocket/trunk@818 180e2498-e6e9-4542-8430-84ac67f01cd8

66 files changed:
android-libraries/achartengine/.classpath [new file with mode: 0644]
android-libraries/achartengine/.project [new file with mode: 0644]
android-libraries/achartengine/AndroidManifest.xml [new file with mode: 0644]
android-libraries/achartengine/extra/LICENSE-2.0.txt [new file with mode: 0644]
android-libraries/achartengine/project.properties [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/ChartFactory.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/GraphicalActivity.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/GraphicalView.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/ITouchHandler.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/TouchHandler.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/TouchHandlerOld.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/AbstractChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/BarChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/BubbleChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/ClickableArea.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/CombinedXYChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/CubicLineChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/DialChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/DoughnutChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/LineChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/PieChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/PieMapper.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/PieSegment.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/PointStyle.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/RangeBarChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/RangeStackedBarChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/RoundChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/ScatterChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/TimeChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/XYChart.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/chart/package.html [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/image/zoom-1.png [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/image/zoom_in.png [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/image/zoom_out.png [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/CategorySeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/MultipleCategorySeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/Point.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/RangeCategorySeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/SeriesSelection.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/TimeSeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/XYMultipleSeriesDataset.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/XYSeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/XYValueSeries.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/model/package.html [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/package.html [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/BasicStroke.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/DefaultRenderer.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/DialRenderer.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/SimpleSeriesRenderer.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/XYMultipleSeriesRenderer.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/XYSeriesRenderer.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/renderer/package.html [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/AbstractTool.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/FitZoom.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/Pan.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/PanListener.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/Zoom.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/ZoomEvent.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/tools/ZoomListener.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/util/IndexXYMap.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/util/MathHelper.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/util/XYEntry.java [new file with mode: 0644]
android-libraries/achartengine/src/org/achartengine/util/package.html [new file with mode: 0644]
android/.classpath
android/libs/achartengine-1.0.0.jar [deleted file]
android/project.properties

diff --git a/android-libraries/achartengine/.classpath b/android-libraries/achartengine/.classpath
new file mode 100644 (file)
index 0000000..a4f1e40
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="src" path="gen"/>\r
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>\r
+       <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>\r
+       <classpathentry kind="output" path="bin/classes"/>\r
+</classpath>\r
diff --git a/android-libraries/achartengine/.project b/android-libraries/achartengine/.project
new file mode 100644 (file)
index 0000000..fb1c756
--- /dev/null
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>achartengine</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>com.android.ide.eclipse.adt.ApkBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>com.android.ide.eclipse.adt.AndroidNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/android-libraries/achartengine/AndroidManifest.xml b/android-libraries/achartengine/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..083e05f
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="org.achartengine.chartdemo.demo"
+      android:versionCode="1"
+      android:versionName="1.0.0">
+
+<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="7"></uses-sdk>
+</manifest> 
\ No newline at end of file
diff --git a/android-libraries/achartengine/extra/LICENSE-2.0.txt b/android-libraries/achartengine/extra/LICENSE-2.0.txt
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/android-libraries/achartengine/project.properties b/android-libraries/achartengine/project.properties
new file mode 100644 (file)
index 0000000..337e8f3
--- /dev/null
@@ -0,0 +1,12 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-7
+android.library=true
diff --git a/android-libraries/achartengine/src/org/achartengine/ChartFactory.java b/android-libraries/achartengine/src/org/achartengine/ChartFactory.java
new file mode 100644 (file)
index 0000000..301f1a8
--- /dev/null
@@ -0,0 +1,708 @@
+/**\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;\r
+\r
+import org.achartengine.chart.BarChart;\r
+import org.achartengine.chart.BarChart.Type;\r
+import org.achartengine.chart.BubbleChart;\r
+import org.achartengine.chart.CombinedXYChart;\r
+import org.achartengine.chart.CubicLineChart;\r
+import org.achartengine.chart.DialChart;\r
+import org.achartengine.chart.DoughnutChart;\r
+import org.achartengine.chart.LineChart;\r
+import org.achartengine.chart.PieChart;\r
+import org.achartengine.chart.RangeBarChart;\r
+import org.achartengine.chart.ScatterChart;\r
+import org.achartengine.chart.TimeChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.model.CategorySeries;\r
+import org.achartengine.model.MultipleCategorySeries;\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.DialRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+\r
+import android.content.Context;\r
+import android.content.Intent;\r
+\r
+/**\r
+ * Utility methods for creating chart views or intents.\r
+ */\r
+public class ChartFactory {\r
+  /** The key for the chart data. */\r
+  public static final String CHART = "chart";\r
+\r
+  /** The key for the chart graphical activity title. */\r
+  public static final String TITLE = "title";\r
+\r
+  private ChartFactory() {\r
+    // empty for now\r
+  }\r
+\r
+  /**\r
+   * Creates a line chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a line chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getLineChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new LineChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a cubic line chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a line chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getCubeLineChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, float smoothness) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new CubicLineChart(dataset, renderer, smoothness);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a scatter chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a scatter chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getScatterChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new ScatterChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a bubble chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a scatter chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getBubbleChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new BubbleChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a time chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param format the date format pattern to be used for displaying the X axis\r
+   *          date labels. If null, a default appropriate format will be used.\r
+   * @return a time chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getTimeChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, String format) {\r
+    checkParameters(dataset, renderer);\r
+    TimeChart chart = new TimeChart(dataset, renderer);\r
+    chart.setDateFormat(format);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a bar chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param type the bar chart type\r
+   * @return a bar chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getBarChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new BarChart(dataset, renderer, type);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a range bar chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param type the range bar chart type\r
+   * @return a bar chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final GraphicalView getRangeBarChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type) {\r
+    checkParameters(dataset, renderer);\r
+    XYChart chart = new RangeBarChart(dataset, renderer, type);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a combined XY chart view.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param types the chart types (cannot be null)\r
+   * @return a combined XY chart graphical view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if a dataset number of items is different than the number of\r
+   *           series renderers or number of chart types\r
+   */\r
+  public static final GraphicalView getCombinedXYChartView(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, String[] types) {\r
+    if (dataset == null || renderer == null || types == null\r
+        || dataset.getSeriesCount() != types.length) {\r
+      throw new IllegalArgumentException(\r
+          "Dataset, renderer and types should be not null and the datasets series count should be equal to the types length");\r
+    }\r
+    checkParameters(dataset, renderer);\r
+    CombinedXYChart chart = new CombinedXYChart(dataset, renderer, types);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a pie chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @return a pie chart view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final GraphicalView getPieChartView(Context context, CategorySeries dataset,\r
+      DefaultRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    PieChart chart = new PieChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a dial chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the dial renderer (cannot be null)\r
+   * @return a pie chart view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final GraphicalView getDialChartView(Context context, CategorySeries dataset,\r
+      DialRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    DialChart chart = new DialChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * Creates a doughnut chart intent that can be used to start the graphical\r
+   * view activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @return a pie chart view\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final GraphicalView getDoughnutChartView(Context context,\r
+      MultipleCategorySeries dataset, DefaultRenderer renderer) {\r
+    checkParameters(dataset, renderer);\r
+    DoughnutChart chart = new DoughnutChart(dataset, renderer);\r
+    return new GraphicalView(context, chart);\r
+  }\r
+\r
+  /**\r
+   * \r
+   * Creates a line chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a line chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getLineChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    return getLineChartIntent(context, dataset, renderer, "");\r
+  }\r
+\r
+  /**\r
+   * \r
+   * Creates a cubic line chart intent that can be used to start the graphical\r
+   * view activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a line chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getCubicLineChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, float smoothness) {\r
+    return getCubicLineChartIntent(context, dataset, renderer, smoothness, "");\r
+  }\r
+\r
+  /**\r
+   * Creates a scatter chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a scatter chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getScatterChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    return getScatterChartIntent(context, dataset, renderer, "");\r
+  }\r
+\r
+  /**\r
+   * Creates a bubble chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @return a scatter chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getBubbleChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    return getBubbleChartIntent(context, dataset, renderer, "");\r
+  }\r
+\r
+  /**\r
+   * Creates a time chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param format the date format pattern to be used for displaying the X axis\r
+   *          date labels. If null, a default appropriate format will be used.\r
+   * @return a time chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getTimeChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, String format) {\r
+    return getTimeChartIntent(context, dataset, renderer, format, "");\r
+  }\r
+\r
+  /**\r
+   * Creates a bar chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param type the bar chart type\r
+   * @return a bar chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getBarChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, Type type) {\r
+    return getBarChartIntent(context, dataset, renderer, type, "");\r
+  }\r
+\r
+  /**\r
+   * Creates a line chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title. If this is null,\r
+   *          then the title bar will be hidden. If a blank title is passed in,\r
+   *          then the title bar will be the default. Pass in any other string\r
+   *          to set a custom title.\r
+   * @return a line chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getLineChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    XYChart chart = new LineChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a line chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title. If this is null,\r
+   *          then the title bar will be hidden. If a blank title is passed in,\r
+   *          then the title bar will be the default. Pass in any other string\r
+   *          to set a custom title.\r
+   * @return a line chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getCubicLineChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, float smoothness,\r
+      String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    XYChart chart = new CubicLineChart(dataset, renderer, smoothness);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a scatter chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a scatter chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getScatterChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    XYChart chart = new ScatterChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a bubble chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a scatter chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getBubbleChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    XYChart chart = new BubbleChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a time chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param format the date format pattern to be used for displaying the X axis\r
+   *          date labels. If null, a default appropriate format will be used\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a time chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getTimeChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, String format, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    TimeChart chart = new TimeChart(dataset, renderer);\r
+    chart.setDateFormat(format);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a bar chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param type the bar chart type\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a bar chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getBarChartIntent(Context context, XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer, Type type, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    BarChart chart = new BarChart(dataset, renderer, type);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a range bar chart intent that can be used to start the graphical\r
+   * view activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param type the range bar chart type\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a range bar chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  public static final Intent getRangeBarChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type,\r
+      String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    RangeBarChart chart = new RangeBarChart(dataset, renderer, type);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a combined XY chart intent that can be used to start the graphical\r
+   * view activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @param types the chart types (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a combined XY chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if a dataset number of items is different than the number of\r
+   *           series renderers or number of chart types\r
+   */\r
+  public static final Intent getCombinedXYChartIntent(Context context,\r
+      XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, String[] types,\r
+      String activityTitle) {\r
+    if (dataset == null || renderer == null || types == null\r
+        || dataset.getSeriesCount() != types.length) {\r
+      throw new IllegalArgumentException(\r
+          "Datasets, renderers and types should be not null and the datasets series count should be equal to the types length");\r
+    }\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    CombinedXYChart chart = new CombinedXYChart(dataset, renderer, types);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a pie chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a pie chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final Intent getPieChartIntent(Context context, CategorySeries dataset,\r
+      DefaultRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    PieChart chart = new PieChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a doughnut chart intent that can be used to start the graphical\r
+   * view activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the multiple category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a pie chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final Intent getDoughnutChartIntent(Context context,\r
+      MultipleCategorySeries dataset, DefaultRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    DoughnutChart chart = new DoughnutChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Creates a dial chart intent that can be used to start the graphical view\r
+   * activity.\r
+   * \r
+   * @param context the context\r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the dial renderer (cannot be null)\r
+   * @param activityTitle the graphical chart activity title\r
+   * @return a dial chart intent\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  public static final Intent getDialChartIntent(Context context, CategorySeries dataset,\r
+      DialRenderer renderer, String activityTitle) {\r
+    checkParameters(dataset, renderer);\r
+    Intent intent = new Intent(context, GraphicalActivity.class);\r
+    DialChart chart = new DialChart(dataset, renderer);\r
+    intent.putExtra(CHART, chart);\r
+    intent.putExtra(TITLE, activityTitle);\r
+    return intent;\r
+  }\r
+\r
+  /**\r
+   * Checks the validity of the dataset and renderer parameters.\r
+   * \r
+   * @param dataset the multiple series dataset (cannot be null)\r
+   * @param renderer the multiple series renderer (cannot be null)\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset and the renderer don't include the same number of\r
+   *           series\r
+   */\r
+  private static void checkParameters(XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    if (dataset == null || renderer == null\r
+        || dataset.getSeriesCount() != renderer.getSeriesRendererCount()) {\r
+      throw new IllegalArgumentException(\r
+          "Dataset and renderer should be not null and should have the same number of series");\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Checks the validity of the dataset and renderer parameters.\r
+   * \r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  private static void checkParameters(CategorySeries dataset, DefaultRenderer renderer) {\r
+    if (dataset == null || renderer == null\r
+        || dataset.getItemCount() != renderer.getSeriesRendererCount()) {\r
+      throw new IllegalArgumentException(\r
+          "Dataset and renderer should be not null and the dataset number of items should be equal to the number of series renderers");\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Checks the validity of the dataset and renderer parameters.\r
+   * \r
+   * @param dataset the category series dataset (cannot be null)\r
+   * @param renderer the series renderer (cannot be null)\r
+   * @throws IllegalArgumentException if dataset is null or renderer is null or\r
+   *           if the dataset number of items is different than the number of\r
+   *           series renderers\r
+   */\r
+  private static void checkParameters(MultipleCategorySeries dataset, DefaultRenderer renderer) {\r
+    if (dataset == null || renderer == null\r
+        || !checkMultipleSeriesItems(dataset, renderer.getSeriesRendererCount())) {\r
+      throw new IllegalArgumentException(\r
+          "Titles and values should be not null and the dataset number of items should be equal to the number of series renderers");\r
+    }\r
+  }\r
+\r
+  private static boolean checkMultipleSeriesItems(MultipleCategorySeries dataset, int value) {\r
+    int count = dataset.getCategoriesCount();\r
+    boolean equal = true;\r
+    for (int k = 0; k < count && equal; k++) {\r
+      equal = dataset.getValues(k).length == dataset.getTitles(k).length;\r
+    }\r
+    return equal;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/GraphicalActivity.java b/android-libraries/achartengine/src/org/achartengine/GraphicalActivity.java
new file mode 100644 (file)
index 0000000..56c190a
--- /dev/null
@@ -0,0 +1,48 @@
+/**\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;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+\r
+import android.app.Activity;\r
+import android.os.Bundle;\r
+import android.view.Window;\r
+\r
+/**\r
+ * An activity that encapsulates a graphical view of the chart.\r
+ */\r
+public class GraphicalActivity extends Activity {\r
+  /** The encapsulated graphical view. */\r
+  private GraphicalView mView;\r
+  /** The chart to be drawn. */\r
+  private AbstractChart mChart;\r
+\r
+  @Override\r
+  protected void onCreate(Bundle savedInstanceState) {\r
+    super.onCreate(savedInstanceState);\r
+    Bundle extras = getIntent().getExtras();\r
+    mChart = (AbstractChart) extras.getSerializable(ChartFactory.CHART);\r
+    mView = new GraphicalView(this, mChart);\r
+    String title = extras.getString(ChartFactory.TITLE);\r
+    if (title == null) {\r
+      requestWindowFeature(Window.FEATURE_NO_TITLE);\r
+    } else if (title.length() > 0) {\r
+      setTitle(title);\r
+    }\r
+    setContentView(mView);\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/GraphicalView.java b/android-libraries/achartengine/src/org/achartengine/GraphicalView.java
new file mode 100644 (file)
index 0000000..e9aebff
--- /dev/null
@@ -0,0 +1,337 @@
+/**\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;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.model.Point;\r
+import org.achartengine.model.SeriesSelection;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.tools.FitZoom;\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.Zoom;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.content.Context;\r
+import android.graphics.Bitmap;\r
+import android.graphics.BitmapFactory;\r
+import android.graphics.Canvas;\r
+import android.graphics.Color;\r
+import android.graphics.Paint;\r
+import android.graphics.Rect;\r
+import android.graphics.RectF;\r
+import android.os.Build;\r
+import android.os.Handler;\r
+import android.view.MotionEvent;\r
+import android.view.View;\r
+\r
+/**\r
+ * The view that encapsulates the graphical chart.\r
+ */\r
+public class GraphicalView extends View {\r
+  /** The chart to be drawn. */\r
+  private AbstractChart mChart;\r
+  /** The chart renderer. */\r
+  private DefaultRenderer mRenderer;\r
+  /** The view bounds. */\r
+  private Rect mRect = new Rect();\r
+  /** The user interface thread handler. */\r
+  private Handler mHandler;\r
+  /** The zoom buttons rectangle. */\r
+  private RectF mZoomR = new RectF();\r
+  /** The zoom in icon. */\r
+  private Bitmap zoomInImage;\r
+  /** The zoom out icon. */\r
+  private Bitmap zoomOutImage;\r
+  /** The fit zoom icon. */\r
+  private Bitmap fitZoomImage;\r
+  /** The zoom area size. */\r
+  private int zoomSize = 50;\r
+  /** The zoom buttons background color. */\r
+  private static final int ZOOM_BUTTONS_COLOR = Color.argb(175, 150, 150, 150);\r
+  /** The zoom in tool. */\r
+  private Zoom mZoomIn;\r
+  /** The zoom out tool. */\r
+  private Zoom mZoomOut;\r
+  /** The fit zoom tool. */\r
+  private FitZoom mFitZoom;\r
+  /** The paint to be used when drawing the chart. */\r
+  private Paint mPaint = new Paint();\r
+  /** The touch handler. */\r
+  private ITouchHandler mTouchHandler;\r
+  /** The old x coordinate. */\r
+  private float oldX;\r
+  /** The old y coordinate. */\r
+  private float oldY;\r
+\r
+  /**\r
+   * Creates a new graphical view.\r
+   * \r
+   * @param context the context\r
+   * @param chart the chart to be drawn\r
+   */\r
+  public GraphicalView(Context context, AbstractChart chart) {\r
+    super(context);\r
+    mChart = chart;\r
+    mHandler = new Handler();\r
+    if (mChart instanceof XYChart) {\r
+      mRenderer = ((XYChart) mChart).getRenderer();\r
+    } else {\r
+      mRenderer = ((RoundChart) mChart).getRenderer();\r
+    }\r
+    if (mRenderer.isZoomButtonsVisible()) {\r
+      zoomInImage = BitmapFactory.decodeStream(GraphicalView.class\r
+          .getResourceAsStream("image/zoom_in.png"));\r
+      zoomOutImage = BitmapFactory.decodeStream(GraphicalView.class\r
+          .getResourceAsStream("image/zoom_out.png"));\r
+      fitZoomImage = BitmapFactory.decodeStream(GraphicalView.class\r
+          .getResourceAsStream("image/zoom-1.png"));\r
+    }\r
+\r
+    if (mRenderer instanceof XYMultipleSeriesRenderer\r
+        && ((XYMultipleSeriesRenderer) mRenderer).getMarginsColor() == XYMultipleSeriesRenderer.NO_COLOR) {\r
+      ((XYMultipleSeriesRenderer) mRenderer).setMarginsColor(mPaint.getColor());\r
+    }\r
+    if (mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()\r
+        || mRenderer.isExternalZoomEnabled()) {\r
+      mZoomIn = new Zoom(mChart, true, mRenderer.getZoomRate());\r
+      mZoomOut = new Zoom(mChart, false, mRenderer.getZoomRate());\r
+      mFitZoom = new FitZoom(mChart);\r
+    }\r
+    int version = 7;\r
+    try {\r
+      version = Integer.valueOf(Build.VERSION.SDK);\r
+    } catch (Exception e) {\r
+      // do nothing\r
+    }\r
+    if (version < 7) {\r
+      mTouchHandler = new TouchHandlerOld(this, mChart);\r
+    } else {\r
+      mTouchHandler = new TouchHandler(this, mChart);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the current series selection object.\r
+   * \r
+   * @return the series selection\r
+   */\r
+  public SeriesSelection getCurrentSeriesAndPoint() {\r
+    return mChart.getSeriesAndPointForScreenCoordinate(new Point(oldX, oldY));\r
+  }\r
+\r
+  /**\r
+   * Transforms the currently selected screen point to a real point.\r
+   * \r
+   * @param scale the scale\r
+   * @return the currently selected real point\r
+   */\r
+  public double[] toRealPoint(int scale) {\r
+    if (mChart instanceof XYChart) {\r
+      XYChart chart = (XYChart) mChart;\r
+      return chart.toRealPoint(oldX, oldY, scale);\r
+    }\r
+    return null;\r
+  }\r
+\r
+  @Override\r
+  protected void onDraw(Canvas canvas) {\r
+    super.onDraw(canvas);\r
+    canvas.getClipBounds(mRect);\r
+    int top = mRect.top;\r
+    int left = mRect.left;\r
+    int width = mRect.width();\r
+    int height = mRect.height();\r
+    if (mRenderer.isInScroll()) {\r
+      top = 0;\r
+      left = 0;\r
+      width = getMeasuredWidth();\r
+      height = getMeasuredHeight();\r
+    }\r
+    mChart.draw(canvas, left, top, width, height, mPaint);\r
+    if (mRenderer != null && mRenderer.isZoomEnabled() && mRenderer.isZoomButtonsVisible()) {\r
+      mPaint.setColor(ZOOM_BUTTONS_COLOR);\r
+      zoomSize = Math.max(zoomSize, Math.min(width, height) / 7);\r
+      mZoomR.set(left + width - zoomSize * 3, top + height - zoomSize * 0.775f, left + width, top\r
+          + height);\r
+      canvas.drawRoundRect(mZoomR, zoomSize / 3, zoomSize / 3, mPaint);\r
+      float buttonY = top + height - zoomSize * 0.625f;\r
+      canvas.drawBitmap(zoomInImage, left + width - zoomSize * 2.75f, buttonY, null);\r
+      canvas.drawBitmap(zoomOutImage, left + width - zoomSize * 1.75f, buttonY, null);\r
+      canvas.drawBitmap(fitZoomImage, left + width - zoomSize * 0.75f, buttonY, null);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Sets the zoom rate.\r
+   * \r
+   * @param rate the zoom rate\r
+   */\r
+  public void setZoomRate(float rate) {\r
+    if (mZoomIn != null && mZoomOut != null) {\r
+      mZoomIn.setZoomRate(rate);\r
+      mZoomOut.setZoomRate(rate);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Do a chart zoom in.\r
+   */\r
+  public void zoomIn() {\r
+    if (mZoomIn != null) {\r
+      mZoomIn.apply(Zoom.ZOOM_AXIS_XY);\r
+      repaint();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Do a chart zoom out.\r
+   */\r
+  public void zoomOut() {\r
+    if (mZoomOut != null) {\r
+      mZoomOut.apply(Zoom.ZOOM_AXIS_XY);\r
+      repaint();\r
+    }\r
+  }\r
+  \r
+\r
+\r
+  /**\r
+   * Do a chart zoom reset / fit zoom.\r
+   */\r
+  public void zoomReset() {\r
+    if (mFitZoom != null) {\r
+      mFitZoom.apply();\r
+      mZoomIn.notifyZoomResetListeners();\r
+      repaint();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Adds a new zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public void addZoomListener(ZoomListener listener, boolean onButtons, boolean onPinch) {\r
+    if (onButtons) {\r
+      if (mZoomIn != null) {\r
+        mZoomIn.addZoomListener(listener);\r
+        mZoomOut.addZoomListener(listener);\r
+      }\r
+      if (onPinch) {\r
+        mTouchHandler.addZoomListener(listener);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes a zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public synchronized void removeZoomListener(ZoomListener listener) {\r
+    if (mZoomIn != null) {\r
+      mZoomIn.removeZoomListener(listener);\r
+      mZoomOut.removeZoomListener(listener);\r
+    }\r
+    mTouchHandler.removeZoomListener(listener);\r
+  }\r
+\r
+  /**\r
+   * Adds a new pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void addPanListener(PanListener listener) {\r
+    mTouchHandler.addPanListener(listener);\r
+  }\r
+\r
+  /**\r
+   * Removes a pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void removePanListener(PanListener listener) {\r
+    mTouchHandler.removePanListener(listener);\r
+  }\r
+\r
+  protected RectF getZoomRectangle() {\r
+    return mZoomR;\r
+  }\r
+\r
+  @Override\r
+  public boolean onTouchEvent(MotionEvent event) {\r
+    if (event.getAction() == MotionEvent.ACTION_DOWN) {\r
+      // save the x and y so they can be used in the click and long press\r
+      // listeners\r
+      oldX = event.getX();\r
+      oldY = event.getY();\r
+    }\r
+    if (mRenderer != null && (mRenderer.isPanEnabled() || mRenderer.isZoomEnabled())) {\r
+      if (mTouchHandler.handleTouch(event)) {\r
+        return true;\r
+      }\r
+    }\r
+    return super.onTouchEvent(event);\r
+  }\r
+\r
+  /**\r
+   * Schedule a view content repaint.\r
+   */\r
+  public void repaint() {\r
+    mHandler.post(new Runnable() {\r
+      public void run() {\r
+        invalidate();\r
+      }\r
+    });\r
+  }\r
+\r
+  /**\r
+   * Schedule a view content repaint, in the specified rectangle area.\r
+   * \r
+   * @param left the left position of the area to be repainted\r
+   * @param top the top position of the area to be repainted\r
+   * @param right the right position of the area to be repainted\r
+   * @param bottom the bottom position of the area to be repainted\r
+   */\r
+  public void repaint(final int left, final int top, final int right, final int bottom) {\r
+    mHandler.post(new Runnable() {\r
+      public void run() {\r
+        invalidate(left, top, right, bottom);\r
+      }\r
+    });\r
+  }\r
+\r
+  /**\r
+   * Saves the content of the graphical view to a bitmap.\r
+   * \r
+   * @return the bitmap\r
+   */\r
+  public Bitmap toBitmap() {\r
+    setDrawingCacheEnabled(false);\r
+    if (!isDrawingCacheEnabled()) {\r
+      setDrawingCacheEnabled(true);\r
+    }\r
+    if (mRenderer.isApplyBackgroundColor()) {\r
+      setDrawingCacheBackgroundColor(mRenderer.getBackgroundColor());\r
+    }\r
+    setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);\r
+    return getDrawingCache(true);\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/ITouchHandler.java b/android-libraries/achartengine/src/org/achartengine/ITouchHandler.java
new file mode 100644 (file)
index 0000000..4debe96
--- /dev/null
@@ -0,0 +1,63 @@
+/**\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;\r
+\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.view.MotionEvent;\r
+\r
+/**\r
+ * The interface to be implemented by the touch handlers.\r
+ */\r
+public interface ITouchHandler {\r
+  /**\r
+   * Handles the touch event.\r
+   * \r
+   * @param event the touch event\r
+   * @return true if the event was handled\r
+   */\r
+  boolean handleTouch(MotionEvent event);\r
+  \r
+  /**\r
+   * Adds a new zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  void addZoomListener(ZoomListener listener);\r
+\r
+  /**\r
+   * Removes a zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  void removeZoomListener(ZoomListener listener);\r
+  \r
+  /**\r
+   * Adds a new pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  void addPanListener(PanListener listener);\r
+\r
+  /**\r
+   * Removes a pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  void removePanListener(PanListener listener);\r
+\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/TouchHandler.java b/android-libraries/achartengine/src/org/achartengine/TouchHandler.java
new file mode 100644 (file)
index 0000000..a06d05d
--- /dev/null
@@ -0,0 +1,204 @@
+/**\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;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.tools.Pan;\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.Zoom;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.graphics.RectF;\r
+import android.view.MotionEvent;\r
+\r
+/**\r
+ * The main handler of the touch events.\r
+ */\r
+public class TouchHandler implements ITouchHandler {\r
+  /** The chart renderer. */\r
+  private DefaultRenderer mRenderer;\r
+  /** The old x coordinate. */\r
+  private float oldX;\r
+  /** The old y coordinate. */\r
+  private float oldY;\r
+  /** The old x2 coordinate. */\r
+  private float oldX2;\r
+  /** The old y2 coordinate. */\r
+  private float oldY2;\r
+  /** The zoom buttons rectangle. */\r
+  private RectF zoomR = new RectF();\r
+  /** The pan tool. */\r
+  private Pan mPan;\r
+  /** The zoom for the pinch gesture. */\r
+  private Zoom mPinchZoom;\r
+  /** The graphical view. */\r
+  private GraphicalView graphicalView;\r
+\r
+  /**\r
+   * Creates a new graphical view.\r
+   * \r
+   * @param view the graphical view\r
+   * @param chart the chart to be drawn\r
+   */\r
+  public TouchHandler(GraphicalView view, AbstractChart chart) {\r
+    graphicalView = view;\r
+    zoomR = graphicalView.getZoomRectangle();\r
+    if (chart instanceof XYChart) {\r
+      mRenderer = ((XYChart) chart).getRenderer();\r
+    } else {\r
+      mRenderer = ((RoundChart) chart).getRenderer();\r
+    }\r
+    if (mRenderer.isPanEnabled()) {\r
+      mPan = new Pan(chart);\r
+    }\r
+    if (mRenderer.isZoomEnabled()) {\r
+      mPinchZoom = new Zoom(chart, true, 1);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Handles the touch event.\r
+   * \r
+   * @param event the touch event\r
+   */\r
+  public boolean handleTouch(MotionEvent event) {\r
+    int action = event.getAction();\r
+    if (mRenderer != null && action == MotionEvent.ACTION_MOVE) {\r
+      if (oldX >= 0 || oldY >= 0) {\r
+        float newX = event.getX(0);\r
+        float newY = event.getY(0);\r
+        if (event.getPointerCount() > 1 && (oldX2 >= 0 || oldY2 >= 0) && mRenderer.isZoomEnabled()) {\r
+          float newX2 = event.getX(1);\r
+          float newY2 = event.getY(1);\r
+          float newDeltaX = Math.abs(newX - newX2);\r
+          float newDeltaY = Math.abs(newY - newY2);\r
+          float oldDeltaX = Math.abs(oldX - oldX2);\r
+          float oldDeltaY = Math.abs(oldY - oldY2);\r
+          float zoomRate = 1;\r
+\r
+          float tan1 = Math.abs(newY - oldY) / Math.abs(newX - oldX);\r
+          float tan2 = Math.abs(newY2 - oldY2) / Math.abs(newX2 - oldX2);\r
+          if ( tan1 <= 0.577 && tan2 <= 0.577) {\r
+            // horizontal pinch zoom, |deltaY| / |deltaX| is [0 ~ 0.577], 0.577 is the approximate value of tan(Pi/6)\r
+            zoomRate = newDeltaX / oldDeltaX;\r
+            if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+              mPinchZoom.setZoomRate(zoomRate);\r
+              mPinchZoom.apply(Zoom.ZOOM_AXIS_X);\r
+            }\r
+          } else if ( tan1 >= 1.732 && tan2 >= 1.732 ) {\r
+            // pinch zoom vertically, |deltaY| / |deltaX| is [1.732 ~ infinity], 1.732 is the approximate value of tan(Pi/3)\r
+            zoomRate = newDeltaY / oldDeltaY;\r
+            if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+              mPinchZoom.setZoomRate(zoomRate);\r
+              mPinchZoom.apply(Zoom.ZOOM_AXIS_Y);\r
+            }\r
+          } else if ( (tan1 > 0.577 && tan1 < 1.732) && (tan2 > 0.577 && tan2 < 1.732) ){\r
+            // pinch zoom diagonally\r
+            if (Math.abs(newX - oldX) >= Math.abs(newY - oldY)) {\r
+              zoomRate = newDeltaX / oldDeltaX;\r
+            } else {\r
+              zoomRate = newDeltaY / oldDeltaY;\r
+            }\r
+            if (zoomRate > 0.909 && zoomRate < 1.1) {\r
+              mPinchZoom.setZoomRate(zoomRate);\r
+              mPinchZoom.apply(Zoom.ZOOM_AXIS_XY);\r
+            }\r
+          }\r
+          oldX2 = newX2;\r
+          oldY2 = newY2;\r
+        } else if (mRenderer.isPanEnabled()) {\r
+          mPan.apply(oldX, oldY, newX, newY);\r
+          oldX2 = 0;\r
+          oldY2 = 0;\r
+        }\r
+        oldX = newX;\r
+        oldY = newY;\r
+        graphicalView.repaint();\r
+        return true;\r
+      }\r
+    } else if (action == MotionEvent.ACTION_DOWN) {\r
+      oldX = event.getX(0);\r
+      oldY = event.getY(0);\r
+      if (mRenderer != null && mRenderer.isZoomEnabled() && zoomR.contains(oldX, oldY)) {\r
+        if (oldX < zoomR.left + zoomR.width() / 3) {\r
+          graphicalView.zoomIn();\r
+        } else if (oldX < zoomR.left + zoomR.width() * 2 / 3) {\r
+          graphicalView.zoomOut();\r
+        } else {\r
+          graphicalView.zoomReset();\r
+        }\r
+        return true;\r
+      }\r
+    } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP) {\r
+      oldX = 0;\r
+      oldY = 0;\r
+      oldX2 = 0;\r
+      oldY2 = 0;\r
+      if (action == MotionEvent.ACTION_POINTER_UP) {\r
+        oldX = -1;\r
+        oldY = -1;\r
+      }\r
+    }\r
+    return !mRenderer.isClickEnabled();\r
+  }\r
+\r
+  /**\r
+   * Adds a new zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public void addZoomListener(ZoomListener listener) {\r
+    if (mPinchZoom != null) {\r
+      mPinchZoom.addZoomListener(listener);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes a zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public void removeZoomListener(ZoomListener listener) {\r
+    if (mPinchZoom != null) {\r
+      mPinchZoom.removeZoomListener(listener);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Adds a new pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void addPanListener(PanListener listener) {\r
+    if (mPan != null) {\r
+      mPan.addPanListener(listener);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes a pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void removePanListener(PanListener listener) {\r
+    if (mPan != null) {\r
+      mPan.removePanListener(listener);\r
+    }\r
+  }\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/TouchHandlerOld.java b/android-libraries/achartengine/src/org/achartengine/TouchHandlerOld.java
new file mode 100644 (file)
index 0000000..38b4f22
--- /dev/null
@@ -0,0 +1,137 @@
+/**\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;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.tools.Pan;\r
+import org.achartengine.tools.PanListener;\r
+import org.achartengine.tools.ZoomListener;\r
+\r
+import android.graphics.RectF;\r
+import android.view.MotionEvent;\r
+\r
+/**\r
+ * A handler implementation for touch events for older platforms.\r
+ */\r
+public class TouchHandlerOld implements ITouchHandler {\r
+  /** The chart renderer. */\r
+  private DefaultRenderer mRenderer;\r
+  /** The old x coordinate. */\r
+  private float oldX;\r
+  /** The old y coordinate. */\r
+  private float oldY;\r
+  /** The zoom buttons rectangle. */\r
+  private RectF zoomR = new RectF();\r
+  /** The pan tool. */\r
+  private Pan mPan;\r
+  /** The graphical view. */\r
+  private GraphicalView graphicalView;\r
+\r
+  /**\r
+   * Creates an implementation of the old version of the touch handler.\r
+   * \r
+   * @param view the graphical view\r
+   * @param chart the chart to be drawn\r
+   */\r
+  public TouchHandlerOld(GraphicalView view, AbstractChart chart) {\r
+    graphicalView = view;\r
+    zoomR = graphicalView.getZoomRectangle();\r
+    if (chart instanceof XYChart) {\r
+      mRenderer = ((XYChart) chart).getRenderer();\r
+    } else {\r
+      mRenderer = ((RoundChart) chart).getRenderer();\r
+    }\r
+    if (mRenderer.isPanEnabled()) {\r
+      mPan = new Pan(chart);\r
+    }\r
+  }\r
+\r
+  public boolean handleTouch(MotionEvent event) {\r
+    int action = event.getAction();\r
+    if (mRenderer != null && action == MotionEvent.ACTION_MOVE) {\r
+      if (oldX >= 0 || oldY >= 0) {\r
+        float newX = event.getX();\r
+        float newY = event.getY();\r
+        if (mRenderer.isPanEnabled()) {\r
+          mPan.apply(oldX, oldY, newX, newY);\r
+        }\r
+        oldX = newX;\r
+        oldY = newY;\r
+        graphicalView.repaint();\r
+        return true;\r
+      }\r
+    } else if (action == MotionEvent.ACTION_DOWN) {\r
+      oldX = event.getX();\r
+      oldY = event.getY();\r
+      if (mRenderer != null && mRenderer.isZoomEnabled() && zoomR.contains(oldX, oldY)) {\r
+        if (oldX < zoomR.left + zoomR.width() / 3) {\r
+          graphicalView.zoomIn();\r
+        } else if (oldX < zoomR.left + zoomR.width() * 2 / 3) {\r
+          graphicalView.zoomOut();\r
+        } else {\r
+          graphicalView.zoomReset();\r
+        }\r
+        return true;\r
+      }\r
+    } else if (action == MotionEvent.ACTION_UP) {\r
+      oldX = 0;\r
+      oldY = 0;\r
+    }\r
+    return !mRenderer.isClickEnabled();\r
+  }\r
+\r
+  /**\r
+   * Adds a new zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public void addZoomListener(ZoomListener listener) {\r
+  }\r
+\r
+  /**\r
+   * Removes a zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public void removeZoomListener(ZoomListener listener) {\r
+  }\r
+\r
+  /**\r
+   * Adds a new pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void addPanListener(PanListener listener) {\r
+    if (mPan != null) {\r
+      mPan.addPanListener(listener);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes a pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public void removePanListener(PanListener listener) {\r
+    if (mPan != null) {\r
+      mPan.removePanListener(listener);\r
+    }\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/AbstractChart.java b/android-libraries/achartengine/src/org/achartengine/chart/AbstractChart.java
new file mode 100644 (file)
index 0000000..f99a5c2
--- /dev/null
@@ -0,0 +1,475 @@
+/**\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 java.io.Serializable;\r
+import java.util.List;\r
+\r
+import org.achartengine.model.Point;\r
+import org.achartengine.model.SeriesSelection;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Color;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.Path;\r
+import android.graphics.Rect;\r
+import android.graphics.RectF;\r
+\r
+/**\r
+ * An abstract class to be implemented by the chart rendering classes.\r
+ */\r
+public abstract class AbstractChart implements Serializable {\r
+  /**\r
+   * The graphical representation of the chart.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  public abstract void draw(Canvas canvas, int x, int y, int width, int height, Paint paint);\r
+\r
+  /**\r
+   * Draws the chart background.\r
+   * \r
+   * @param renderer the chart renderer\r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint used for drawing\r
+   * @param newColor if a new color is to be used\r
+   * @param color the color to be used\r
+   */\r
+  protected void drawBackground(DefaultRenderer renderer, Canvas canvas, int x, int y, int width,\r
+      int height, Paint paint, boolean newColor, int color) {\r
+    if (renderer.isApplyBackgroundColor() || newColor) {\r
+      if (newColor) {\r
+        paint.setColor(color);\r
+      } else {\r
+        paint.setColor(renderer.getBackgroundColor());\r
+      }\r
+      paint.setStyle(Style.FILL);\r
+      canvas.drawRect(x, y, x + width, y + height, paint);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Draws the chart legend.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param renderer the series renderer\r
+   * @param titles the titles to go to the legend\r
+   * @param left the left X value of the area to draw to\r
+   * @param right the right X value of the area to draw to\r
+   * @param y the y value of the area to draw to\r
+   * @param width the width of the area to draw to\r
+   * @param height the height of the area to draw to\r
+   * @param legendSize the legend size\r
+   * @param paint the paint to be used for drawing\r
+   * @param calculate if only calculating the legend size\r
+   * \r
+   * @return the legend height\r
+   */\r
+  protected int drawLegend(Canvas canvas, DefaultRenderer renderer, String[] titles, int left,\r
+      int right, int y, int width, int height, int legendSize, Paint paint, boolean calculate) {\r
+    float size = 32;\r
+    if (renderer.isShowLegend()) {\r
+      float currentX = left;\r
+      float currentY = y + height - legendSize + size;\r
+      paint.setTextAlign(Align.LEFT);\r
+      paint.setTextSize(renderer.getLegendTextSize());\r
+      int sLength = Math.min(titles.length, renderer.getSeriesRendererCount());\r
+      for (int i = 0; i < sLength; i++) {\r
+        final float lineSize = getLegendShapeWidth(i);\r
+        String text = titles[i];\r
+        if (titles.length == renderer.getSeriesRendererCount()) {\r
+          paint.setColor(renderer.getSeriesRendererAt(i).getColor());\r
+        } else {\r
+          paint.setColor(Color.LTGRAY);\r
+        }\r
+        float[] widths = new float[text.length()];\r
+        paint.getTextWidths(text, widths);\r
+        float sum = 0;\r
+        for (float value : widths) {\r
+          sum += value;\r
+        }\r
+        float extraSize = lineSize + 10 + sum;\r
+        float currentWidth = currentX + extraSize;\r
+\r
+        if (i > 0 && getExceed(currentWidth, renderer, right, width)) {\r
+          currentX = left;\r
+          currentY += renderer.getLegendTextSize();\r
+          size += renderer.getLegendTextSize();\r
+          currentWidth = currentX + extraSize;\r
+        }\r
+        if (getExceed(currentWidth, renderer, right, width)) {\r
+          float maxWidth = right - currentX - lineSize - 10;\r
+          if (isVertical(renderer)) {\r
+            maxWidth = width - currentX - lineSize - 10;\r
+          }\r
+          int nr = paint.breakText(text, true, maxWidth, widths);\r
+          text = text.substring(0, nr) + "...";\r
+        }\r
+        if (!calculate) {\r
+          drawLegendShape(canvas, renderer.getSeriesRendererAt(i), currentX, currentY, i, paint);\r
+          drawString(canvas, text, currentX + lineSize + 5, currentY + 5, paint);\r
+        }\r
+        currentX += extraSize;\r
+      }\r
+    }\r
+    return Math.round(size + renderer.getLegendTextSize());\r
+  }\r
+\r
+  /**\r
+   * Draw a multiple lines string.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param text the text to be painted\r
+   * @param x the x value of the area to draw to\r
+   * @param y the y value of the area to draw to\r
+   * @param paint the paint to be used for drawing\r
+   */\r
+  protected void drawString(Canvas canvas, String text, float x, float y, Paint paint) {\r
+    String[] lines = text.split("\n");\r
+    Rect rect = new Rect();\r
+    int yOff = 0;\r
+    for (int i = 0; i < lines.length; ++i) {\r
+      canvas.drawText(lines[i], x, y + yOff, paint);\r
+      paint.getTextBounds(lines[i], 0, lines[i].length(), rect);\r
+      yOff = yOff + rect.height() + 5; // space between lines is 5\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Calculates if the current width exceeds the total width.\r
+   * \r
+   * @param currentWidth the current width\r
+   * @param renderer the renderer\r
+   * @param right the right side pixel value\r
+   * @param width the total width\r
+   * @return if the current width exceeds the total width\r
+   */\r
+  protected boolean getExceed(float currentWidth, DefaultRenderer renderer, int right, int width) {\r
+    boolean exceed = currentWidth > right;\r
+    if (isVertical(renderer)) {\r
+      exceed = currentWidth > width;\r
+    }\r
+    return exceed;\r
+  }\r
+\r
+  /**\r
+   * Checks if the current chart is rendered as vertical.\r
+   * \r
+   * @param renderer the renderer\r
+   * @return if the chart is rendered as a vertical one\r
+   */\r
+  public boolean isVertical(DefaultRenderer renderer) {\r
+    return renderer instanceof XYMultipleSeriesRenderer\r
+        && ((XYMultipleSeriesRenderer) renderer).getOrientation() == Orientation.VERTICAL;\r
+  }\r
+  \r
+  /**\r
+   * Makes sure the fraction digit is not displayed, if not needed.\r
+   * \r
+   * @param label the input label value\r
+   * @return the label without the useless fraction digit\r
+   */\r
+  protected String getLabel(double label) {\r
+    String text = "";\r
+    if (label == Math.round(label)) {\r
+      text = Math.round(label) + "";\r
+    } else {\r
+      text = label + "";\r
+    }\r
+    return text;\r
+  }\r
+\r
+  private static float[] calculateDrawPoints(float p1x, float p1y, float p2x, float p2y,\r
+      int screenHeight, int screenWidth) {\r
+    float drawP1x;\r
+    float drawP1y;\r
+    float drawP2x;\r
+    float drawP2y;\r
+\r
+    if (p1y > screenHeight) {\r
+      // Intersection with the top of the screen\r
+      float m = (p2y - p1y) / (p2x - p1x);\r
+      drawP1x = (screenHeight - p1y + m * p1x) / m;\r
+      drawP1y = screenHeight;\r
+\r
+      if (drawP1x < 0) {\r
+        // If Intersection is left of the screen we calculate the intersection\r
+        // with the left border\r
+        drawP1x = 0;\r
+        drawP1y = p1y - m * p1x;\r
+      } else if (drawP1x > screenWidth) {\r
+        // If Intersection is right of the screen we calculate the intersection\r
+        // with the right border\r
+        drawP1x = screenWidth;\r
+        drawP1y = m * screenWidth + p1y - m * p1x;\r
+      }\r
+    } else if (p1y < 0) {\r
+      float m = (p2y - p1y) / (p2x - p1x);\r
+      drawP1x = (-p1y + m * p1x) / m;\r
+      drawP1y = 0;\r
+      if (drawP1x < 0) {\r
+        drawP1x = 0;\r
+        drawP1y = p1y - m * p1x;\r
+      } else if (drawP1x > screenWidth) {\r
+        drawP1x = screenWidth;\r
+        drawP1y = m * screenWidth + p1y - m * p1x;\r
+      }\r
+    } else {\r
+      // If the point is in the screen use it\r
+      drawP1x = p1x;\r
+      drawP1y = p1y;\r
+    }\r
+\r
+    if (p2y > screenHeight) {\r
+      float m = (p2y - p1y) / (p2x - p1x);\r
+      drawP2x = (screenHeight - p1y + m * p1x) / m;\r
+      drawP2y = screenHeight;\r
+      if (drawP2x < 0) {\r
+        drawP2x = 0;\r
+        drawP2y = p1y - m * p1x;\r
+      } else if (drawP2x > screenWidth) {\r
+        drawP2x = screenWidth;\r
+        drawP2y = m * screenWidth + p1y - m * p1x;\r
+      }\r
+    } else if (p2y < 0) {\r
+      float m = (p2y - p1y) / (p2x - p1x);\r
+      drawP2x = (-p1y + m * p1x) / m;\r
+      drawP2y = 0;\r
+      if (drawP2x < 0) {\r
+        drawP2x = 0;\r
+        drawP2y = p1y - m * p1x;\r
+      } else if (drawP2x > screenWidth) {\r
+        drawP2x = screenWidth;\r
+        drawP2y = m * screenWidth + p1y - m * p1x;\r
+      }\r
+    } else {\r
+      // If the point is in the screen use it\r
+      drawP2x = p2x;\r
+      drawP2y = p2y;\r
+    }\r
+\r
+    return new float[] { drawP1x, drawP1y, drawP2x, drawP2y };\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a path.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param points the points that are contained in the path to paint\r
+   * @param paint the paint to be used for painting\r
+   * @param circular if the path ends with the start point\r
+   */\r
+  protected void drawPath(Canvas canvas, float[] points, Paint paint, boolean circular) {\r
+    Path path = new Path();\r
+    int height = canvas.getHeight();\r
+    int width = canvas.getWidth();\r
+\r
+    float[] tempDrawPoints;\r
+    if (points.length < 4) {\r
+      return;\r
+    }\r
+    tempDrawPoints = calculateDrawPoints(points[0], points[1], points[2], points[3], height, width);\r
+    path.moveTo(tempDrawPoints[0], tempDrawPoints[1]);\r
+    path.lineTo(tempDrawPoints[2], tempDrawPoints[3]);\r
+\r
+    for (int i = 4; i < points.length; i += 2) {\r
+      if ((points[i - 1] < 0 && points[i + 1] < 0)\r
+          || (points[i - 1] > height && points[i + 1] > height)) {\r
+        continue;\r
+      }\r
+      tempDrawPoints = calculateDrawPoints(points[i - 2], points[i - 1], points[i], points[i + 1],\r
+          height, width);\r
+      if (!circular) {\r
+        path.moveTo(tempDrawPoints[0], tempDrawPoints[1]);\r
+      }\r
+      path.lineTo(tempDrawPoints[2], tempDrawPoints[3]);\r
+    }\r
+    if (circular) {\r
+      path.lineTo(points[0], points[1]);\r
+    }\r
+    canvas.drawPath(path, paint);\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 abstract int getLegendShapeWidth(int seriesIndex);\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 abstract void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer, float x,\r
+      float y, int seriesIndex, Paint paint);\r
+\r
+  /**\r
+   * Calculates the best text to fit into the available space.\r
+   * \r
+   * @param text the entire text\r
+   * @param width the width to fit the text into\r
+   * @param paint the paint\r
+   * @return the text to fit into the space\r
+   */\r
+  private String getFitText(String text, float width, Paint paint) {\r
+    String newText = text;\r
+    int length = text.length();\r
+    int diff = 0;\r
+    while (paint.measureText(newText) > width && diff < length) {\r
+      diff++;\r
+      newText = text.substring(0, length - diff) + "...";\r
+    }\r
+    if (diff == length) {\r
+      newText = "...";\r
+    }\r
+    return newText;\r
+  }\r
+\r
+  /**\r
+   * Calculates the current legend size.\r
+   * \r
+   * @param renderer the renderer\r
+   * @param defaultHeight the default height\r
+   * @param extraHeight the added extra height\r
+   * @return the legend size\r
+   */\r
+  protected int getLegendSize(DefaultRenderer renderer, int defaultHeight, float extraHeight) {\r
+    int legendSize = renderer.getLegendHeight();\r
+    if (renderer.isShowLegend() && legendSize == 0) {\r
+      legendSize = defaultHeight;\r
+    }\r
+    if (!renderer.isShowLegend() && renderer.isShowLabels()) {\r
+      legendSize = (int) (renderer.getLabelsTextSize() * 4 / 3 + extraHeight);\r
+    }\r
+    return legendSize;\r
+  }\r
+\r
+  /**\r
+   * Draws a text label.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param labelText the label text\r
+   * @param renderer the renderer\r
+   * @param prevLabelsBounds the previous rendered label bounds\r
+   * @param centerX the round chart center on X axis\r
+   * @param centerY the round chart center on Y axis\r
+   * @param shortRadius the short radius for the round chart\r
+   * @param longRadius the long radius for the round chart\r
+   * @param currentAngle the current angle\r
+   * @param angle the label extra angle\r
+   * @param left the left side\r
+   * @param right the right side\r
+   * @param color the label color\r
+   * @param paint the paint\r
+   * @param line if a line to the label should be drawn\r
+   */\r
+  protected void drawLabel(Canvas canvas, String labelText, DefaultRenderer renderer,\r
+      List<RectF> prevLabelsBounds, int centerX, int centerY, float shortRadius, float longRadius,\r
+      float currentAngle, float angle, int left, int right, int color, Paint paint, boolean line) {\r
+    if (renderer.isShowLabels()) {\r
+      paint.setColor(color);\r
+      double rAngle = Math.toRadians(90 - (currentAngle + angle / 2));\r
+      double sinValue = Math.sin(rAngle);\r
+      double cosValue = Math.cos(rAngle);\r
+      int x1 = Math.round(centerX + (float) (shortRadius * sinValue));\r
+      int y1 = Math.round(centerY + (float) (shortRadius * cosValue));\r
+      int x2 = Math.round(centerX + (float) (longRadius * sinValue));\r
+      int y2 = Math.round(centerY + (float) (longRadius * cosValue));\r
+\r
+      float size = renderer.getLabelsTextSize();\r
+      float extra = Math.max(size / 2, 10);\r
+      paint.setTextAlign(Align.LEFT);\r
+      if (x1 > x2) {\r
+        extra = -extra;\r
+        paint.setTextAlign(Align.RIGHT);\r
+      }\r
+      float xLabel = x2 + extra;\r
+      float yLabel = y2;\r
+      float width = right - xLabel;\r
+      if (x1 > x2) {\r
+        width = xLabel - left;\r
+      }\r
+      labelText = getFitText(labelText, width, paint);\r
+      float widthLabel = paint.measureText(labelText);\r
+      boolean okBounds = false;\r
+      while (!okBounds && line) {\r
+        boolean intersects = false;\r
+        int length = prevLabelsBounds.size();\r
+        for (int j = 0; j < length && !intersects; j++) {\r
+          RectF prevLabelBounds = prevLabelsBounds.get(j);\r
+          if (prevLabelBounds.intersects(xLabel, yLabel, xLabel + widthLabel, yLabel + size)) {\r
+            intersects = true;\r
+            yLabel = Math.max(yLabel, prevLabelBounds.bottom);\r
+          }\r
+        }\r
+        okBounds = !intersects;\r
+      }\r
+\r
+      if (line) {\r
+        y2 = (int) (yLabel - size / 2);\r
+        canvas.drawLine(x1, y1, x2, y2, paint);\r
+        canvas.drawLine(x2, y2, x2 + extra, y2, paint);\r
+      } else {\r
+        paint.setTextAlign(Align.CENTER);\r
+      }\r
+      canvas.drawText(labelText, xLabel, yLabel, paint);\r
+      if (line) {\r
+        prevLabelsBounds.add(new RectF(xLabel, yLabel, xLabel + widthLabel, yLabel + size));\r
+      }\r
+    }\r
+  }\r
+\r
+  public boolean isNullValue(double value) {\r
+    return Double.isNaN(value) || Double.isInfinite(value) || value == MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Given screen coordinates, returns the series and point indexes of a chart\r
+   * element. If there is no chart element (line, point, bar, etc) at those\r
+   * coordinates, null is returned.\r
+   * \r
+   * @param screenPoint\r
+   * @return the series and point indexes\r
+   */\r
+  public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {\r
+    return null;\r
+  }\r
+\r
+}\r
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
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/BubbleChart.java b/android-libraries/achartengine/src/org/achartengine/chart/BubbleChart.java
new file mode 100644 (file)
index 0000000..f312571
--- /dev/null
@@ -0,0 +1,146 @@
+/**\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.XYValueSeries;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.RectF;\r
+\r
+/**\r
+ * The bubble chart rendering class.\r
+ */\r
+public class BubbleChart extends XYChart {\r
+  /** The constant to identify this chart type. */\r
+  public static final String TYPE = "Bubble";\r
+  /** The legend shape width. */\r
+  private static final int SHAPE_WIDTH = 10;\r
+  /** The minimum bubble size. */\r
+  private static final int MIN_BUBBLE_SIZE = 2;\r
+  /** The maximum bubble size. */\r
+  private static final int MAX_BUBBLE_SIZE = 20;\r
+\r
+  BubbleChart() {\r
+  }\r
+\r
+  /**\r
+   * Builds a new bubble chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   */\r
+  public BubbleChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    super(dataset, renderer);\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
+    XYSeriesRenderer renderer = (XYSeriesRenderer) seriesRenderer;\r
+    paint.setColor(renderer.getColor());\r
+    paint.setStyle(Style.FILL);\r
+    int length = points.length;\r
+    XYValueSeries series = (XYValueSeries) mDataset.getSeriesAt(seriesIndex);\r
+    double max = series.getMaxValue();\r
+    double coef = MAX_BUBBLE_SIZE / max;\r
+    for (int i = 0; i < length; i += 2) {\r
+      double size = series.getValue(startIndex + i / 2) * coef + MIN_BUBBLE_SIZE;\r
+      drawCircle(canvas, paint, points[i], points[i + 1], (float) size);\r
+    }\r
+  }\r
+\r
+  @Override\r
+  protected ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex) {\r
+    int length = points.length;\r
+    XYValueSeries series = (XYValueSeries) mDataset.getSeriesAt(seriesIndex);\r
+    double max = series.getMaxValue();\r
+    double coef = MAX_BUBBLE_SIZE / max;\r
+    ClickableArea[] ret = new ClickableArea[length / 2];\r
+    for (int i = 0; i < length; i += 2) {\r
+      double size = series.getValue(startIndex + i / 2) * coef + MIN_BUBBLE_SIZE;\r
+      ret[i / 2] = new ClickableArea(new RectF(points[i] - (float) size, points[i + 1]\r
+          - (float) size, points[i] + (float) size, points[i + 1] + (float) size), values[i],\r
+          values[i + 1]);\r
+    }\r
+    return ret;\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
+    paint.setStyle(Style.FILL);\r
+    drawCircle(canvas, paint, x + SHAPE_WIDTH, y, 3);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a circle point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\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 radius the bubble radius\r
+   */\r
+  private void drawCircle(Canvas canvas, Paint paint, float x, float y, float radius) {\r
+    canvas.drawCircle(x, y, radius, paint);\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
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/ClickableArea.java b/android-libraries/achartengine/src/org/achartengine/chart/ClickableArea.java
new file mode 100644 (file)
index 0000000..d2d306c
--- /dev/null
@@ -0,0 +1,44 @@
+/**\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 android.graphics.RectF;\r
+\r
+public class ClickableArea {\r
+  private RectF rect;\r
+  private double x;\r
+  private double y;\r
+\r
+  public ClickableArea(RectF rect, double x, double y) {\r
+    super();\r
+    this.rect = rect;\r
+    this.x = x;\r
+    this.y = y;\r
+  }\r
+\r
+  public RectF getRect() {\r
+    return rect;\r
+  }\r
+\r
+  public double getX() {\r
+    return x;\r
+  }\r
+\r
+  public double getY() {\r
+    return y;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/CombinedXYChart.java b/android-libraries/achartengine/src/org/achartengine/chart/CombinedXYChart.java
new file mode 100644 (file)
index 0000000..d684c3a
--- /dev/null
@@ -0,0 +1,177 @@
+/**\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 java.util.List;\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
+import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+\r
+/**\r
+ * The combined XY chart rendering class.\r
+ */\r
+public class CombinedXYChart extends XYChart {\r
+  /** The embedded XY charts. */\r
+  private XYChart[] mCharts;\r
+  /** The supported charts for being combined. */\r
+  private Class[] xyChartTypes = new Class[] { TimeChart.class, LineChart.class,\r
+      CubicLineChart.class, BarChart.class, BubbleChart.class, ScatterChart.class,\r
+      RangeBarChart.class, RangeStackedBarChart.class };\r
+\r
+  /**\r
+   * Builds a new combined XY chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   * @param types the XY chart types\r
+   */\r
+  public CombinedXYChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer,\r
+      String[] types) {\r
+    super(dataset, renderer);\r
+    int length = types.length;\r
+    mCharts = new XYChart[length];\r
+    for (int i = 0; i < length; i++) {\r
+      try {\r
+        mCharts[i] = getXYChart(types[i]);\r
+      } catch (Exception e) {\r
+        // ignore\r
+      }\r
+      if (mCharts[i] == null) {\r
+        throw new IllegalArgumentException("Unknown chart type " + types[i]);\r
+      } else {\r
+        XYMultipleSeriesDataset newDataset = new XYMultipleSeriesDataset();\r
+        newDataset.addSeries(dataset.getSeriesAt(i));\r
+        XYMultipleSeriesRenderer newRenderer = new XYMultipleSeriesRenderer();\r
+        // TODO: copy other parameters here\r
+        newRenderer.setBarSpacing(renderer.getBarSpacing());\r
+        newRenderer.setPointSize(renderer.getPointSize());\r
+        int scale = dataset.getSeriesAt(i).getScaleNumber();\r
+        if (renderer.isMinXSet(scale)) {\r
+          newRenderer.setXAxisMin(renderer.getXAxisMin(scale));\r
+        }\r
+        if (renderer.isMaxXSet(scale)) {\r
+          newRenderer.setXAxisMax(renderer.getXAxisMax(scale));\r
+        }\r
+        if (renderer.isMinYSet(scale)) {\r
+          newRenderer.setYAxisMin(renderer.getYAxisMin(scale));\r
+        }\r
+        if (renderer.isMaxYSet(scale)) {\r
+          newRenderer.setYAxisMax(renderer.getYAxisMax(scale));\r
+        }\r
+        newRenderer.addSeriesRenderer(renderer.getSeriesRendererAt(i));\r
+        mCharts[i].setDatasetRenderer(newDataset, newRenderer);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns a chart instance based on the provided type.\r
+   * \r
+   * @param type the chart type\r
+   * @return an instance of a chart implementation\r
+   * @throws IllegalAccessException\r
+   * @throws InstantiationException\r
+   */\r
+  private XYChart getXYChart(String type) throws IllegalAccessException, InstantiationException {\r
+    XYChart chart = null;\r
+    int length = xyChartTypes.length;\r
+    for (int i = 0; i < length && chart == null; i++) {\r
+      XYChart newChart = (XYChart) xyChartTypes[i].newInstance();\r
+      if (type.equals(newChart.getChartType())) {\r
+        chart = newChart;\r
+      }\r
+    }\r
+    return chart;\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
+    mCharts[seriesIndex].setScreenR(getScreenR());\r
+    mCharts[seriesIndex].setCalcRange(getCalcRange(mDataset.getSeriesAt(seriesIndex)\r
+        .getScaleNumber()), 0);\r
+    mCharts[seriesIndex].drawSeries(canvas, paint, points, seriesRenderer, yAxisValue, 0,\r
+        startIndex);\r
+  }\r
+\r
+  @Override\r
+  protected ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex) {\r
+    return mCharts[seriesIndex].clickableAreasForPoints(points, values, yAxisValue, 0, startIndex);\r
+  }\r
+\r
+  @Override\r
+  protected void drawSeries(XYSeries series, Canvas canvas, Paint paint, List<Float> pointsList,\r
+      SimpleSeriesRenderer seriesRenderer, float yAxisValue, int seriesIndex, Orientation or,\r
+      int startIndex) {\r
+    mCharts[seriesIndex].setScreenR(getScreenR());\r
+    mCharts[seriesIndex].setCalcRange(getCalcRange(mDataset.getSeriesAt(seriesIndex)\r
+        .getScaleNumber()), 0);\r
+    mCharts[seriesIndex].drawSeries(series, canvas, paint, pointsList, seriesRenderer, yAxisValue,\r
+        0, or, startIndex);\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 mCharts[seriesIndex].getLegendShapeWidth(0);\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
+    mCharts[seriesIndex].drawLegendShape(canvas, renderer, x, y, 0, paint);\r
+  }\r
+\r
+  /**\r
+   * Returns the chart type identifier.\r
+   * \r
+   * @return the chart type\r
+   */\r
+  public String getChartType() {\r
+    return "Combined";\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/CubicLineChart.java b/android-libraries/achartengine/src/org/achartengine/chart/CubicLineChart.java
new file mode 100644 (file)
index 0000000..2011318
--- /dev/null
@@ -0,0 +1,120 @@
+/**\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.Point;\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Path;\r
+\r
+/**\r
+ * The interpolated (cubic) line chart rendering class.\r
+ */\r
+public class CubicLineChart extends LineChart {\r
+  /** The chart type. */\r
+  public static final String TYPE = "Cubic";\r
+\r
+  private float firstMultiplier;\r
+\r
+  private float secondMultiplier;\r
+\r
+  private Point p1 = new Point();\r
+\r
+  private Point p2 = new Point();\r
+\r
+  private Point p3 = new Point();\r
+\r
+  public CubicLineChart() {\r
+    // default is to have first control point at about 33% of the distance,\r
+    firstMultiplier = 0.33f;\r
+    // and the next at 66% of the distance.\r
+    secondMultiplier = 1 - firstMultiplier;\r
+  }\r
+\r
+  /**\r
+   * Builds a cubic line chart.\r
+   * \r
+   * @param dataset the dataset\r
+   * @param renderer the renderer\r
+   * @param smoothness smoothness determines how smooth the curve should be,\r
+   *          range [0->0.5] super smooth, 0.5, means that it might not get\r
+   *          close to control points if you have random data // less smooth,\r
+   *          (close to 0) means that it will most likely touch all control //\r
+   *          points\r
+   */\r
+  public CubicLineChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer,\r
+      float smoothness) {\r
+    super(dataset, renderer);\r
+    firstMultiplier = smoothness;\r
+    secondMultiplier = 1 - firstMultiplier;\r
+  }\r
+\r
+  @Override\r
+  protected void drawPath(Canvas canvas, float[] points, Paint paint, boolean circular) {\r
+    Path p = new Path();\r
+    float x = points[0];\r
+    float y = points[1];\r
+    p.moveTo(x, y);\r
+\r
+    int length = points.length;\r
+    if (circular) {\r
+      length -= 4;\r
+    }\r
+\r
+    for (int i = 0; i < length; i += 2) {\r
+      int nextIndex = i + 2 < length ? i + 2 : i;\r
+      int nextNextIndex = i + 4 < length ? i + 4 : nextIndex;\r
+      calc(points, p1, i, nextIndex, secondMultiplier);\r
+      p2.setX(points[nextIndex]);\r
+      p2.setY(points[nextIndex + 1]);\r
+      calc(points, p3, nextIndex, nextNextIndex, firstMultiplier);\r
+      // From last point, approaching x1/y1 and x2/y2 and ends up at x3/y3\r
+      p.cubicTo(p1.getX(), p1.getY(), p2.getX(), p2.getY(), p3.getX(), p3.getY());\r
+    }\r
+    if (circular) {\r
+      for (int i = length; i < length + 4; i += 2) {\r
+        p.lineTo(points[i], points[i + 1]);\r
+      }\r
+      p.lineTo(points[0], points[1]);\r
+    }\r
+    canvas.drawPath(p, paint);\r
+  }\r
+\r
+  private void calc(float[] points, Point result, int index1, int index2, final float multiplier) {\r
+    float p1x = points[index1];\r
+    float p1y = points[index1 + 1];\r
+    float p2x = points[index2];\r
+    float p2y = points[index2 + 1];\r
+\r
+    float diffX = p2x - p1x; // p2.x - p1.x;\r
+    float diffY = p2y - p1y; // p2.y - p1.y;\r
+    result.setX(p1x + (diffX * multiplier));\r
+    result.setY(p1y + (diffY * multiplier));\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
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/DialChart.java b/android-libraries/achartengine/src/org/achartengine/chart/DialChart.java
new file mode 100644 (file)
index 0000000..ebfcbbb
--- /dev/null
@@ -0,0 +1,236 @@
+/**\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.CategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.DialRenderer;\r
+import org.achartengine.renderer.DialRenderer.Type;\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+import android.graphics.Paint.Style;\r
+\r
+/**\r
+ * The dial chart rendering class.\r
+ */\r
+public class DialChart extends RoundChart {\r
+  /** The radius of the needle. */\r
+  private static final int NEEDLE_RADIUS = 10;\r
+  /** The series renderer. */\r
+  private DialRenderer mRenderer;\r
+\r
+  /**\r
+   * Builds a new dial chart instance.\r
+   * \r
+   * @param dataset the series dataset\r
+   * @param renderer the dial renderer\r
+   */\r
+  public DialChart(CategorySeries dataset, DialRenderer renderer) {\r
+    super(dataset, renderer);\r
+    mRenderer = renderer;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the dial chart.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  @Override\r
+  public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {\r
+    paint.setAntiAlias(mRenderer.isAntialiasing());\r
+    paint.setStyle(Style.FILL);\r
+    paint.setTextSize(mRenderer.getLabelsTextSize());\r
+    int legendSize = getLegendSize(mRenderer, height / 5, 0);\r
+    int left = x;\r
+    int top = y;\r
+    int right = x + width;\r
+\r
+    int sLength = mDataset.getItemCount();\r
+    String[] titles = new String[sLength];\r
+    for (int i = 0; i < sLength; i++) {\r
+      titles[i] = mDataset.getCategory(i);\r
+    }\r
+\r
+    if (mRenderer.isFitLegend()) {\r
+      legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,\r
+          paint, true);\r
+    }\r
+    int bottom = y + height - legendSize;\r
+    drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+\r
+    int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));\r
+    int radius = (int) (mRadius * 0.35 * mRenderer.getScale());\r
+    if (mCenterX == NO_VALUE) {\r
+      mCenterX = (left + right) / 2;\r
+    }\r
+    if (mCenterY == NO_VALUE) {\r
+      mCenterY = (bottom + top) / 2;\r
+    }\r
+    float shortRadius = radius * 0.9f;\r
+    float longRadius = radius * 1.1f;\r
+    double min = mRenderer.getMinValue();\r
+    double max = mRenderer.getMaxValue();\r
+    double angleMin = mRenderer.getAngleMin();\r
+    double angleMax = mRenderer.getAngleMax();\r
+    if (!mRenderer.isMinValueSet() || !mRenderer.isMaxValueSet()) {\r
+      int count = mRenderer.getSeriesRendererCount();\r
+      for (int i = 0; i < count; i++) {\r
+        double value = mDataset.getValue(i);\r
+        if (!mRenderer.isMinValueSet()) {\r
+          min = Math.min(min, value);\r
+        }\r
+        if (!mRenderer.isMaxValueSet()) {\r
+          max = Math.max(max, value);\r
+        }\r
+      }\r
+    }\r
+    if (min == max) {\r
+      min = min * 0.5;\r
+      max = max * 1.5;\r
+    }\r
+\r
+    paint.setColor(mRenderer.getLabelsColor());\r
+    double minorTicks = mRenderer.getMinorTicksSpacing();\r
+    double majorTicks = mRenderer.getMajorTicksSpacing();\r
+    if (minorTicks == MathHelper.NULL_VALUE) {\r
+      minorTicks = (max - min) / 30;\r
+    }\r
+    if (majorTicks == MathHelper.NULL_VALUE) {\r
+      majorTicks = (max - min) / 10;\r
+    }\r
+    drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, radius,\r
+        minorTicks, paint, false);\r
+    drawTicks(canvas, min, max, angleMin, angleMax, mCenterX, mCenterY, longRadius, shortRadius,\r
+        majorTicks, paint, true);\r
+\r
+    int count = mRenderer.getSeriesRendererCount();\r
+    for (int i = 0; i < count; i++) {\r
+      double angle = getAngleForValue(mDataset.getValue(i), angleMin, angleMax, min, max);\r
+      paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());\r
+      boolean type = mRenderer.getVisualTypeForIndex(i) == Type.ARROW;\r
+      drawNeedle(canvas, angle, mCenterX, mCenterY, shortRadius, type, paint);\r
+    }\r
+    drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);\r
+    drawTitle(canvas, x, y, width, paint);\r
+  }\r
+\r
+  /**\r
+   * Returns the angle for a specific chart value.\r
+   * \r
+   * @param value the chart value\r
+   * @param minAngle the minimum chart angle value\r
+   * @param maxAngle the maximum chart angle value\r
+   * @param min the minimum chart value\r
+   * @param max the maximum chart value\r
+   * @return the angle\r
+   */\r
+  private double getAngleForValue(double value, double minAngle, double maxAngle, double min,\r
+      double max) {\r
+    double angleDiff = maxAngle - minAngle;\r
+    double diff = max - min;\r
+    return Math.toRadians(minAngle + (value - min) * angleDiff / diff);\r
+  }\r
+\r
+  /**\r
+   * Draws the chart tick lines.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param min the minimum chart value\r
+   * @param max the maximum chart value\r
+   * @param minAngle the minimum chart angle value\r
+   * @param maxAngle the maximum chart angle value\r
+   * @param centerX the center x value\r
+   * @param centerY the center y value\r
+   * @param longRadius the long radius\r
+   * @param shortRadius the short radius\r
+   * @param ticks the tick spacing\r
+   * @param paint the paint settings\r
+   * @param labels paint the labels\r
+   * @return the angle\r
+   */\r
+  private void drawTicks(Canvas canvas, double min, double max, double minAngle, double maxAngle,\r
+      int centerX, int centerY, double longRadius, double shortRadius, double ticks, Paint paint,\r
+      boolean labels) {\r
+    for (double i = min; i <= max; i += ticks) {\r
+      double angle = getAngleForValue(i, minAngle, maxAngle, min, max);\r
+      double sinValue = Math.sin(angle);\r
+      double cosValue = Math.cos(angle);\r
+      int x1 = Math.round(centerX + (float) (shortRadius * sinValue));\r
+      int y1 = Math.round(centerY + (float) (shortRadius * cosValue));\r
+      int x2 = Math.round(centerX + (float) (longRadius * sinValue));\r
+      int y2 = Math.round(centerY + (float) (longRadius * cosValue));\r
+      canvas.drawLine(x1, y1, x2, y2, paint);\r
+      if (labels) {\r
+        paint.setTextAlign(Align.LEFT);\r
+        if (x1 <= x2) {\r
+          paint.setTextAlign(Align.RIGHT);\r
+        }\r
+        String text = i + "";\r
+        if (Math.round(i) == (long) i) {\r
+          text = (long) i + "";\r
+        }\r
+        canvas.drawText(text, x1, y1, paint);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the angle for a specific chart value.\r
+   * \r
+   * @param canvas the canvas\r
+   * @param angle the needle angle value\r
+   * @param centerX the center x value\r
+   * @param centerY the center y value\r
+   * @param radius the radius\r
+   * @param arrow if a needle or an arrow to be painted\r
+   * @param paint the paint settings\r
+   * @return the angle\r
+   */\r
+  private void drawNeedle(Canvas canvas, double angle, int centerX, int centerY, double radius,\r
+      boolean arrow, Paint paint) {\r
+    double diff = Math.toRadians(90);\r
+    int needleSinValue = (int) (NEEDLE_RADIUS * Math.sin(angle - diff));\r
+    int needleCosValue = (int) (NEEDLE_RADIUS * Math.cos(angle - diff));\r
+    int needleX = (int) (radius * Math.sin(angle));\r
+    int needleY = (int) (radius * Math.cos(angle));\r
+    int needleCenterX = centerX + needleX;\r
+    int needleCenterY = centerY + needleY;\r
+    float[] points;\r
+    if (arrow) {\r
+      int arrowBaseX = centerX + (int) (radius * 0.85 * Math.sin(angle));\r
+      int arrowBaseY = centerY + (int) (radius * 0.85 * Math.cos(angle));\r
+      points = new float[] { arrowBaseX - needleSinValue, arrowBaseY - needleCosValue,\r
+          needleCenterX, needleCenterY, arrowBaseX + needleSinValue, arrowBaseY + needleCosValue };\r
+      float width = paint.getStrokeWidth();\r
+      paint.setStrokeWidth(5);\r
+      canvas.drawLine(centerX, centerY, needleCenterX, needleCenterY, paint);\r
+      paint.setStrokeWidth(width);\r
+    } else {\r
+      points = new float[] { centerX - needleSinValue, centerY - needleCosValue, needleCenterX,\r
+          needleCenterY, centerX + needleSinValue, centerY + needleCosValue };\r
+    }\r
+    drawPath(canvas, points, paint, true);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/DoughnutChart.java b/android-libraries/achartengine/src/org/achartengine/chart/DoughnutChart.java
new file mode 100644 (file)
index 0000000..ad67b07
--- /dev/null
@@ -0,0 +1,162 @@
+/**\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 java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.achartengine.model.MultipleCategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\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
+\r
+/**\r
+ * The doughnut chart rendering class.\r
+ */\r
+public class DoughnutChart extends RoundChart {\r
+  /** The series dataset. */\r
+  private MultipleCategorySeries mDataset;\r
+  /** A step variable to control the size of the legend shape. */\r
+  private int mStep;\r
+\r
+  /**\r
+   * Builds a new doughnut chart instance.\r
+   * \r
+   * @param dataset the series dataset\r
+   * @param renderer the series renderer\r
+   */\r
+  public DoughnutChart(MultipleCategorySeries dataset, DefaultRenderer renderer) {\r
+    super(null, renderer);\r
+    mDataset = dataset;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the doughnut chart.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  @Override\r
+  public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {\r
+    paint.setAntiAlias(mRenderer.isAntialiasing());\r
+    paint.setStyle(Style.FILL);\r
+    paint.setTextSize(mRenderer.getLabelsTextSize());\r
+    int legendSize = getLegendSize(mRenderer, height / 5, 0);\r
+    int left = x;\r
+    int top = y;\r
+    int right = x + width;\r
+    int cLength = mDataset.getCategoriesCount();\r
+    String[] categories = new String[cLength];\r
+    for (int category = 0; category < cLength; category++) {\r
+      categories[category] = mDataset.getCategory(category);\r
+    }\r
+    if (mRenderer.isFitLegend()) {\r
+      legendSize = drawLegend(canvas, mRenderer, categories, left, right, y, width, height,\r
+          legendSize, paint, true);\r
+    }\r
+\r
+    int bottom = y + height - legendSize;\r
+    drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+    mStep = SHAPE_WIDTH * 3 / 4;\r
+\r
+    int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));\r
+    double rCoef = 0.35 * mRenderer.getScale();\r
+    double decCoef = 0.2 / cLength;\r
+    int radius = (int) (mRadius * rCoef);\r
+    if (mCenterX == NO_VALUE) {\r
+      mCenterX = (left + right) / 2;\r
+    }\r
+    if (mCenterY == NO_VALUE) {\r
+      mCenterY = (bottom + top) / 2;\r
+    }\r
+    float shortRadius = radius * 0.9f;\r
+    float longRadius = radius * 1.1f;\r
+    List<RectF> prevLabelsBounds = new ArrayList<RectF>();\r
+    for (int category = 0; category < cLength; category++) {\r
+      int sLength = mDataset.getItemCount(category);\r
+      double total = 0;\r
+      String[] titles = new String[sLength];\r
+      for (int i = 0; i < sLength; i++) {\r
+        total += mDataset.getValues(category)[i];\r
+        titles[i] = mDataset.getTitles(category)[i];\r
+      }\r
+      float currentAngle = mRenderer.getStartAngle();\r
+      RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY\r
+          + radius);\r
+      for (int i = 0; i < sLength; i++) {\r
+        paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());\r
+        float value = (float) mDataset.getValues(category)[i];\r
+        float angle = (float) (value / total * 360);\r
+        canvas.drawArc(oval, currentAngle, angle, true, paint);\r
+        drawLabel(canvas, mDataset.getTitles(category)[i], mRenderer, prevLabelsBounds, mCenterX,\r
+            mCenterY, shortRadius, longRadius, currentAngle, angle, left, right,\r
+            mRenderer.getLabelsColor(), paint, true);\r
+        currentAngle += angle;\r
+      }\r
+      radius -= (int) mRadius * decCoef;\r
+      shortRadius -= mRadius * decCoef - 2;\r
+      if (mRenderer.getBackgroundColor() != 0) {\r
+        paint.setColor(mRenderer.getBackgroundColor());\r
+      } else {\r
+        paint.setColor(Color.WHITE);\r
+      }\r
+      paint.setStyle(Style.FILL);\r
+      oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);\r
+      canvas.drawArc(oval, 0, 360, true, paint);\r
+      radius -= 1;\r
+    }\r
+    prevLabelsBounds.clear();\r
+    drawLegend(canvas, mRenderer, categories, left, right, y, width, height, legendSize, paint,\r
+        false);\r
+    drawTitle(canvas, x, y, width, paint);\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
+    mStep--;\r
+    canvas.drawCircle(x + SHAPE_WIDTH - mStep, y, mStep, paint);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/LineChart.java b/android-libraries/achartengine/src/org/achartengine/chart/LineChart.java
new file mode 100644 (file)
index 0000000..2c45898
--- /dev/null
@@ -0,0 +1,175 @@
+/**\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.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.RectF;\r
+\r
+/**\r
+ * The line chart rendering class.\r
+ */\r
+public class LineChart extends XYChart {\r
+  /** The constant to identify this chart type. */\r
+  public static final String TYPE = "Line";\r
+  /** The legend shape width. */\r
+  private static final int SHAPE_WIDTH = 30;\r
+  /** The scatter chart to be used to draw the data points. */\r
+  private ScatterChart pointsChart;\r
+\r
+  LineChart() {\r
+  }\r
+\r
+  /**\r
+   * Builds a new line chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   */\r
+  public LineChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    super(dataset, renderer);\r
+    pointsChart = new ScatterChart(dataset, renderer);\r
+  }\r
+\r
+  /**\r
+   * Sets the series and the renderer.\r
+   * \r
+   * @param dataset the series dataset\r
+   * @param renderer the series renderer\r
+   */\r
+  protected void setDatasetRenderer(XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    super.setDatasetRenderer(dataset, renderer);\r
+    pointsChart = new ScatterChart(dataset, renderer);\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 length = points.length;\r
+    XYSeriesRenderer renderer = (XYSeriesRenderer) seriesRenderer;\r
+    float lineWidth = paint.getStrokeWidth();\r
+    paint.setStrokeWidth(renderer.getLineWidth());\r
+    if (renderer.isFillBelowLine()) {\r
+      paint.setColor(renderer.getFillBelowLineColor());\r
+      int pLength = points.length;\r
+      float[] fillPoints = new float[pLength + 4];\r
+      System.arraycopy(points, 0, fillPoints, 0, length);\r
+      fillPoints[0] = points[0] + 1;\r
+      fillPoints[length] = fillPoints[length - 2];\r
+      fillPoints[length + 1] = yAxisValue;\r
+      fillPoints[length + 2] = fillPoints[0];\r
+      fillPoints[length + 3] = fillPoints[length + 1];\r
+      for (int i = 0; i < length + 4; i += 2) {\r
+        if (fillPoints[i + 1] < 0) {\r
+          fillPoints[i + 1] = 0;\r
+        }\r
+      }\r
+      paint.setStyle(Style.FILL);\r
+      drawPath(canvas, fillPoints, paint, true);\r
+    }\r
+    paint.setColor(seriesRenderer.getColor());\r
+    paint.setStyle(Style.STROKE);\r
+    drawPath(canvas, points, paint, false);\r
+    paint.setStrokeWidth(lineWidth);\r
+  }\r
+\r
+  @Override\r
+  protected ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex) {\r
+    int length = points.length;\r
+    ClickableArea[] ret = new ClickableArea[length / 2];\r
+    for (int i = 0; i < length; i += 2) {\r
+      int selectableBuffer = mRenderer.getSelectableBuffer();\r
+      ret[i / 2] = new ClickableArea(new RectF(points[i] - selectableBuffer, points[i + 1]\r
+          - selectableBuffer, points[i] + selectableBuffer, points[i + 1] + selectableBuffer),\r
+          values[i], values[i + 1]);\r
+    }\r
+    return ret;\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
+    canvas.drawLine(x, y, x + SHAPE_WIDTH, y, paint);\r
+    if (isRenderPoints(renderer)) {\r
+      pointsChart.drawLegendShape(canvas, renderer, x + 5, y, seriesIndex, paint);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart should display the points as a certain shape.\r
+   * \r
+   * @param renderer the series renderer\r
+   */\r
+  public boolean isRenderPoints(SimpleSeriesRenderer renderer) {\r
+    return ((XYSeriesRenderer) renderer).getPointStyle() != PointStyle.POINT;\r
+  }\r
+\r
+  /**\r
+   * Returns the scatter chart to be used for drawing the data points.\r
+   * \r
+   * @return the data points scatter chart\r
+   */\r
+  public ScatterChart getPointsChart() {\r
+    return pointsChart;\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
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/PieChart.java b/android-libraries/achartengine/src/org/achartengine/chart/PieChart.java
new file mode 100644 (file)
index 0000000..d656a95
--- /dev/null
@@ -0,0 +1,136 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.chart;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.achartengine.model.CategorySeries;
+import org.achartengine.model.Point;
+import org.achartengine.model.SeriesSelection;
+import org.achartengine.renderer.DefaultRenderer;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.RectF;
+
+/**
+ * The pie chart rendering class.
+ */
+public class PieChart extends RoundChart {
+  /** Handles returning values when tapping on PieChart. */
+  private PieMapper mPieMapper;
+
+  /**
+   * Builds a new pie chart instance.
+   * 
+   * @param dataset the series dataset
+   * @param renderer the series renderer
+   */
+  public PieChart(CategorySeries dataset, DefaultRenderer renderer) {
+    super(dataset, renderer);
+    mPieMapper = new PieMapper();
+  }
+
+  /**
+   * The graphical representation of the pie chart.
+   * 
+   * @param canvas the canvas to paint to
+   * @param x the top left x value of the view to draw to
+   * @param y the top left y value of the view to draw to
+   * @param width the width of the view to draw to
+   * @param height the height of the view to draw to
+   * @param paint the paint
+   */
+  @Override
+  public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {
+    paint.setAntiAlias(mRenderer.isAntialiasing());
+    paint.setStyle(Style.FILL);
+    paint.setTextSize(mRenderer.getLabelsTextSize());
+    int legendSize = getLegendSize(mRenderer, height / 5, 0);
+    int left = x;
+    int top = y;
+    int right = x + width;
+    int sLength = mDataset.getItemCount();
+    double total = 0;
+    String[] titles = new String[sLength];
+    for (int i = 0; i < sLength; i++) {
+      total += mDataset.getValue(i);
+      titles[i] = mDataset.getCategory(i);
+    }
+    if (mRenderer.isFitLegend()) {
+      legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,
+          paint, true);
+    }
+    int bottom = y + height - legendSize;
+    drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);
+
+    float currentAngle = mRenderer.getStartAngle();
+    int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
+    int radius = (int) (mRadius * 0.35 * mRenderer.getScale());
+
+    if (mCenterX == NO_VALUE) {
+      mCenterX = (left + right) / 2;
+    }
+    if (mCenterY == NO_VALUE) {
+      mCenterY = (bottom + top) / 2;
+    }
+
+    // Hook in clip detection after center has been calculated
+    mPieMapper.setDimensions(radius, mCenterX, mCenterY);
+    boolean loadPieCfg = !mPieMapper.areAllSegmentPresent(sLength);
+    if (loadPieCfg) {
+      mPieMapper.clearPieSegments();
+    }
+
+    float shortRadius = radius * 0.9f;
+    float longRadius = radius * 1.1f;
+
+    RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY
+        + radius);
+    List<RectF> prevLabelsBounds = new ArrayList<RectF>();
+
+    for (int i = 0; i < sLength; i++) {
+      paint.setColor(mRenderer.getSeriesRendererAt(i).getColor());
+      float value = (float) mDataset.getValue(i);
+      float angle = (float) (value / total * 360);
+      canvas.drawArc(oval, currentAngle, angle, true, paint);
+      drawLabel(canvas, mDataset.getCategory(i), mRenderer, prevLabelsBounds, mCenterX, mCenterY,
+          shortRadius, longRadius, currentAngle, angle, left, right, mRenderer.getLabelsColor(),
+          paint, true);
+      if (mRenderer.isDisplayValues()) {
+        drawLabel(canvas, getLabel(mDataset.getValue(i)), mRenderer, prevLabelsBounds, mCenterX,
+            mCenterY, shortRadius / 2, longRadius / 2, currentAngle, angle, left, right,
+            mRenderer.getLabelsColor(), paint, false);
+      }
+
+      // Save details for getSeries functionality
+      if (loadPieCfg) {
+        mPieMapper.addPieSegment(i, value, currentAngle, angle);
+      }
+      currentAngle += angle;
+    }
+    prevLabelsBounds.clear();
+    drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);
+    drawTitle(canvas, x, y, width, paint);
+  }
+
+  public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {
+    return mPieMapper.getSeriesAndPointForScreenCoordinate(screenPoint);
+  }
+
+}
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/PieMapper.java b/android-libraries/achartengine/src/org/achartengine/chart/PieMapper.java
new file mode 100644 (file)
index 0000000..6e4b715
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.chart;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.achartengine.model.Point;
+import org.achartengine.model.SeriesSelection;
+
+/**
+ * PieChart Segment Selection Management.
+ */
+public class PieMapper implements Serializable {
+
+  private List<PieSegment> mPieSegmentList = new ArrayList<PieSegment>();
+
+  private int mPieChartRadius;
+
+  private int mCenterX, mCenterY;
+
+  /**
+   * Set PieChart location on screen.
+   * 
+   * @param pieRadius
+   * @param centerX
+   * @param centerY
+   */
+  public void setDimensions(int pieRadius, int centerX, int centerY) {
+    mPieChartRadius = pieRadius;
+    mCenterX = centerX;
+    mCenterY = centerY;
+  }
+
+  /**
+   * If we have all PieChart Config then there is no point in reloading it
+   * 
+   * @param datasetSize
+   * @return true if cfg for each segment is present
+   */
+  public boolean areAllSegmentPresent(int datasetSize) {
+    return mPieSegmentList.size() == datasetSize;
+  }
+  
+  /**
+   * Add configuration for a PieChart Segment
+   * 
+   * @param dataIndex
+   * @param value
+   * @param startAngle
+   * @param angle
+   */
+  public void addPieSegment(int dataIndex, float value, float startAngle, float angle) {
+    mPieSegmentList.add(new PieSegment(dataIndex, value, startAngle, angle));
+  }
+  
+  /**
+   * Clears the pie segments list.
+   */
+  public void clearPieSegments() {
+    mPieSegmentList.clear();
+  }
+
+  /**
+   * Fetches angle relative to pie chart center point where 3 O'Clock is 0 and
+   * 12 O'Clock is 270degrees
+   * 
+   * @param screenPoint
+   * @return angle in degress from 0-360.
+   */
+  public double getAngle(Point screenPoint) {
+    double dx = screenPoint.getX() - mCenterX;
+    // Minus to correct for coord re-mapping
+    double dy = -(screenPoint.getY() - mCenterY);
+
+    double inRads = Math.atan2(dy, dx);
+
+    // We need to map to coord system when 0 degree is at 3 O'clock, 270 at 12
+    // O'clock
+    if (inRads < 0)
+      inRads = Math.abs(inRads);
+    else
+      inRads = 2 * Math.PI - inRads;
+
+    return Math.toDegrees(inRads);
+  }
+
+  /**
+   * Checks if Point falls within PieChart
+   * 
+   * @param screenPoint
+   * @return true if in PieChart
+   */
+  public boolean isOnPieChart(Point screenPoint) {
+    // Using a bit of Pythagoras
+    // inside circle if (x-center_x)**2 + (y-center_y)**2 <= radius**2:
+
+    double sqValue = (Math.pow(mCenterX - screenPoint.getX(), 2) + Math.pow(
+        mCenterY - screenPoint.getY(), 2));
+
+    double radiusSquared = mPieChartRadius * mPieChartRadius;
+    boolean isOnPieChart = sqValue <= radiusSquared;
+    return isOnPieChart;
+  }
+
+  /**
+   * Fetches the SeriesSelection for the PieSegment selected.
+   * 
+   * @param screenPoint - the user tap location
+   * @return null if screen point is not in PieChart or its config if it is
+   */
+  public SeriesSelection getSeriesAndPointForScreenCoordinate(Point screenPoint) {
+    if (isOnPieChart(screenPoint)) {
+      double angleFromPieCenter = getAngle(screenPoint);
+
+      for (PieSegment pieSeg : mPieSegmentList) {
+        if (pieSeg.isInSegment(angleFromPieCenter)) {
+          return new SeriesSelection(0, pieSeg.getDataIndex(), pieSeg.getValue(),
+              pieSeg.getValue());
+        }
+      }
+    }
+    return null;
+  }
+}
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/PieSegment.java b/android-libraries/achartengine/src/org/achartengine/chart/PieSegment.java
new file mode 100644 (file)
index 0000000..0fb0a2e
--- /dev/null
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.chart;
+
+import java.io.Serializable;
+
+/**
+ * Holds An PieChart Segment
+ */
+public class PieSegment implements Serializable {
+  private float mStartAngle;
+
+  private float mEndAngle;
+
+  private int mDataIndex;
+
+  private float mValue;
+
+  public PieSegment(int dataIndex, float value, float startAngle, float angle) {
+    mStartAngle = startAngle;
+    mEndAngle = angle + startAngle;
+    mDataIndex = dataIndex;
+    mValue = value;
+  }
+
+  /**
+   * Checks if angle falls in segment.
+   * 
+   * @param angle
+   * @return true if in segment, false otherwise.
+   */
+  public boolean isInSegment(double angle) {
+    return angle >= mStartAngle && angle <= mEndAngle;
+  }
+
+  protected float getStartAngle() {
+    return mStartAngle;
+  }
+
+  protected float getEndAngle() {
+    return mEndAngle;
+  }
+
+  protected int getDataIndex() {
+    return mDataIndex;
+  }
+
+  protected float getValue() {
+    return mValue;
+  }
+
+  public String toString() {
+    return "mDataIndex=" + mDataIndex + ",mValue=" + mValue + ",mStartAngle=" + mStartAngle
+        + ",mEndAngle=" + mEndAngle;
+  }
+
+}
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/PointStyle.java b/android-libraries/achartengine/src/org/achartengine/chart/PointStyle.java
new file mode 100644 (file)
index 0000000..29a2311
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.chart;
+
+/**
+ * The chart point style enumerator.
+ */
+public enum PointStyle {
+  X("x"), CIRCLE("circle"), TRIANGLE("triangle"), SQUARE("square"), DIAMOND("diamond"), POINT(
+      "point");
+
+  /** The point shape name. */
+  private String mName;
+
+  /**
+   * The point style enum constructor.
+   * 
+   * @param name the name
+   */
+  private PointStyle(String name) {
+    mName = name;
+  }
+
+  /**
+   * Returns the point shape name.
+   * 
+   * @return the point shape name
+   */
+  public String getName() {
+    return mName;
+  }
+
+  /**
+   * Returns the point shape name.
+   * 
+   * @return the point shape name
+   */
+  public String toString() {
+    return getName();
+  }
+
+  /**
+   * Return the point shape that has the provided symbol.
+   * 
+   * @param name the point style name
+   * @return the point shape
+   */
+  public static PointStyle getPointStyleForName(String name) {
+    PointStyle pointStyle = null;
+    PointStyle[] styles = values();
+    int length = styles.length;
+    for (int i = 0; i < length && pointStyle == null; i++) {
+      if (styles[i].mName.equals(name)) {
+        pointStyle = styles[i];
+      }
+    }
+    return pointStyle;
+  }
+
+  /**
+   * Returns the point shape index based on the given name.
+   * 
+   * @return the point shape index
+   */
+  public static int getIndexForName(String name) {
+    int index = -1;
+    PointStyle[] styles = values();
+    int length = styles.length;
+    for (int i = 0; i < length && index < 0; i++) {
+      if (styles[i].mName.equals(name)) {
+        index = i;
+      }
+    }
+    return Math.max(0, index);
+  }
+
+}
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/RangeBarChart.java b/android-libraries/achartengine/src/org/achartengine/chart/RangeBarChart.java
new file mode 100644 (file)
index 0000000..105f509
--- /dev/null
@@ -0,0 +1,145 @@
+/**\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.Paint;\r
+import android.graphics.Paint.Style;\r
+\r
+/**\r
+ * The range bar chart rendering class.\r
+ */\r
+public class RangeBarChart extends BarChart {\r
+  /** The chart type. */\r
+  public static final String TYPE = "RangeBar";\r
+\r
+  RangeBarChart() {\r
+  }\r
+\r
+  RangeBarChart(Type type) {\r
+    super(type);\r
+  }\r
+\r
+  /**\r
+   * Builds a new range bar chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   * @param type the range bar chart type\r
+   */\r
+  public RangeBarChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, Type type) {\r
+    super(dataset, renderer, type);\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
+    int start = 0;\r
+    if (startIndex > 0) {\r
+      start = 2;\r
+    }\r
+    for (int i = start; i < length; i += 4) {\r
+      if (points.length > i + 3) {\r
+        float xMin = points[i];\r
+        float yMin = points[i + 1];\r
+        // xMin = xMax\r
+        float xMax = points[i + 2];\r
+        float yMax = points[i + 3];\r
+        drawBar(canvas, xMin, yMin, xMax, yMax, halfDiffX, seriesNr, seriesIndex, paint);\r
+      }\r
+    }\r
+    paint.setColor(seriesRenderer.getColor());\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
+    int start = 0;\r
+    if (startIndex > 0) {\r
+      start = 2;\r
+    }\r
+    for (int i = start; i < points.length; i += 4) {\r
+      int index = startIndex + i / 2;\r
+      float x = points[i];\r
+      if (mType == Type.DEFAULT) {\r
+        x += seriesIndex * 2 * halfDiffX - (seriesNr - 1.5f) * halfDiffX;\r
+      }\r
+\r
+      if (!isNullValue(series.getY(index + 1)) && points.length > i + 3) {\r
+        // draw the maximum value\r
+        drawText(canvas, getLabel(series.getY(index + 1)), x,\r
+            points[i + 3] - renderer.getChartValuesSpacing(), paint, 0);\r
+      }\r
+      if (!isNullValue(series.getY(index)) && points.length > i + 1) {\r
+        // draw the minimum value\r
+        drawText(canvas, getLabel(series.getY(index)), x,\r
+            points[i + 1] + renderer.getChartValuesTextSize() + renderer.getChartValuesSpacing()\r
+                - 3, paint, 0);\r
+      }\r
+    }\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 0.5f;\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
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/RangeStackedBarChart.java b/android-libraries/achartengine/src/org/achartengine/chart/RangeStackedBarChart.java
new file mode 100644 (file)
index 0000000..4da4f00
--- /dev/null
@@ -0,0 +1,29 @@
+/**\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
+public class RangeStackedBarChart extends RangeBarChart {\r
+  /** The chart type. */\r
+  public static final String TYPE = "RangeStackedBar";\r
+\r
+  RangeStackedBarChart() {\r
+    super(Type.STACKED);\r
+  }\r
+\r
+  public String getChartType() {\r
+    return TYPE;\r
+  }\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/RoundChart.java b/android-libraries/achartengine/src/org/achartengine/chart/RoundChart.java
new file mode 100644 (file)
index 0000000..1a2121d
--- /dev/null
@@ -0,0 +1,143 @@
+/**\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.CategorySeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+\r
+/**\r
+ * An abstract class to be extended by round like chart rendering classes.\r
+ */\r
+public abstract class RoundChart extends AbstractChart {\r
+  /** The legend shape width. */\r
+  protected static final int SHAPE_WIDTH = 10;\r
+  /** The series dataset. */\r
+  protected CategorySeries mDataset;\r
+  /** The series renderer. */\r
+  protected DefaultRenderer mRenderer;\r
+  /** A no value constant. */\r
+  protected static final int NO_VALUE = Integer.MAX_VALUE;\r
+  /** The chart center X axis. */\r
+  protected int mCenterX = NO_VALUE;\r
+  /** The chart center y axis. */\r
+  protected int mCenterY = NO_VALUE;\r
+\r
+  /**\r
+   * Round chart.\r
+   * \r
+   * @param dataset the series dataset\r
+   * @param renderer the series renderer\r
+   */\r
+  public RoundChart(CategorySeries dataset, DefaultRenderer renderer) {\r
+    mDataset = dataset;\r
+    mRenderer = renderer;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the round chart title.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  public void drawTitle(Canvas canvas, int x, int y, int width, Paint paint) {\r
+    if (mRenderer.isShowLabels()) {\r
+      paint.setColor(mRenderer.getLabelsColor());\r
+      paint.setTextAlign(Align.CENTER);\r
+      paint.setTextSize(mRenderer.getChartTitleTextSize());\r
+      drawString(canvas, mRenderer.getChartTitle(), x + width / 2,\r
+          y + mRenderer.getChartTitleTextSize(), paint);\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
+    canvas.drawRect(x, y - SHAPE_WIDTH / 2, x + SHAPE_WIDTH, y + SHAPE_WIDTH / 2, paint);\r
+  }\r
+\r
+  /**\r
+   * Returns the renderer.\r
+   * \r
+   * @return the renderer\r
+   */\r
+  public DefaultRenderer getRenderer() {\r
+    return mRenderer;\r
+  }\r
+\r
+  /**\r
+   * Returns the center on X axis.\r
+   * \r
+   * @return the center on X axis\r
+   */\r
+  public int getCenterX() {\r
+    return mCenterX;\r
+  }\r
+\r
+  /**\r
+   * Returns the center on Y axis.\r
+   * \r
+   * @return the center on Y axis\r
+   */\r
+  public int getCenterY() {\r
+    return mCenterY;\r
+  }\r
+\r
+  /**\r
+   * Sets a new center on X axis.\r
+   * \r
+   * @param centerX center on X axis\r
+   */\r
+  public void setCenterX(int centerX) {\r
+    mCenterX = centerX;\r
+  }\r
+\r
+  /**\r
+   * Sets a new center on Y axis.\r
+   * \r
+   * @param centerY center on Y axis\r
+   */\r
+  public void setCenterY(int centerY) {\r
+    mCenterY = centerY;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/ScatterChart.java b/android-libraries/achartengine/src/org/achartengine/chart/ScatterChart.java
new file mode 100644 (file)
index 0000000..1d3b2a1
--- /dev/null
@@ -0,0 +1,266 @@
+/**\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.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.RectF;\r
+\r
+/**\r
+ * The scatter chart rendering class.\r
+ */\r
+public class ScatterChart extends XYChart {\r
+  /** The constant to identify this chart type. */\r
+  public static final String TYPE = "Scatter";\r
+  /** The default point shape size. */\r
+  private static final float SIZE = 3;\r
+  /** The legend shape width. */\r
+  private static final int SHAPE_WIDTH = 10;\r
+  /** The point shape size. */\r
+  private float size = SIZE;\r
+\r
+  ScatterChart() {\r
+  }\r
+\r
+  /**\r
+   * Builds a new scatter chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   */\r
+  public ScatterChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    super(dataset, renderer);\r
+    size = renderer.getPointSize();\r
+  }\r
+\r
+  // TODO: javadoc\r
+  protected void setDatasetRenderer(XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    super.setDatasetRenderer(dataset, renderer);\r
+    size = renderer.getPointSize();\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
+    XYSeriesRenderer renderer = (XYSeriesRenderer) seriesRenderer;\r
+    paint.setColor(renderer.getColor());\r
+    if (renderer.isFillPoints()) {\r
+      paint.setStyle(Style.FILL);\r
+    } else {\r
+      paint.setStyle(Style.STROKE);\r
+    }\r
+    int length = points.length;\r
+    switch (renderer.getPointStyle()) {\r
+    case X:\r
+      for (int i = 0; i < length; i += 2) {\r
+        drawX(canvas, paint, points[i], points[i + 1]);\r
+      }\r
+      break;\r
+    case CIRCLE:\r
+      for (int i = 0; i < length; i += 2) {\r
+        drawCircle(canvas, paint, points[i], points[i + 1]);\r
+      }\r
+      break;\r
+    case TRIANGLE:\r
+      float[] path = new float[6];\r
+      for (int i = 0; i < length; i += 2) {\r
+        drawTriangle(canvas, paint, path, points[i], points[i + 1]);\r
+      }\r
+      break;\r
+    case SQUARE:\r
+      for (int i = 0; i < length; i += 2) {\r
+        drawSquare(canvas, paint, points[i], points[i + 1]);\r
+      }\r
+      break;\r
+    case DIAMOND:\r
+      path = new float[8];\r
+      for (int i = 0; i < length; i += 2) {\r
+        drawDiamond(canvas, paint, path, points[i], points[i + 1]);\r
+      }\r
+      break;\r
+    case POINT:\r
+      canvas.drawPoints(points, paint);\r
+      break;\r
+    }\r
+  }\r
+\r
+  @Override\r
+  protected ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex) {\r
+    int length = points.length;\r
+    ClickableArea[] ret = new ClickableArea[length / 2];\r
+    for (int i = 0; i < length; i += 2) {\r
+      int selectableBuffer = mRenderer.getSelectableBuffer();\r
+      ret[i / 2] = new ClickableArea(new RectF(points[i] - selectableBuffer, points[i + 1]\r
+          - selectableBuffer, points[i] + selectableBuffer, points[i + 1] + selectableBuffer),\r
+          values[i], values[i + 1]);\r
+    }\r
+    return ret;\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
+    if (((XYSeriesRenderer) renderer).isFillPoints()) {\r
+      paint.setStyle(Style.FILL);\r
+    } else {\r
+      paint.setStyle(Style.STROKE);\r
+    }\r
+    switch (((XYSeriesRenderer) renderer).getPointStyle()) {\r
+    case X:\r
+      drawX(canvas, paint, x + SHAPE_WIDTH, y);\r
+      break;\r
+    case CIRCLE:\r
+      drawCircle(canvas, paint, x + SHAPE_WIDTH, y);\r
+      break;\r
+    case TRIANGLE:\r
+      drawTriangle(canvas, paint, new float[6], x + SHAPE_WIDTH, y);\r
+      break;\r
+    case SQUARE:\r
+      drawSquare(canvas, paint, x + SHAPE_WIDTH, y);\r
+      break;\r
+    case DIAMOND:\r
+      drawDiamond(canvas, paint, new float[8], x + SHAPE_WIDTH, y);\r
+      break;\r
+    case POINT:\r
+      canvas.drawPoint(x + SHAPE_WIDTH, y, paint);\r
+      break;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of an X point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\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
+   */\r
+  private void drawX(Canvas canvas, Paint paint, float x, float y) {\r
+    canvas.drawLine(x - size, y - size, x + size, y + size, paint);\r
+    canvas.drawLine(x + size, y - size, x - size, y + size, paint);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a circle point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\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
+   */\r
+  private void drawCircle(Canvas canvas, Paint paint, float x, float y) {\r
+    canvas.drawCircle(x, y, size, paint);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a triangle point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param path the triangle path\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
+   */\r
+  private void drawTriangle(Canvas canvas, Paint paint, float[] path, float x, float y) {\r
+    path[0] = x;\r
+    path[1] = y - size - size / 2;\r
+    path[2] = x - size;\r
+    path[3] = y + size;\r
+    path[4] = x + size;\r
+    path[5] = path[3];\r
+    drawPath(canvas, path, paint, true);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a square point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\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
+   */\r
+  private void drawSquare(Canvas canvas, Paint paint, float x, float y) {\r
+    canvas.drawRect(x - size, y - size, x + size, y + size, paint);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a diamond point shape.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param path the diamond path\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
+   */\r
+  private void drawDiamond(Canvas canvas, Paint paint, float[] path, float x, float y) {\r
+    path[0] = x;\r
+    path[1] = y - size;\r
+    path[2] = x - size;\r
+    path[3] = y;\r
+    path[4] = x;\r
+    path[5] = y + size;\r
+    path[6] = x + size;\r
+    path[7] = y;\r
+    drawPath(canvas, path, paint, true);\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
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/TimeChart.java b/android-libraries/achartengine/src/org/achartengine/chart/TimeChart.java
new file mode 100644 (file)
index 0000000..ba201de
--- /dev/null
@@ -0,0 +1,226 @@
+/**\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 java.text.DateFormat;\r
+import java.text.SimpleDateFormat;\r
+import java.util.ArrayList;\r
+import java.util.Date;\r
+import java.util.List;\r
+\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.Paint;\r
+\r
+/**\r
+ * The time chart rendering class.\r
+ */\r
+public class TimeChart extends LineChart {\r
+  /** The constant to identify this chart type. */\r
+  public static final String TYPE = "Time";\r
+  /** The number of milliseconds in a day. */\r
+  public static final long DAY = 24 * 60 * 60 * 1000;\r
+  /** The date format pattern to be used in formatting the X axis labels. */\r
+  private String mDateFormat;\r
+  /** The starting point for labels. */\r
+  private Double mStartPoint;\r
+\r
+  TimeChart() {\r
+  }\r
+\r
+  /**\r
+   * Builds a new time chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   */\r
+  public TimeChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    super(dataset, renderer);\r
+  }\r
+\r
+  /**\r
+   * Returns the date format pattern to be used for formatting the X axis\r
+   * labels.\r
+   * \r
+   * @return the date format pattern for the X axis labels\r
+   */\r
+  public String getDateFormat() {\r
+    return mDateFormat;\r
+  }\r
+\r
+  /**\r
+   * Sets the date format pattern to be used for formatting the X axis labels.\r
+   * \r
+   * @param format the date format pattern for the X axis labels. If null, an\r
+   *          appropriate default format will be used.\r
+   */\r
+  public void setDateFormat(String format) {\r
+    mDateFormat = format;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the labels on the X axis.\r
+   * \r
+   * @param xLabels the X labels values\r
+   * @param xTextLabelLocations the X text label locations\r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param left the left value of the labels area\r
+   * @param top the top value of the labels area\r
+   * @param bottom the bottom value of the labels area\r
+   * @param xPixelsPerUnit the amount of pixels per one unit in the chart labels\r
+   * @param minX the minimum value on the X axis in the chart\r
+   * @param maxX the maximum value on the X axis in the chart\r
+   */\r
+  @Override\r
+  protected void drawXLabels(List<Double> xLabels, Double[] xTextLabelLocations, Canvas canvas,\r
+      Paint paint, int left, int top, int bottom, double xPixelsPerUnit, double minX, double maxX) {\r
+    int length = xLabels.size();\r
+    if (length > 0) {\r
+      boolean showLabels = mRenderer.isShowLabels();\r
+      boolean showGridY = mRenderer.isShowGridY();\r
+      DateFormat format = getDateFormat(xLabels.get(0), xLabels.get(length - 1));\r
+      for (int i = 0; i < length; i++) {\r
+        long label = Math.round(xLabels.get(i));\r
+        float xLabel = (float) (left + xPixelsPerUnit * (label - minX));\r
+        if (showLabels) {\r
+          paint.setColor(mRenderer.getXLabelsColor());\r
+          canvas\r
+              .drawLine(xLabel, bottom, xLabel, bottom + mRenderer.getLabelsTextSize() / 3, paint);\r
+          drawText(canvas, format.format(new Date(label)), xLabel,\r
+              bottom + mRenderer.getLabelsTextSize() * 4 / 3, paint, mRenderer.getXLabelsAngle());\r
+        }\r
+        if (showGridY) {\r
+          paint.setColor(mRenderer.getGridColor());\r
+          canvas.drawLine(xLabel, bottom, xLabel, top, paint);\r
+        }\r
+      }\r
+    }\r
+    drawXTextLabels(xTextLabelLocations, canvas, paint, true, left, top, bottom, xPixelsPerUnit,\r
+        minX, maxX);\r
+  }\r
+\r
+  /**\r
+   * Returns the date format pattern to be used, based on the date range.\r
+   * \r
+   * @param start the start date in milliseconds\r
+   * @param end the end date in milliseconds\r
+   * @return the date format\r
+   */\r
+  private DateFormat getDateFormat(double start, double end) {\r
+    if (mDateFormat != null) {\r
+      SimpleDateFormat format = null;\r
+      try {\r
+        format = new SimpleDateFormat(mDateFormat);\r
+        return format;\r
+      } catch (Exception e) {\r
+        // do nothing here\r
+      }\r
+    }\r
+    DateFormat format = SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM);\r
+    double diff = end - start;\r
+    if (diff > DAY && diff < 5 * DAY) {\r
+      format = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT);\r
+    } else if (diff < DAY) {\r
+      format = SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM);\r
+    }\r
+    return format;\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
+  protected List<Double> getXLabels(double min, double max, int count) {\r
+    final List<Double> result = new ArrayList<Double>();\r
+    if (!mRenderer.isXRoundedLabels()) {\r
+      if (mDataset.getSeriesCount() > 0) {\r
+        XYSeries series = mDataset.getSeriesAt(0);\r
+        int length = series.getItemCount();\r
+        int intervalLength = 0;\r
+        int startIndex = -1;\r
+        for (int i = 0; i < length; i++) {\r
+          double value = series.getX(i);\r
+          if (min <= value && value <= max) {\r
+            intervalLength++;\r
+            if (startIndex < 0) {\r
+              startIndex = i;\r
+            }\r
+          }\r
+        }\r
+        if (intervalLength < count) {\r
+          for (int i = startIndex; i < startIndex + intervalLength; i++) {\r
+            result.add(series.getX(i));\r
+          }\r
+        } else {\r
+          float step = (float) intervalLength / count;\r
+          int intervalCount = 0;\r
+          for (int i = 0; i < length && intervalCount < count; i++) {\r
+            double value = series.getX(Math.round(i * step));\r
+            if (min <= value && value <= max) {\r
+              result.add(value);\r
+              intervalCount++;\r
+            }\r
+          }\r
+        }\r
+        return result;\r
+      } else {\r
+        return super.getXLabels(min, max, count);\r
+      }\r
+    }\r
+    if (mStartPoint == null) {\r
+      mStartPoint = min - (min % DAY) + DAY + new Date(Math.round(min)).getTimezoneOffset() * 60\r
+          * 1000;\r
+    }\r
+    if (count > 25) {\r
+      count = 25;\r
+    }\r
+\r
+    \r
+    final double cycleMath = (max - min) / count;\r
+    if (cycleMath <= 0) {\r
+      return result;\r
+    }\r
+    double cycle = DAY;\r
+\r
+    if (cycleMath <= DAY) {\r
+      while (cycleMath < cycle / 2) {\r
+        cycle = cycle / 2;\r
+      }\r
+    } else {\r
+      while (cycleMath > cycle) {\r
+        cycle = cycle * 2;\r
+      }\r
+    }\r
+\r
+    double val = mStartPoint - Math.floor((mStartPoint - min) / cycle) * cycle;\r
+    int i = 0;\r
+    while (val < max && i++ <= count) {\r
+      result.add(val);\r
+      val += cycle;\r
+    }\r
+\r
+    return result;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/XYChart.java b/android-libraries/achartengine/src/org/achartengine/chart/XYChart.java
new file mode 100644 (file)
index 0000000..6b531d6
--- /dev/null
@@ -0,0 +1,905 @@
+/**\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 java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.HashMap;\r
+import java.util.LinkedList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
+import java.util.SortedMap;\r
+\r
+import org.achartengine.model.Point;\r
+import org.achartengine.model.SeriesSelection;\r
+import org.achartengine.model.XYMultipleSeriesDataset;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.BasicStroke;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.renderer.SimpleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Canvas;\r
+import android.graphics.DashPathEffect;\r
+import android.graphics.Paint;\r
+import android.graphics.Paint.Align;\r
+import android.graphics.Paint.Cap;\r
+import android.graphics.Paint.Join;\r
+import android.graphics.Paint.Style;\r
+import android.graphics.PathEffect;\r
+import android.graphics.Rect;\r
+import android.graphics.RectF;\r
+import android.graphics.Typeface;\r
+\r
+/**\r
+ * The XY chart rendering class.\r
+ */\r
+public abstract class XYChart extends AbstractChart {\r
+  /** The multiple series dataset. */\r
+  protected XYMultipleSeriesDataset mDataset;\r
+  /** The multiple series renderer. */\r
+  protected XYMultipleSeriesRenderer mRenderer;\r
+  /** The current scale value. */\r
+  private float mScale;\r
+  /** The current translate value. */\r
+  private float mTranslate;\r
+  /** The canvas center point. */\r
+  private Point mCenter;\r
+  /** The visible chart area, in screen coordinates. */\r
+  private Rect mScreenR;\r
+  /** The calculated range. */\r
+  private final Map<Integer, double[]> mCalcRange = new HashMap<Integer, double[]>();\r
+\r
+  /**\r
+   * The clickable areas for all points. The array index is the series index,\r
+   * and the RectF list index is the point index in that series.\r
+   */\r
+  private Map<Integer, List<ClickableArea>> clickableAreas = new HashMap<Integer, List<ClickableArea>>();\r
+\r
+  protected XYChart() {\r
+  }\r
+\r
+  /**\r
+   * Builds a new XY chart instance.\r
+   * \r
+   * @param dataset the multiple series dataset\r
+   * @param renderer the multiple series renderer\r
+   */\r
+  public XYChart(XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer) {\r
+    mDataset = dataset;\r
+    mRenderer = renderer;\r
+  }\r
+\r
+  // TODO: javadoc\r
+  protected void setDatasetRenderer(XYMultipleSeriesDataset dataset,\r
+      XYMultipleSeriesRenderer renderer) {\r
+    mDataset = dataset;\r
+    mRenderer = renderer;\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the XY chart.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param x the top left x value of the view to draw to\r
+   * @param y the top left y value of the view to draw to\r
+   * @param width the width of the view to draw to\r
+   * @param height the height of the view to draw to\r
+   * @param paint the paint\r
+   */\r
+  public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {\r
+    paint.setAntiAlias(mRenderer.isAntialiasing());\r
+    int legendSize = getLegendSize(mRenderer, height / 5, mRenderer.getAxisTitleTextSize());\r
+    int[] margins = mRenderer.getMargins();\r
+    int left = x + margins[1];\r
+    int top = y + margins[0];\r
+    int right = x + width - margins[3];\r
+    int sLength = mDataset.getSeriesCount();\r
+    String[] titles = new String[sLength];\r
+    for (int i = 0; i < sLength; i++) {\r
+      titles[i] = mDataset.getSeriesAt(i).getTitle();\r
+    }\r
+    if (mRenderer.isFitLegend() && mRenderer.isShowLegend()) {\r
+      legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize,\r
+          paint, true);\r
+    }\r
+    int bottom = y + height - margins[2] - legendSize;\r
+    if (mScreenR == null) {\r
+      mScreenR = new Rect();\r
+    }\r
+    mScreenR.set(left, top, right, bottom);\r
+    drawBackground(mRenderer, canvas, x, y, width, height, paint, false, DefaultRenderer.NO_COLOR);\r
+\r
+    if (paint.getTypeface() == null\r
+        || !paint.getTypeface().toString().equals(mRenderer.getTextTypefaceName())\r
+        || paint.getTypeface().getStyle() != mRenderer.getTextTypefaceStyle()) {\r
+      paint.setTypeface(Typeface.create(mRenderer.getTextTypefaceName(),\r
+          mRenderer.getTextTypefaceStyle()));\r
+    }\r
+    Orientation or = mRenderer.getOrientation();\r
+    if (or == Orientation.VERTICAL) {\r
+      right -= legendSize;\r
+      bottom += legendSize - 20;\r
+    }\r
+    int angle = or.getAngle();\r
+    boolean rotate = angle == 90;\r
+    mScale = (float) (height) / width;\r
+    mTranslate = Math.abs(width - height) / 2;\r
+    if (mScale < 1) {\r
+      mTranslate *= -1;\r
+    }\r
+    mCenter = new Point((x + width) / 2, (y + height) / 2);\r
+    if (rotate) {\r
+      transform(canvas, angle, false);\r
+    }\r
+\r
+    int maxScaleNumber = -Integer.MAX_VALUE;\r
+    for (int i = 0; i < sLength; i++) {\r
+      maxScaleNumber = Math.max(maxScaleNumber, mDataset.getSeriesAt(i).getScaleNumber());\r
+    }\r
+    maxScaleNumber++;\r
+    if (maxScaleNumber < 0) {\r
+      return;\r
+    }\r
+    double[] minX = new double[maxScaleNumber];\r
+    double[] maxX = new double[maxScaleNumber];\r
+    double[] minY = new double[maxScaleNumber];\r
+    double[] maxY = new double[maxScaleNumber];\r
+    boolean[] isMinXSet = new boolean[maxScaleNumber];\r
+    boolean[] isMaxXSet = new boolean[maxScaleNumber];\r
+    boolean[] isMinYSet = new boolean[maxScaleNumber];\r
+    boolean[] isMaxYSet = new boolean[maxScaleNumber];\r
+\r
+    for (int i = 0; i < maxScaleNumber; i++) {\r
+      minX[i] = mRenderer.getXAxisMin(i);\r
+      maxX[i] = mRenderer.getXAxisMax(i);\r
+      minY[i] = mRenderer.getYAxisMin(i);\r
+      maxY[i] = mRenderer.getYAxisMax(i);\r
+      isMinXSet[i] = mRenderer.isMinXSet(i);\r
+      isMaxXSet[i] = mRenderer.isMaxXSet(i);\r
+      isMinYSet[i] = mRenderer.isMinYSet(i);\r
+      isMaxYSet[i] = mRenderer.isMaxYSet(i);\r
+      if (mCalcRange.get(i) == null) {\r
+        mCalcRange.put(i, new double[4]);\r
+      }\r
+    }\r
+    double[] xPixelsPerUnit = new double[maxScaleNumber];\r
+    double[] yPixelsPerUnit = new double[maxScaleNumber];\r
+    for (int i = 0; i < sLength; i++) {\r
+      XYSeries series = mDataset.getSeriesAt(i);\r
+      int scale = series.getScaleNumber();\r
+      if (series.getItemCount() == 0) {\r
+        continue;\r
+      }\r
+      if (!isMinXSet[scale]) {\r
+        double minimumX = series.getMinX();\r
+        minX[scale] = Math.min(minX[scale], minimumX);\r
+        mCalcRange.get(scale)[0] = minX[scale];\r
+      }\r
+      if (!isMaxXSet[scale]) {\r
+        double maximumX = series.getMaxX();\r
+        maxX[scale] = Math.max(maxX[scale], maximumX);\r
+        mCalcRange.get(scale)[1] = maxX[scale];\r
+      }\r
+      if (!isMinYSet[scale]) {\r
+        double minimumY = series.getMinY();\r
+        minY[scale] = Math.min(minY[scale], (float) minimumY);\r
+        mCalcRange.get(scale)[2] = minY[scale];\r
+      }\r
+      if (!isMaxYSet[scale]) {\r
+        double maximumY = series.getMaxY();\r
+        maxY[scale] = Math.max(maxY[scale], (float) maximumY);\r
+        mCalcRange.get(scale)[3] = maxY[scale];\r
+      }\r
+    }\r
+    for (int i = 0; i < maxScaleNumber; i++) {\r
+      if (maxX[i] - minX[i] != 0) {\r
+        xPixelsPerUnit[i] = (right - left) / (maxX[i] - minX[i]);\r
+      }\r
+      if (maxY[i] - minY[i] != 0) {\r
+        yPixelsPerUnit[i] = (float) ((bottom - top) / (maxY[i] - minY[i]));\r
+      }\r
+    }\r
+\r
+    boolean hasValues = false;\r
+    // use a linked list for these reasons:\r
+    // 1) Avoid a large contiguous memory allocation\r
+    // 2) We don't need random seeking, only sequential reading/writing, so\r
+    // linked list makes sense\r
+    clickableAreas = new HashMap<Integer, List<ClickableArea>>();\r
+    for (int i = 0; i < sLength; i++) {\r
+      XYSeries series = mDataset.getSeriesAt(i);\r
+      int scale = series.getScaleNumber();\r
+      if (series.getItemCount() == 0) {\r
+        continue;\r
+      }\r
+\r
+      hasValues = true;\r
+      SimpleSeriesRenderer seriesRenderer = mRenderer.getSeriesRendererAt(i);\r
+\r
+      // int originalValuesLength = series.getItemCount();\r
+      // int valuesLength = originalValuesLength;\r
+      // int length = valuesLength * 2;\r
+\r
+      List<Float> points = new ArrayList<Float>();\r
+      List<Double> values = new ArrayList<Double>();\r
+      float yAxisValue = Math.min(bottom, (float) (bottom + yPixelsPerUnit[scale] * minY[scale]));\r
+      LinkedList<ClickableArea> clickableArea = new LinkedList<ClickableArea>();\r
+\r
+      clickableAreas.put(i, clickableArea);\r
+\r
+      SortedMap<Double, Double> range = series.getRange(minX[scale], maxX[scale], 1);\r
+      int startIndex = -1;\r
+\r
+      for (Entry<Double, Double> value : range.entrySet()) {\r
+\r
+        double xValue = value.getKey();\r
+        double yValue = value.getValue();\r
+        if (startIndex < 0) {\r
+          startIndex = series.getIndexForKey(xValue);\r
+        }\r
+\r
+        // points.add((float) (left + xPixelsPerUnit[scale]\r
+        // * (value.getKey().floatValue() - minX[scale])));\r
+        // points.add((float) (bottom - yPixelsPerUnit[scale]\r
+        // * (value.getValue().floatValue() - minY[scale])));\r
+        values.add(value.getKey());\r
+        values.add(value.getValue());\r
+\r
+        if (!isNullValue(yValue)) {\r
+          points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));\r
+          points.add((float) (bottom - yPixelsPerUnit[scale] * (yValue - minY[scale])));\r
+        } else if (isRenderNullValues()) {\r
+          points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));\r
+          points.add((float) (bottom - yPixelsPerUnit[scale] * (-minY[scale])));\r
+        } else {\r
+          if (points.size() > 0) {\r
+            drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or, startIndex);\r
+            ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(\r
+                MathHelper.getFloats(points), MathHelper.getDoubles(values), yAxisValue, i,\r
+                startIndex);\r
+            clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));\r
+            points.clear();\r
+            values.clear();\r
+          }\r
+          clickableArea.add(null);\r
+        }\r
+      }\r
+\r
+      if (points.size() > 0) {\r
+        drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or, startIndex);\r
+        ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(\r
+            MathHelper.getFloats(points), MathHelper.getDoubles(values), yAxisValue, i, startIndex);\r
+        clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));\r
+      }\r
+    }\r
+\r
+    // draw stuff over the margins such as data doesn't render on these areas\r
+    drawBackground(mRenderer, canvas, x, bottom, width, height - bottom, paint, true,\r
+        mRenderer.getMarginsColor());\r
+    drawBackground(mRenderer, canvas, x, y, width, margins[0], paint, true,\r
+        mRenderer.getMarginsColor());\r
+    if (or == Orientation.HORIZONTAL) {\r
+      drawBackground(mRenderer, canvas, x, y, left - x, height - y, paint, true,\r
+          mRenderer.getMarginsColor());\r
+      drawBackground(mRenderer, canvas, right, y, margins[3], height - y, paint, true,\r
+          mRenderer.getMarginsColor());\r
+    } else if (or == Orientation.VERTICAL) {\r
+      drawBackground(mRenderer, canvas, right, y, width - right, height - y, paint, true,\r
+          mRenderer.getMarginsColor());\r
+      drawBackground(mRenderer, canvas, x, y, left - x, height - y, paint, true,\r
+          mRenderer.getMarginsColor());\r
+    }\r
+\r
+    boolean showLabels = mRenderer.isShowLabels() && hasValues;\r
+    boolean showGridX = mRenderer.isShowGridX();\r
+    boolean showCustomTextGrid = mRenderer.isShowCustomTextGrid();\r
+    if (showLabels || showGridX) {\r
+      List<Double> xLabels = getValidLabels(getXLabels(minX[0], maxX[0], mRenderer.getXLabels()));\r
+      Map<Integer, List<Double>> allYLabels = getYLabels(minY, maxY, maxScaleNumber);\r
+\r
+      int xLabelsLeft = left;\r
+      if (showLabels) {\r
+        paint.setColor(mRenderer.getXLabelsColor());\r
+        paint.setTextSize(mRenderer.getLabelsTextSize());\r
+        paint.setTextAlign(mRenderer.getXLabelsAlign());\r
+        if (mRenderer.getXLabelsAlign() == Align.LEFT) {\r
+          xLabelsLeft += mRenderer.getLabelsTextSize() / 4;\r
+        }\r
+      }\r
+      drawXLabels(xLabels, mRenderer.getXTextLabelLocations(), canvas, paint, xLabelsLeft, top,\r
+          bottom, xPixelsPerUnit[0], minX[0], maxX[0]);\r
+      drawYLabels(allYLabels, canvas, paint, maxScaleNumber, left, right, bottom, yPixelsPerUnit,\r
+          minY);\r
+\r
+      if (showLabels) {\r
+        paint.setColor(mRenderer.getLabelsColor());\r
+        for (int i = 0; i < maxScaleNumber; i++) {\r
+          Align axisAlign = mRenderer.getYAxisAlign(i);\r
+          Double[] yTextLabelLocations = mRenderer.getYTextLabelLocations(i);\r
+          for (Double location : yTextLabelLocations) {\r
+            if (minY[i] <= location && location <= maxY[i]) {\r
+              float yLabel = (float) (bottom - yPixelsPerUnit[i]\r
+                  * (location.doubleValue() - minY[i]));\r
+              String label = mRenderer.getYTextLabel(location, i);\r
+              paint.setColor(mRenderer.getYLabelsColor(i));\r
+              paint.setTextAlign(mRenderer.getYLabelsAlign(i));\r
+              if (or == Orientation.HORIZONTAL) {\r
+                if (axisAlign == Align.LEFT) {\r
+                  canvas.drawLine(left + getLabelLinePos(axisAlign), yLabel, left, yLabel, paint);\r
+                  drawText(canvas, label, left, yLabel - 2, paint, mRenderer.getYLabelsAngle());\r
+                } else {\r
+                  canvas.drawLine(right, yLabel, right + getLabelLinePos(axisAlign), yLabel, paint);\r
+                  drawText(canvas, label, right, yLabel - 2, paint, mRenderer.getYLabelsAngle());\r
+                }\r
+                \r
+                if (showCustomTextGrid) {\r
+                  paint.setColor(mRenderer.getGridColor());\r
+                  canvas.drawLine(left, yLabel, right, yLabel, paint);\r
+                }\r
+              } else {\r
+                canvas.drawLine(right - getLabelLinePos(axisAlign), yLabel, right, yLabel, paint);\r
+                drawText(canvas, label, right + 10, yLabel - 2, paint, mRenderer.getYLabelsAngle());\r
+                if (showCustomTextGrid) {\r
+                  paint.setColor(mRenderer.getGridColor());\r
+                  canvas.drawLine(right, yLabel, left, yLabel, paint);\r
+                }\r
+              }\r
+            }\r
+          }\r
+        }\r
+      }\r
+\r
+      if (showLabels) {\r
+        paint.setColor(mRenderer.getLabelsColor());\r
+        float size = mRenderer.getAxisTitleTextSize();\r
+        paint.setTextSize(size);\r
+        paint.setTextAlign(Align.CENTER);\r
+        if (or == Orientation.HORIZONTAL) {\r
+          drawText(canvas, mRenderer.getXTitle(), x + width / 2,\r
+              bottom + mRenderer.getLabelsTextSize() * 4 / 3 + size, paint, 0);\r
+          for (int i = 0; i < maxScaleNumber; i++) {\r
+            Align axisAlign = mRenderer.getYAxisAlign(i);\r
+            if (axisAlign == Align.LEFT) {\r
+              drawText(canvas, mRenderer.getYTitle(i), x + size, y + height / 2, paint, -90);\r
+            } else {\r
+              drawText(canvas, mRenderer.getYTitle(i), x + width, y + height / 2, paint, -90);\r
+            }\r
+          }\r
+          paint.setTextSize(mRenderer.getChartTitleTextSize());\r
+          drawText(canvas, mRenderer.getChartTitle(), x + width / 2,\r
+              y + mRenderer.getChartTitleTextSize(), paint, 0);\r
+        } else if (or == Orientation.VERTICAL) {\r
+          drawText(canvas, mRenderer.getXTitle(), x + width / 2, y + height - size, paint, -90);\r
+          drawText(canvas, mRenderer.getYTitle(), right + 20, y + height / 2, paint, 0);\r
+          paint.setTextSize(mRenderer.getChartTitleTextSize());\r
+          drawText(canvas, mRenderer.getChartTitle(), x + size, top + height / 2, paint, 0);\r
+        }\r
+      }\r
+    }\r
+    if (or == Orientation.HORIZONTAL) {\r
+      drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);\r
+    } else if (or == Orientation.VERTICAL) {\r
+      transform(canvas, angle, true);\r
+      drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, false);\r
+      transform(canvas, angle, false);\r
+    }\r
+    if (mRenderer.isShowAxes()) {\r
+      paint.setColor(mRenderer.getAxesColor());\r
+      canvas.drawLine(left, bottom, right, bottom, paint);\r
+      boolean rightAxis = false;\r
+      for (int i = 0; i < maxScaleNumber && !rightAxis; i++) {\r
+        rightAxis = mRenderer.getYAxisAlign(i) == Align.RIGHT;\r
+      }\r
+      if (or == Orientation.HORIZONTAL) {\r
+        canvas.drawLine(left, top, left, bottom, paint);\r
+        if (rightAxis) {\r
+          canvas.drawLine(right, top, right, bottom, paint);\r
+        }\r
+      } else if (or == Orientation.VERTICAL) {\r
+        canvas.drawLine(right, top, right, bottom, paint);\r
+      }\r
+    }\r
+    if (rotate) {\r
+      transform(canvas, angle, true);\r
+    }\r
+  }\r
+\r
+  protected List<Double> getXLabels(double min, double max, int count) {\r
+    return MathHelper.getLabels(min, max, count);\r
+  }\r
+\r
+  protected Map<Integer, List<Double>> getYLabels(double[] minY, double[] maxY, int maxScaleNumber) {\r
+    Map<Integer, List<Double>> allYLabels = new HashMap<Integer, List<Double>>();\r
+    for (int i = 0; i < maxScaleNumber; i++) {\r
+      allYLabels.put(i,\r
+          getValidLabels(MathHelper.getLabels(minY[i], maxY[i], mRenderer.getYLabels())));\r
+    }\r
+    return allYLabels;\r
+  }\r
+\r
+  protected Rect getScreenR() {\r
+    return mScreenR;\r
+  }\r
+\r
+  protected void setScreenR(Rect screenR) {\r
+    mScreenR = screenR;\r
+  }\r
+\r
+  private List<Double> getValidLabels(List<Double> labels) {\r
+    List<Double> result = new ArrayList<Double>(labels);\r
+    for (Double label : labels) {\r
+      if (label.isNaN()) {\r
+        result.remove(label);\r
+      }\r
+    }\r
+    return result;\r
+  }\r
+\r
+  /**\r
+   * Draws the series.\r
+   * \r
+   * @param series the series\r
+   * @param canvas the canvas\r
+   * @param paint the paint object\r
+   * @param pointsList the points to be rendered\r
+   * @param seriesRenderer the series renderer\r
+   * @param yAxisValue the y axis value in pixels\r
+   * @param seriesIndex the series index\r
+   * @param or the orientation\r
+   * @param startIndex the start index of the rendering points\r
+   */\r
+  protected void drawSeries(XYSeries series, Canvas canvas, Paint paint, List<Float> pointsList,\r
+      SimpleSeriesRenderer seriesRenderer, float yAxisValue, int seriesIndex, Orientation or,\r
+      int startIndex) {\r
+    BasicStroke stroke = seriesRenderer.getStroke();\r
+    Cap cap = paint.getStrokeCap();\r
+    Join join = paint.getStrokeJoin();\r
+    float miter = paint.getStrokeMiter();\r
+    PathEffect pathEffect = paint.getPathEffect();\r
+    Style style = paint.getStyle();\r
+    if (stroke != null) {\r
+      PathEffect effect = null;\r
+      if (stroke.getIntervals() != null) {\r
+        effect = new DashPathEffect(stroke.getIntervals(), stroke.getPhase());\r
+      }\r
+      setStroke(stroke.getCap(), stroke.getJoin(), stroke.getMiter(), Style.FILL_AND_STROKE,\r
+          effect, paint);\r
+    }\r
+    float[] points = MathHelper.getFloats(pointsList);\r
+    drawSeries(canvas, paint, points, seriesRenderer, yAxisValue, seriesIndex, startIndex);\r
+    if (isRenderPoints(seriesRenderer)) {\r
+      ScatterChart pointsChart = getPointsChart();\r
+      if (pointsChart != null) {\r
+        pointsChart.drawSeries(canvas, paint, points, seriesRenderer, yAxisValue, seriesIndex,\r
+            startIndex);\r
+      }\r
+    }\r
+    paint.setTextSize(seriesRenderer.getChartValuesTextSize());\r
+    if (or == Orientation.HORIZONTAL) {\r
+      paint.setTextAlign(Align.CENTER);\r
+    } else {\r
+      paint.setTextAlign(Align.LEFT);\r
+    }\r
+    if (seriesRenderer.isDisplayChartValues()) {\r
+      paint.setTextAlign(seriesRenderer.getChartValuesTextAlign());\r
+      drawChartValuesText(canvas, series, seriesRenderer, paint, points, seriesIndex, startIndex);\r
+    }\r
+    if (stroke != null) {\r
+      setStroke(cap, join, miter, style, pathEffect, paint);\r
+    }\r
+  }\r
+\r
+  private void setStroke(Cap cap, Join join, float miter, Style style, PathEffect pathEffect,\r
+      Paint paint) {\r
+    paint.setStrokeCap(cap);\r
+    paint.setStrokeJoin(join);\r
+    paint.setStrokeMiter(miter);\r
+    paint.setPathEffect(pathEffect);\r
+    paint.setStyle(style);\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
+    if (points.length > 1) { // there are more than one point\r
+      // record the first point's position\r
+      float previousPointX = points[0];\r
+      float previousPointY = points[1];\r
+      for (int k = 0; k < points.length; k += 2) {\r
+        if (k == 2) { // decide whether to display first two points' values or not\r
+          if (Math.abs(points[2]- points[0]) > 100 || Math.abs(points[3] - points[1]) > 100) {\r
+            // first point\r
+            drawText(canvas, getLabel(series.getY(startIndex)), points[0], points[1]\r
+                - renderer.getChartValuesSpacing(), paint, 0);\r
+            // second point\r
+            drawText(canvas, getLabel(series.getY(startIndex + 1)), points[2], points[3]\r
+                - renderer.getChartValuesSpacing(), paint, 0);\r
+\r
+            previousPointX = points[2];\r
+            previousPointY = points[3];\r
+          }\r
+        } else if (k > 2) {\r
+          // compare current point's position with the previous point's, if they are not too close, display\r
+          if (Math.abs(points[k]- previousPointX) > 100 || Math.abs(points[k+1] - previousPointY) > 100) {\r
+            drawText(canvas, getLabel(series.getY(startIndex + k / 2)), points[k], points[k + 1]\r
+                - renderer.getChartValuesSpacing(), paint, 0);\r
+            previousPointX = points[k];\r
+            previousPointY = points[k+1];\r
+          }\r
+        }\r
+      }\r
+    } else { // if only one point, display it\r
+      for (int k = 0; k < points.length; k += 2) {\r
+        drawText(canvas, getLabel(series.getY(startIndex + k / 2)), points[k], points[k + 1]\r
+            - renderer.getChartValuesSpacing(), paint, 0);\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of a text, to handle both HORIZONTAL and\r
+   * VERTICAL orientations and extra rotation angles.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param text the text to be rendered\r
+   * @param x the X axis location of the text\r
+   * @param y the Y axis location of the text\r
+   * @param paint the paint to be used for drawing\r
+   * @param extraAngle the text angle\r
+   */\r
+  protected void drawText(Canvas canvas, String text, float x, float y, Paint paint,\r
+      float extraAngle) {\r
+    float angle = -mRenderer.getOrientation().getAngle() + extraAngle;\r
+    if (angle != 0) {\r
+      // canvas.scale(1 / mScale, mScale);\r
+      canvas.rotate(angle, x, y);\r
+    }\r
+    drawString(canvas, text, x, y, paint);\r
+    if (angle != 0) {\r
+      canvas.rotate(-angle, x, y);\r
+      // canvas.scale(mScale, 1 / mScale);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Transform the canvas such as it can handle both HORIZONTAL and VERTICAL\r
+   * orientations.\r
+   * \r
+   * @param canvas the canvas to paint to\r
+   * @param angle the angle of rotation\r
+   * @param inverse if the inverse transform needs to be applied\r
+   */\r
+  private void transform(Canvas canvas, float angle, boolean inverse) {\r
+    if (inverse) {\r
+      canvas.scale(1 / mScale, mScale);\r
+      canvas.translate(mTranslate, -mTranslate);\r
+      canvas.rotate(-angle, mCenter.getX(), mCenter.getY());\r
+    } else {\r
+      canvas.rotate(angle, mCenter.getX(), mCenter.getY());\r
+      canvas.translate(-mTranslate, mTranslate);\r
+      canvas.scale(mScale, 1 / mScale);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the labels on the X axis.\r
+   * \r
+   * @param xLabels the X labels values\r
+   * @param xTextLabelLocations the X text label locations\r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param left the left value of the labels area\r
+   * @param top the top value of the labels area\r
+   * @param bottom the bottom value of the labels area\r
+   * @param xPixelsPerUnit the amount of pixels per one unit in the chart labels\r
+   * @param minX the minimum value on the X axis in the chart\r
+   * @param maxX the maximum value on the X axis in the chart\r
+   */\r
+  protected void drawXLabels(List<Double> xLabels, Double[] xTextLabelLocations, Canvas canvas,\r
+      Paint paint, int left, int top, int bottom, double xPixelsPerUnit, double minX, double maxX) {\r
+    int length = xLabels.size();\r
+    boolean showLabels = mRenderer.isShowLabels();\r
+    boolean showGridY = mRenderer.isShowGridY();\r
+    for (int i = 0; i < length; i++) {\r
+      double label = xLabels.get(i);\r
+      float xLabel = (float) (left + xPixelsPerUnit * (label - minX));\r
+      if (showLabels) {\r
+        paint.setColor(mRenderer.getXLabelsColor());\r
+        canvas.drawLine(xLabel, bottom, xLabel, bottom + mRenderer.getLabelsTextSize() / 3, paint);\r
+        drawText(canvas, getLabel(label), xLabel, bottom + mRenderer.getLabelsTextSize() * 4 / 3,\r
+            paint, mRenderer.getXLabelsAngle());\r
+      }\r
+      if (showGridY) {\r
+        paint.setColor(mRenderer.getGridColor());\r
+        canvas.drawLine(xLabel, bottom, xLabel, top, paint);\r
+      }\r
+    }\r
+    drawXTextLabels(xTextLabelLocations, canvas, paint, showLabels, left, top, bottom,\r
+        xPixelsPerUnit, minX, maxX);\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the labels on the X axis.\r
+   * \r
+   * @param allYLabels the Y labels values\r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param maxScaleNumber the maximum scale number\r
+   * @param left the left value of the labels area\r
+   * @param right the right value of the labels area\r
+   * @param bottom the bottom value of the labels area\r
+   * @param yPixelsPerUnit the amount of pixels per one unit in the chart labels\r
+   * @param minY the minimum value on the Y axis in the chart\r
+   */\r
+  protected void drawYLabels(Map<Integer, List<Double>> allYLabels, Canvas canvas, Paint paint,\r
+      int maxScaleNumber, int left, int right, int bottom, double[] yPixelsPerUnit, double[] minY) {\r
+    Orientation or = mRenderer.getOrientation();\r
+    boolean showGridX = mRenderer.isShowGridX();\r
+    boolean showLabels = mRenderer.isShowLabels();\r
+    for (int i = 0; i < maxScaleNumber; i++) {\r
+      paint.setTextAlign(mRenderer.getYLabelsAlign(i));\r
+      List<Double> yLabels = allYLabels.get(i);\r
+      int length = yLabels.size();\r
+      for (int j = 0; j < length; j++) {\r
+        double label = yLabels.get(j);\r
+        Align axisAlign = mRenderer.getYAxisAlign(i);\r
+        boolean textLabel = mRenderer.getYTextLabel(label, i) != null;\r
+        float yLabel = (float) (bottom - yPixelsPerUnit[i] * (label - minY[i]));\r
+        if (or == Orientation.HORIZONTAL) {\r
+          if (showLabels && !textLabel) {\r
+            paint.setColor(mRenderer.getYLabelsColor(i));\r
+            if (axisAlign == Align.LEFT) {\r
+              canvas.drawLine(left + getLabelLinePos(axisAlign), yLabel, left, yLabel, paint);\r
+              drawText(canvas, getLabel(label), left, yLabel - 2, paint,\r
+                  mRenderer.getYLabelsAngle());\r
+            } else {\r
+              canvas.drawLine(right, yLabel, right + getLabelLinePos(axisAlign), yLabel, paint);\r
+              drawText(canvas, getLabel(label), right, yLabel - 2, paint,\r
+                  mRenderer.getYLabelsAngle());\r
+            }\r
+          }\r
+          if (showGridX) {\r
+            paint.setColor(mRenderer.getGridColor());\r
+            canvas.drawLine(left, yLabel, right, yLabel, paint);\r
+          }\r
+        } else if (or == Orientation.VERTICAL) {\r
+          if (showLabels && !textLabel) {\r
+            paint.setColor(mRenderer.getYLabelsColor(i));\r
+            canvas.drawLine(right - getLabelLinePos(axisAlign), yLabel, right, yLabel, paint);\r
+            drawText(canvas, getLabel(label), right + 10, yLabel - 2, paint,\r
+                mRenderer.getYLabelsAngle());\r
+          }\r
+          if (showGridX) {\r
+            paint.setColor(mRenderer.getGridColor());\r
+            canvas.drawLine(right, yLabel, left, yLabel, paint);\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * The graphical representation of the text labels on the X axis.\r
+   * \r
+   * @param xTextLabelLocations the X text label locations\r
+   * @param canvas the canvas to paint to\r
+   * @param paint the paint to be used for drawing\r
+   * @param left the left value of the labels area\r
+   * @param top the top value of the labels area\r
+   * @param bottom the bottom value of the labels area\r
+   * @param xPixelsPerUnit the amount of pixels per one unit in the chart labels\r
+   * @param minX the minimum value on the X axis in the chart\r
+   * @param maxX the maximum value on the X axis in the chart\r
+   */\r
+  protected void drawXTextLabels(Double[] xTextLabelLocations, Canvas canvas, Paint paint,\r
+      boolean showLabels, int left, int top, int bottom, double xPixelsPerUnit, double minX,\r
+      double maxX) {\r
+    boolean showCustomTextGrid = mRenderer.isShowCustomTextGrid();\r
+    if (showLabels) {\r
+      paint.setColor(mRenderer.getXLabelsColor());\r
+      for (Double location : xTextLabelLocations) {\r
+        if (minX <= location && location <= maxX) {\r
+          float xLabel = (float) (left + xPixelsPerUnit * (location.doubleValue() - minX));\r
+          paint.setColor(mRenderer.getXLabelsColor());\r
+          canvas\r
+          .drawLine(xLabel, bottom, xLabel, bottom + mRenderer.getLabelsTextSize() / 3, paint);\r
+          drawText(canvas, mRenderer.getXTextLabel(location), xLabel,\r
+              bottom + mRenderer.getLabelsTextSize() * 4 / 3, paint, mRenderer.getXLabelsAngle());\r
+          if (showCustomTextGrid) {\r
+            paint.setColor(mRenderer.getGridColor());\r
+            canvas.drawLine(xLabel, bottom, xLabel, top, paint);\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  // TODO: docs\r
+  public XYMultipleSeriesRenderer getRenderer() {\r
+    return mRenderer;\r
+  }\r
+\r
+  public XYMultipleSeriesDataset getDataset() {\r
+    return mDataset;\r
+  }\r
+\r
+  public double[] getCalcRange(int scale) {\r
+    return mCalcRange.get(scale);\r
+  }\r
+\r
+  public void setCalcRange(double[] range, int scale) {\r
+    mCalcRange.put(scale, range);\r
+  }\r
+\r
+  public double[] toRealPoint(float screenX, float screenY) {\r
+    return toRealPoint(screenX, screenY, 0);\r
+  }\r
+\r
+  public double[] toScreenPoint(double[] realPoint) {\r
+    return toScreenPoint(realPoint, 0);\r
+  }\r
+\r
+  private int getLabelLinePos(Align align) {\r
+    int pos = 4;\r
+    if (align == Align.LEFT) {\r
+      pos = -pos;\r
+    }\r
+    return pos;\r
+  }\r
+\r
+  /**\r
+   * Transforms a screen point to a real coordinates point.\r
+   * \r
+   * @param screenX the screen x axis value\r
+   * @param screenY the screen y axis value\r
+   * @return the real coordinates point\r
+   */\r
+  public double[] toRealPoint(float screenX, float screenY, int scale) {\r
+    double realMinX = mRenderer.getXAxisMin(scale);\r
+    double realMaxX = mRenderer.getXAxisMax(scale);\r
+    double realMinY = mRenderer.getYAxisMin(scale);\r
+    double realMaxY = mRenderer.getYAxisMax(scale);\r
+    return new double[] {\r
+        (screenX - mScreenR.left) * (realMaxX - realMinX) / mScreenR.width() + realMinX,\r
+        (mScreenR.top + mScreenR.height() - screenY) * (realMaxY - realMinY) / mScreenR.height()\r
+            + realMinY };\r
+  }\r
+\r
+  public double[] toScreenPoint(double[] realPoint, int scale) {\r
+    double realMinX = mRenderer.getXAxisMin(scale);\r
+    double realMaxX = mRenderer.getXAxisMax(scale);\r
+    double realMinY = mRenderer.getYAxisMin(scale);\r
+    double realMaxY = mRenderer.getYAxisMax(scale);\r
+    if (!mRenderer.isMinXSet(scale) || !mRenderer.isMaxXSet(scale) || !mRenderer.isMinXSet(scale)\r
+        || !mRenderer.isMaxYSet(scale)) {\r
+      double[] calcRange = getCalcRange(scale);\r
+      realMinX = calcRange[0];\r
+      realMaxX = calcRange[1];\r
+      realMinY = calcRange[2];\r
+      realMaxY = calcRange[3];\r
+    }\r
+    return new double[] {\r
+        (realPoint[0] - realMinX) * mScreenR.width() / (realMaxX - realMinX) + mScreenR.left,\r
+        (realMaxY - realPoint[1]) * mScreenR.height() / (realMaxY - realMinY) + mScreenR.top };\r
+  }\r
+\r
+  public SeriesSelection getSeriesAndPointForScreenCoordinate(final Point screenPoint) {\r
+    if (clickableAreas != null)\r
+      for (int seriesIndex = clickableAreas.size() - 1; seriesIndex >= 0; seriesIndex--) {\r
+        // series 0 is drawn first. Then series 1 is drawn on top, and series 2\r
+        // on top of that.\r
+        // we want to know what the user clicked on, so traverse them in the\r
+        // order they appear on the screen.\r
+        int pointIndex = 0;\r
+        if (clickableAreas.get(seriesIndex) != null) {\r
+          RectF rectangle;\r
+          for (ClickableArea area : clickableAreas.get(seriesIndex)) {\r
+            rectangle = area.getRect();\r
+            if (rectangle != null && rectangle.contains(screenPoint.getX(), screenPoint.getY())) {\r
+              return new SeriesSelection(seriesIndex, pointIndex, area.getX(), area.getY());\r
+            }\r
+            pointIndex++;\r
+          }\r
+        }\r
+      }\r
+    return super.getSeriesAndPointForScreenCoordinate(screenPoint);\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 abstract void drawSeries(Canvas canvas, Paint paint, float[] points,\r
+      SimpleSeriesRenderer seriesRenderer, float yAxisValue, int seriesIndex, int startIndex);\r
+\r
+  /**\r
+   * Returns the clickable areas for all passed points\r
+   * \r
+   * @param points the array of points\r
+   * @param values the array of values of each point\r
+   * @param yAxisValue the minimum value of the y axis\r
+   * @param seriesIndex the index of the series to which the points belong\r
+   * @return an array of rectangles with the clickable area\r
+   * @param startIndex the start index of the rendering points\r
+   */\r
+  protected abstract ClickableArea[] clickableAreasForPoints(float[] points, double[] values,\r
+      float yAxisValue, int seriesIndex, int startIndex);\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 false;\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart should display the points as a certain shape.\r
+   * \r
+   * @param renderer the series renderer\r
+   */\r
+  public boolean isRenderPoints(SimpleSeriesRenderer renderer) {\r
+    return false;\r
+  }\r
+\r
+  /**\r
+   * Returns the default axis minimum.\r
+   * \r
+   * @return the default axis minimum\r
+   */\r
+  public double getDefaultMinimum() {\r
+    return MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the scatter chart to be used for drawing the data points.\r
+   * \r
+   * @return the data points scatter chart\r
+   */\r
+  public ScatterChart getPointsChart() {\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart type identifier.\r
+   * \r
+   * @return the chart type\r
+   */\r
+  public abstract String getChartType();\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/chart/package.html b/android-libraries/achartengine/src/org/achartengine/chart/package.html
new file mode 100644 (file)
index 0000000..2c5fbec
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<title>AChartEngine</title>\r
+<body>\r
+Provides the classes that handle the actual rendering / drawing of the charts, based on the provided model and renderer.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/image/zoom-1.png b/android-libraries/achartengine/src/org/achartengine/image/zoom-1.png
new file mode 100644 (file)
index 0000000..8265f27
Binary files /dev/null and b/android-libraries/achartengine/src/org/achartengine/image/zoom-1.png differ
diff --git a/android-libraries/achartengine/src/org/achartengine/image/zoom_in.png b/android-libraries/achartengine/src/org/achartengine/image/zoom_in.png
new file mode 100644 (file)
index 0000000..1ac4864
Binary files /dev/null and b/android-libraries/achartengine/src/org/achartengine/image/zoom_in.png differ
diff --git a/android-libraries/achartengine/src/org/achartengine/image/zoom_out.png b/android-libraries/achartengine/src/org/achartengine/image/zoom_out.png
new file mode 100644 (file)
index 0000000..d67a87d
Binary files /dev/null and b/android-libraries/achartengine/src/org/achartengine/image/zoom_out.png differ
diff --git a/android-libraries/achartengine/src/org/achartengine/model/CategorySeries.java b/android-libraries/achartengine/src/org/achartengine/model/CategorySeries.java
new file mode 100644 (file)
index 0000000..ae31c7d
--- /dev/null
@@ -0,0 +1,143 @@
+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * A series for the category charts like the pie ones.\r
+ */\r
+public class CategorySeries implements Serializable {\r
+  /** The series title. */\r
+  private String mTitle;\r
+  /** The series categories. */\r
+  private List<String> mCategories = new ArrayList<String>();\r
+  /** The series values. */\r
+  private List<Double> mValues = new ArrayList<Double>();\r
+\r
+  /**\r
+   * Builds a new category series.\r
+   * \r
+   * @param title the series title\r
+   */\r
+  public CategorySeries(String title) {\r
+    mTitle = title;\r
+  }\r
+\r
+  /**\r
+   * Returns the series title.\r
+   * \r
+   * @return the series title\r
+   */\r
+  public String getTitle() {\r
+    return mTitle;\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series\r
+   * \r
+   * @param value the new value\r
+   */\r
+  public synchronized void add(double value) {\r
+    add(mCategories.size() + "", value);\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param category the category\r
+   * @param value the new value\r
+   */\r
+  public synchronized void add(String category, double value) {\r
+    mCategories.add(category);\r
+    mValues.add(value);\r
+  }\r
+\r
+  /**\r
+   * Replaces the value at the specific index in the series.\r
+   * \r
+   * @param index the index in the series\r
+   * @param category the category\r
+   * @param value the new value\r
+   */\r
+  public synchronized void set(int index, String category, double value) {\r
+    mCategories.set(index, category);\r
+    mValues.set(index, value);\r
+  }\r
+\r
+  /**\r
+   * Removes an existing value from the series.\r
+   * \r
+   * @param index the index in the series of the value to remove\r
+   */\r
+  public synchronized void remove(int index) {\r
+    mCategories.remove(index);\r
+    mValues.remove(index);\r
+  }\r
+\r
+  /**\r
+   * Removes all the existing values from the series.\r
+   */\r
+  public synchronized void clear() {\r
+    mCategories.clear();\r
+    mValues.clear();\r
+  }\r
+\r
+  /**\r
+   * Returns the value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the value at the index\r
+   */\r
+  public synchronized double getValue(int index) {\r
+    return mValues.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the category name at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the category name at the index\r
+   */\r
+  public synchronized String getCategory(int index) {\r
+    return mCategories.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the series item count.\r
+   * \r
+   * @return the series item count\r
+   */\r
+  public synchronized int getItemCount() {\r
+    return mCategories.size();\r
+  }\r
+\r
+  /**\r
+   * Transforms the category series to an XY series.\r
+   * \r
+   * @return the XY series\r
+   */\r
+  public XYSeries toXYSeries() {\r
+    XYSeries xySeries = new XYSeries(mTitle);\r
+    int k = 0;\r
+    for (double value : mValues) {\r
+      xySeries.add(++k, value);\r
+    }\r
+    return xySeries;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/MultipleCategorySeries.java b/android-libraries/achartengine/src/org/achartengine/model/MultipleCategorySeries.java
new file mode 100644 (file)
index 0000000..992db4c
--- /dev/null
@@ -0,0 +1,145 @@
+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * A series for the multiple category charts like the doughnut.\r
+ */\r
+public class MultipleCategorySeries implements Serializable {\r
+  /** The series title. */\r
+  private String mTitle;\r
+  /** The series local keys. */\r
+  private List<String> mCategories = new ArrayList<String>();\r
+  /** The series name. */\r
+  private List<String[]> mTitles = new ArrayList<String[]>();\r
+  /** The series values. */\r
+  private List<double[]> mValues = new ArrayList<double[]>();\r
+\r
+  /**\r
+   * Builds a new category series.\r
+   * \r
+   * @param title the series title\r
+   */\r
+  public MultipleCategorySeries(String title) {\r
+    mTitle = title;\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series\r
+   * \r
+   * @param titles the titles to be used as labels\r
+   * @param values the new value\r
+   */\r
+  public void add(String[] titles, double[] values) {\r
+    add(mCategories.size() + "", titles, values);\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param category the category name\r
+   * @param titles the titles to be used as labels\r
+   * @param values the new value\r
+   */\r
+  public void add(String category, String[] titles, double[] values) {\r
+    mCategories.add(category);\r
+    mTitles.add(titles);\r
+    mValues.add(values);\r
+  }\r
+\r
+  /**\r
+   * Removes an existing value from the series.\r
+   * \r
+   * @param index the index in the series of the value to remove\r
+   */\r
+  public void remove(int index) {\r
+    mCategories.remove(index);\r
+    mTitles.remove(index);\r
+    mValues.remove(index);\r
+  }\r
+\r
+  /**\r
+   * Removes all the existing values from the series.\r
+   */\r
+  public void clear() {\r
+    mCategories.clear();\r
+    mTitles.clear();\r
+    mValues.clear();\r
+  }\r
+\r
+  /**\r
+   * Returns the values at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the value at the index\r
+   */\r
+  public double[] getValues(int index) {\r
+    return mValues.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the category name at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the category name at the index\r
+   */\r
+  public String getCategory(int index) {\r
+    return mCategories.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the categories count.\r
+   * \r
+   * @return the categories count\r
+   */\r
+  public int getCategoriesCount() {\r
+    return mCategories.size();\r
+  }\r
+\r
+  /**\r
+   * Returns the series item count.\r
+   * \r
+   * @param index the index\r
+   * @return the series item count\r
+   */\r
+  public int getItemCount(int index) {\r
+    return mValues.get(index).length;\r
+  }\r
+\r
+  /**\r
+   * Returns the series titles.\r
+   * \r
+   * @param index the index\r
+   * @return the series titles\r
+   */\r
+  public String[] getTitles(int index) {\r
+    return mTitles.get(index);\r
+  }\r
+\r
+  /**\r
+   * Transforms the category series to an XY series.\r
+   * \r
+   * @return the XY series\r
+   */\r
+  public XYSeries toXYSeries() {\r
+    XYSeries xySeries = new XYSeries(mTitle);\r
+    return xySeries;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/Point.java b/android-libraries/achartengine/src/org/achartengine/model/Point.java
new file mode 100644 (file)
index 0000000..4d2767c
--- /dev/null
@@ -0,0 +1,52 @@
+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+\r
+/**\r
+ * A class to encapsulate the definition of a point.\r
+ */\r
+public final class Point implements Serializable {\r
+  /** The X axis coordinate value. */\r
+  private float mX;\r
+  /** The Y axis coordinate value. */\r
+  private float mY;\r
+  \r
+  public Point() {\r
+  }\r
+  \r
+  public Point(float x, float y) {\r
+    mX = x;\r
+    mY = y;\r
+  }\r
+  \r
+  public float getX() {\r
+    return mX;\r
+  }\r
+\r
+  public float getY() {\r
+    return mY;\r
+  }\r
+  \r
+  public void setX(float x) {\r
+    mX = x;\r
+  }\r
+  \r
+  public void setY(float y) {\r
+    mY = y;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/RangeCategorySeries.java b/android-libraries/achartengine/src/org/achartengine/model/RangeCategorySeries.java
new file mode 100644 (file)
index 0000000..c004fa1
--- /dev/null
@@ -0,0 +1,111 @@
+/**\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.model;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+/**\r
+ * A series for the range category charts like the range bar.\r
+ */\r
+public class RangeCategorySeries extends CategorySeries {\r
+  /** The series values. */\r
+  private List<Double> mMaxValues = new ArrayList<Double>();\r
+  /**\r
+   * Builds a new category series.\r
+   * \r
+   * @param title the series title\r
+   */\r
+  public RangeCategorySeries(String title) {\r
+    super(title);\r
+  }\r
+  /**\r
+   * Adds new values to the series\r
+   * \r
+   * @param minValue the new minimum value\r
+   * @param maxValue the new maximum value\r
+   */\r
+  public synchronized void add(double minValue, double maxValue) {\r
+    super.add(minValue);\r
+    mMaxValues.add(maxValue);\r
+  }\r
+\r
+  /**\r
+   * Adds new values to the series.\r
+   * \r
+   * @param category the category\r
+   * @param minValue the new minimum value\r
+   * @param maxValue the new maximum value\r
+   */\r
+  public synchronized void add(String category, double minValue, double maxValue) {\r
+    super.add(category, minValue);\r
+    mMaxValues.add(maxValue);\r
+  }\r
+\r
+  /**\r
+   * Removes existing values from the series.\r
+   * \r
+   * @param index the index in the series of the values to remove\r
+   */\r
+  public synchronized void remove(int index) {\r
+    super.remove(index);\r
+    mMaxValues.remove(index);\r
+  }\r
+\r
+  /**\r
+   * Removes all the existing values from the series.\r
+   */\r
+  public synchronized void clear() {\r
+    super.clear();\r
+    mMaxValues.clear();\r
+  }\r
+\r
+  /**\r
+   * Returns the minimum value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the minimum value at the index\r
+   */\r
+  public double getMinimumValue(int index) {\r
+    return getValue(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the maximum value at the index\r
+   */\r
+  public double getMaximumValue(int index) {\r
+    return mMaxValues.get(index);\r
+  }\r
+\r
+  /**\r
+   * Transforms the range category series to an XY series.\r
+   * \r
+   * @return the XY series\r
+   */\r
+  public XYSeries toXYSeries() {\r
+    XYSeries xySeries = new XYSeries(getTitle());\r
+    int length = getItemCount();\r
+    for (int k = 0; k < length; k++) {\r
+      xySeries.add(k + 1, getMinimumValue(k));\r
+      // the new fast XYSeries implementation doesn't allow 2 values at the same X,\r
+      // so I had to do a hack until I find a better solution\r
+      xySeries.add(k + 1.000001, getMaximumValue(k));\r
+    }\r
+    return xySeries;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/SeriesSelection.java b/android-libraries/achartengine/src/org/achartengine/model/SeriesSelection.java
new file mode 100644 (file)
index 0000000..4319c74
--- /dev/null
@@ -0,0 +1,49 @@
+/**\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.model;\r
+\r
+public class SeriesSelection {\r
+  private int mSeriesIndex;\r
+\r
+  private int mPointIndex;\r
+\r
+  private double mXValue;\r
+\r
+  private double mValue;\r
+\r
+  public SeriesSelection(int seriesIndex, int pointIndex, double xValue, double value) {\r
+    mSeriesIndex = seriesIndex;\r
+    mPointIndex = pointIndex;\r
+    mXValue = xValue;\r
+    mValue = value;\r
+  }\r
+\r
+  public int getSeriesIndex() {\r
+    return mSeriesIndex;\r
+  }\r
+\r
+  public int getPointIndex() {\r
+    return mPointIndex;\r
+  }\r
+\r
+  public double getXValue() {\r
+    return mXValue;\r
+  }\r
+\r
+  public double getValue() {\r
+    return mValue;\r
+  }\r
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/model/TimeSeries.java b/android-libraries/achartengine/src/org/achartengine/model/TimeSeries.java
new file mode 100644 (file)
index 0000000..6b9a18e
--- /dev/null
@@ -0,0 +1,43 @@
+/**\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.model;\r
+\r
+import java.util.Date;\r
+\r
+/**\r
+ * A series for the date / time charts.\r
+ */\r
+public class TimeSeries extends XYSeries {\r
+\r
+  /**\r
+   * Builds a new date / time series.\r
+   * \r
+   * @param title the series title\r
+   */\r
+  public TimeSeries(String title) {\r
+    super(title);\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param x the date / time value for the X axis\r
+   * @param y the value for the Y axis\r
+   */\r
+  public synchronized void add(Date x, double y) {\r
+    super.add(x.getTime(), y);\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/XYMultipleSeriesDataset.java b/android-libraries/achartengine/src/org/achartengine/model/XYMultipleSeriesDataset.java
new file mode 100644 (file)
index 0000000..6ac6a6d
--- /dev/null
@@ -0,0 +1,94 @@
+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * A series that includes 0 to many XYSeries.\r
+ */\r
+public class XYMultipleSeriesDataset implements Serializable {\r
+  /** The included series. */\r
+  private List<XYSeries> mSeries = new ArrayList<XYSeries>();\r
+\r
+  /**\r
+   * Adds a new XY series to the list.\r
+   * \r
+   * @param series the XY series to ass\r
+   */\r
+  public synchronized void addSeries(XYSeries series) {\r
+    mSeries.add(series);\r
+  }\r
+\r
+  /**\r
+   * Adds a new XY series to the list.\r
+   * \r
+   * @param index the index in the series list\r
+   * @param series the XY series to ass\r
+   */\r
+  public synchronized void addSeries(int index, XYSeries series) {\r
+    mSeries.add(index, series);\r
+  }\r
+\r
+  /**\r
+   * Removes the XY series from the list.\r
+   * \r
+   * @param index the index in the series list of the series to remove\r
+   */\r
+  public synchronized void removeSeries(int index) {\r
+    mSeries.remove(index);\r
+  }\r
+\r
+  /**\r
+   * Removes the XY series from the list.\r
+   * \r
+   * @param series the XY series to be removed\r
+   */\r
+  public synchronized void removeSeries(XYSeries series) {\r
+    mSeries.remove(series);\r
+  }\r
+\r
+  /**\r
+   * Returns the XY series at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the XY series at the index\r
+   */\r
+  public synchronized XYSeries getSeriesAt(int index) {\r
+    return mSeries.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the XY series count.\r
+   * \r
+   * @return the XY series count\r
+   */\r
+  public synchronized int getSeriesCount() {\r
+    return mSeries.size();\r
+  }\r
+\r
+  /**\r
+   * Returns an array of the XY series.\r
+   * \r
+   * @return the XY series array\r
+   */\r
+  public synchronized XYSeries[] getSeries() {\r
+    return mSeries.toArray(new XYSeries[0]);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/XYSeries.java b/android-libraries/achartengine/src/org/achartengine/model/XYSeries.java
new file mode 100644 (file)
index 0000000..56063b7
--- /dev/null
@@ -0,0 +1,255 @@
+/**\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.model;\r
+\r
+import java.io.Serializable;\r
+import java.util.Iterator;\r
+import java.util.SortedMap;\r
+\r
+import org.achartengine.util.IndexXYMap;\r
+import org.achartengine.util.MathHelper;\r
+import org.achartengine.util.XYEntry;\r
+\r
+/**\r
+ * An XY series encapsulates values for XY charts like line, time, area,\r
+ * scatter... charts.\r
+ */\r
+public class XYSeries implements Serializable {\r
+  /** The series title. */\r
+  private String mTitle;\r
+  /** A map to contain values for X and Y axes and index for each bundle */\r
+  private final IndexXYMap<Double, Double> mXY = new IndexXYMap<Double, Double>();\r
+  /** The minimum value for the X axis. */\r
+  private double mMinX = MathHelper.NULL_VALUE;\r
+  /** The maximum value for the X axis. */\r
+  private double mMaxX = -MathHelper.NULL_VALUE;\r
+  /** The minimum value for the Y axis. */\r
+  private double mMinY = MathHelper.NULL_VALUE;\r
+  /** The maximum value for the Y axis. */\r
+  private double mMaxY = -MathHelper.NULL_VALUE;\r
+  /** The scale number for this series. */\r
+  private final int mScaleNumber;\r
+\r
+  /**\r
+   * Builds a new XY series.\r
+   * \r
+   * @param title the series title.\r
+   */\r
+  public XYSeries(String title) {\r
+    this(title, 0);\r
+  }\r
+\r
+  /**\r
+   * Builds a new XY series.\r
+   * \r
+   * @param title the series title.\r
+   * @param scaleNumber the series scale number\r
+   */\r
+  public XYSeries(String title, int scaleNumber) {\r
+    mTitle = title;\r
+    mScaleNumber = scaleNumber;\r
+    initRange();\r
+  }\r
+\r
+  public int getScaleNumber() {\r
+    return mScaleNumber;\r
+  }\r
+\r
+  /**\r
+   * Initializes the range for both axes.\r
+   */\r
+  private void initRange() {\r
+    mMinX = MathHelper.NULL_VALUE;\r
+    mMaxX = -MathHelper.NULL_VALUE;\r
+    mMinY = MathHelper.NULL_VALUE;\r
+    mMaxY = -MathHelper.NULL_VALUE;\r
+    int length = getItemCount();\r
+    for (int k = 0; k < length; k++) {\r
+      double x = getX(k);\r
+      double y = getY(k);\r
+      updateRange(x, y);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Updates the range on both axes.\r
+   * \r
+   * @param x the new x value\r
+   * @param y the new y value\r
+   */\r
+  private void updateRange(double x, double y) {\r
+    mMinX = Math.min(mMinX, x);\r
+    mMaxX = Math.max(mMaxX, x);\r
+    mMinY = Math.min(mMinY, y);\r
+    mMaxY = Math.max(mMaxY, y);\r
+  }\r
+\r
+  /**\r
+   * Returns the series title.\r
+   * \r
+   * @return the series title\r
+   */\r
+  public String getTitle() {\r
+    return mTitle;\r
+  }\r
+\r
+  /**\r
+   * Sets the series title.\r
+   * \r
+   * @param title the series title\r
+   */\r
+  public void setTitle(String title) {\r
+    mTitle = title;\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param x the value for the X axis\r
+   * @param y the value for the Y axis\r
+   */\r
+  public synchronized void add(double x, double y) {\r
+    mXY.put(x, y);\r
+    updateRange(x, y);\r
+  }\r
+\r
+  /**\r
+   * Removes an existing value from the series.\r
+   * \r
+   * @param index the index in the series of the value to remove\r
+   */\r
+  public synchronized void remove(int index) {\r
+    XYEntry<Double, Double> removedEntry = mXY.removeByIndex(index);\r
+    double removedX = removedEntry.getKey();\r
+    double removedY = removedEntry.getValue();\r
+    if (removedX == mMinX || removedX == mMaxX || removedY == mMinY || removedY == mMaxY) {\r
+      initRange();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes all the existing values from the series.\r
+   */\r
+  public synchronized void clear() {\r
+    mXY.clear();\r
+    initRange();\r
+  }\r
+\r
+  /**\r
+   * Returns the X axis value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the X value\r
+   */\r
+  public synchronized double getX(int index) {\r
+    return mXY.getXByIndex(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the Y axis value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the Y value\r
+   */\r
+  public synchronized double getY(int index) {\r
+    return mXY.getYByIndex(index);\r
+  }\r
+\r
+  /**\r
+   * Returns submap of x and y values according to the given start and end\r
+   * \r
+   * @param start start x value\r
+   * @param stop stop x value\r
+   * @return a submap of x and y values\r
+   */\r
+  public synchronized SortedMap<Double, Double> getRange(double start, double stop,\r
+      int beforeAfterPoints) {\r
+    // we need to add one point before the start and one point after the end (if\r
+    // there are any)\r
+    // to ensure that line doesn't end before the end of the screen\r
+\r
+    // this would be simply: start = mXY.lowerKey(start) but NavigableMap is\r
+    // available since API 9\r
+    SortedMap<Double, Double> headMap = mXY.headMap(start);\r
+    if (!headMap.isEmpty()) {\r
+      start = headMap.lastKey();\r
+    }\r
+\r
+    // this would be simply: end = mXY.higherKey(end) but NavigableMap is\r
+    // available since API 9\r
+    // so we have to do this hack in order to support older versions\r
+    SortedMap<Double, Double> tailMap = mXY.tailMap(stop);\r
+    if (!tailMap.isEmpty()) {\r
+      Iterator<Double> tailIterator = tailMap.keySet().iterator();\r
+      Double next = tailIterator.next();\r
+      if (tailIterator.hasNext()) {\r
+        stop = tailIterator.next();\r
+      } else {\r
+        stop += next;\r
+      }\r
+    }\r
+    return mXY.subMap(start, stop);\r
+  }\r
+\r
+  public int getIndexForKey(double key) {\r
+    return mXY.getIndexForKey(key);\r
+  }\r
+\r
+  /**\r
+   * Returns the series item count.\r
+   * \r
+   * @return the series item count\r
+   */\r
+  public synchronized int getItemCount() {\r
+    return mXY.size();\r
+  }\r
+\r
+  /**\r
+   * Returns the minimum value on the X axis.\r
+   * \r
+   * @return the X axis minimum value\r
+   */\r
+  public double getMinX() {\r
+    return mMinX;\r
+  }\r
+\r
+  /**\r
+   * Returns the minimum value on the Y axis.\r
+   * \r
+   * @return the Y axis minimum value\r
+   */\r
+  public double getMinY() {\r
+    return mMinY;\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum value on the X axis.\r
+   * \r
+   * @return the X axis maximum value\r
+   */\r
+  public double getMaxX() {\r
+    return mMaxX;\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum value on the Y axis.\r
+   * \r
+   * @return the Y axis maximum value\r
+   */\r
+  public double getMaxY() {\r
+    return mMaxY;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/XYValueSeries.java b/android-libraries/achartengine/src/org/achartengine/model/XYValueSeries.java
new file mode 100644 (file)
index 0000000..81aff28
--- /dev/null
@@ -0,0 +1,139 @@
+/**\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.model;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.achartengine.util.MathHelper;\r
+\r
+/**\r
+ * An extension of the XY series which adds a third dimension. It is used for XY\r
+ * charts like bubble.\r
+ */\r
+public class XYValueSeries extends XYSeries {\r
+  /** A list to contain the series values. */\r
+  private List<Double> mValue = new ArrayList<Double>();\r
+  /** The minimum value. */\r
+  private double mMinValue = MathHelper.NULL_VALUE;\r
+  /** The maximum value. */\r
+  private double mMaxValue = -MathHelper.NULL_VALUE;\r
+\r
+  /**\r
+   * Builds a new XY value series.\r
+   * \r
+   * @param title the series title.\r
+   */\r
+  public XYValueSeries(String title) {\r
+    super(title);\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param x the value for the X axis\r
+   * @param y the value for the Y axis\r
+   * @param value the value\r
+   */\r
+  public synchronized void add(double x, double y, double value) {\r
+    super.add(x, y);\r
+    mValue.add(value);\r
+    updateRange(value);\r
+  }\r
+\r
+  /**\r
+   * Initializes the values range.\r
+   */\r
+  private void initRange() {\r
+    mMinValue = MathHelper.NULL_VALUE;\r
+    mMaxValue = MathHelper.NULL_VALUE;\r
+    int length = getItemCount();\r
+    for (int k = 0; k < length; k++) {\r
+      updateRange(getValue(k));\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Updates the values range.\r
+   * \r
+   * @param value the new value\r
+   */\r
+  private void updateRange(double value) {\r
+    mMinValue = Math.min(mMinValue, value);\r
+    mMaxValue = Math.max(mMaxValue, value);\r
+  }\r
+\r
+  /**\r
+   * Adds a new value to the series.\r
+   * \r
+   * @param x the value for the X axis\r
+   * @param y the value for the Y axis\r
+   */\r
+  public synchronized void add(double x, double y) {\r
+    add(x, y, 0d);\r
+  }\r
+\r
+  /**\r
+   * Removes an existing value from the series.\r
+   * \r
+   * @param index the index in the series of the value to remove\r
+   */\r
+  public synchronized void remove(int index) {\r
+    super.remove(index);\r
+    double removedValue = mValue.remove(index);\r
+    if (removedValue == mMinValue || removedValue == mMaxValue) {\r
+      initRange();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Removes all the values from the series.\r
+   */\r
+  public synchronized void clear() {\r
+    super.clear();\r
+    mValue.clear();\r
+    initRange();\r
+  }\r
+\r
+  /**\r
+   * Returns the value at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the value\r
+   */\r
+  public synchronized double getValue(int index) {\r
+    return mValue.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the minimum value.\r
+   * \r
+   * @return the minimum value\r
+   */\r
+  public double getMinValue() {\r
+    return mMinValue;\r
+  }\r
+\r
+  /**\r
+   * Returns the maximum value.\r
+   * \r
+   * @return the maximum value\r
+   */\r
+  public double getMaxValue() {\r
+    return mMaxValue;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/model/package.html b/android-libraries/achartengine/src/org/achartengine/model/package.html
new file mode 100644 (file)
index 0000000..6135d29
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<title>AChartEngine</title>\r
+<body>\r
+Provides the classes that handle the data values (data model) to be used by displaying the charts.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/package.html b/android-libraries/achartengine/src/org/achartengine/package.html
new file mode 100644 (file)
index 0000000..b26cf25
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<title>AChartEngine</title>\r
+<body>\r
+The main classes, including the ChartFactory, GraphicalActivity and GraphicalView.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/BasicStroke.java b/android-libraries/achartengine/src/org/achartengine/renderer/BasicStroke.java
new file mode 100644 (file)
index 0000000..3ac93d5
--- /dev/null
@@ -0,0 +1,107 @@
+/**\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.renderer;\r
+\r
+import java.io.Serializable;\r
+\r
+import android.graphics.Paint.Cap;\r
+import android.graphics.Paint.Join;\r
+\r
+/**\r
+ * A descriptor for the stroke style.\r
+ */\r
+public class BasicStroke implements Serializable {\r
+  /** The solid line style. */\r
+  public static final BasicStroke SOLID = new BasicStroke(Cap.BUTT, Join.MITER, 4, null, 0);\r
+  /** The dashed line style. */\r
+  public static final BasicStroke DASHED = new BasicStroke(Cap.ROUND, Join.BEVEL, 10, new float[] {\r
+      10, 10 }, 1);\r
+  /** The dot line style. */\r
+  public static final BasicStroke DOTTED = new BasicStroke(Cap.ROUND, Join.BEVEL, 5, new float[] {\r
+      2, 10 }, 1);\r
+  /** The stroke cap. */\r
+  private Cap mCap;\r
+  /** The stroke join. */\r
+  private Join mJoin;\r
+  /** The stroke miter. */\r
+  private float mMiter;\r
+  /** The path effect intervals. */\r
+  private float[] mIntervals;\r
+  /** The path effect phase. */\r
+  private float mPhase;\r
+\r
+  /**\r
+   * Build a new basic stroke style.\r
+   * \r
+   * @param cap the stroke cap\r
+   * @param join the stroke join\r
+   * @param miter the stroke miter\r
+   * @param intervals the path effect intervals\r
+   * @param phase the path effect phase\r
+   */\r
+  public BasicStroke(Cap cap, Join join, float miter, float[] intervals, float phase) {\r
+    mCap = cap;\r
+    mJoin = join;\r
+    mMiter = miter;\r
+    mIntervals = intervals;\r
+  }\r
+\r
+  /**\r
+   * Returns the stroke cap.\r
+   * \r
+   * @return the stroke cap\r
+   */\r
+  public Cap getCap() {\r
+    return mCap;\r
+  }\r
+\r
+  /**\r
+   * Returns the stroke join.\r
+   * \r
+   * @return the stroke join\r
+   */\r
+  public Join getJoin() {\r
+    return mJoin;\r
+  }\r
+\r
+  /**\r
+   * Returns the stroke miter.\r
+   * \r
+   * @return the stroke miter\r
+   */\r
+  public float getMiter() {\r
+    return mMiter;\r
+  }\r
+\r
+  /**\r
+   * Returns the path effect intervals.\r
+   * \r
+   * @return the path effect intervals\r
+   */\r
+  public float[] getIntervals() {\r
+    return mIntervals;\r
+  }\r
+\r
+  /**\r
+   * Returns the path effect phase.\r
+   * \r
+   * @return the path effect phase\r
+   */\r
+  public float getPhase() {\r
+    return mPhase;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/DefaultRenderer.java b/android-libraries/achartengine/src/org/achartengine/renderer/DefaultRenderer.java
new file mode 100644 (file)
index 0000000..4dbb254
--- /dev/null
@@ -0,0 +1,750 @@
+/**\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.renderer;\r
+\r
+import java.io.Serializable;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import android.graphics.Color;\r
+import android.graphics.Typeface;\r
+\r
+/**\r
+ * An abstract renderer to be extended by the multiple series classes.\r
+ */\r
+public class DefaultRenderer implements Serializable {\r
+  /** The chart title. */\r
+  private String mChartTitle = "";\r
+  /** The chart title text size. */\r
+  private float mChartTitleTextSize = 15;\r
+  /** A no color constant. */\r
+  public static final int NO_COLOR = 0;\r
+  /** The default background color. */\r
+  public static final int BACKGROUND_COLOR = Color.BLACK;\r
+  /** The default color for text. */\r
+  public static final int TEXT_COLOR = Color.LTGRAY;\r
+  /** A text font for regular text, like the chart labels. */\r
+  private static final Typeface REGULAR_TEXT_FONT = Typeface\r
+      .create(Typeface.SERIF, Typeface.NORMAL);\r
+  /** The typeface name for the texts. */\r
+  private String mTextTypefaceName = REGULAR_TEXT_FONT.toString();\r
+  /** The typeface style for the texts. */\r
+  private int mTextTypefaceStyle = Typeface.NORMAL;\r
+  /** The chart background color. */\r
+  private int mBackgroundColor;\r
+  /** If the background color is applied. */\r
+  private boolean mApplyBackgroundColor;\r
+  /** If the axes are visible. */\r
+  private boolean mShowAxes = true;\r
+  /** The axes color. */\r
+  private int mAxesColor = TEXT_COLOR;\r
+  /** If the labels are visible. */\r
+  private boolean mShowLabels = true;\r
+  /** The labels color. */\r
+  private int mLabelsColor = TEXT_COLOR;\r
+  /** The labels text size. */\r
+  private float mLabelsTextSize = 10;\r
+  /** If the legend is visible. */\r
+  private boolean mShowLegend = true;\r
+  /** The legend text size. */\r
+  private float mLegendTextSize = 12;\r
+  /** If the legend should size to fit. */\r
+  private boolean mFitLegend = false;\r
+  /** If the X axis grid should be displayed. */\r
+  private boolean mShowGridX = false;\r
+  /** If the Y axis grid should be displayed. */\r
+  private boolean mShowGridY = false;\r
+  /** If the custom text grid should be displayed. */\r
+  private boolean mShowCustomTextGrid = false;\r
+  /** The simple renderers that are included in this multiple series renderer. */\r
+  private List<SimpleSeriesRenderer> mRenderers = new ArrayList<SimpleSeriesRenderer>();\r
+  /** The antialiasing flag. */\r
+  private boolean mAntialiasing = true;\r
+  /** The legend height. */\r
+  private int mLegendHeight = 0;\r
+  /** The margins size. */\r
+  private int[] mMargins = new int[] { 20, 30, 10, 20 };\r
+  /** A value to be used for scaling the chart. */\r
+  private float mScale = 1;\r
+  /** A flag for enabling the pan. */\r
+  private boolean mPanEnabled = true;\r
+  /** A flag for enabling the zoom. */\r
+  private boolean mZoomEnabled = true;\r
+  /** A flag for enabling the visibility of the zoom buttons. */\r
+  private boolean mZoomButtonsVisible = false;\r
+  /** The zoom rate. */\r
+  private float mZoomRate = 1.5f;\r
+  /** A flag for enabling the external zoom. */\r
+  private boolean mExternalZoomEnabled = false;\r
+  /** The original chart scale. */\r
+  private float mOriginalScale = mScale;\r
+  /** A flag for enabling the click on elements. */\r
+  private boolean mClickEnabled = false;\r
+  /** The selectable radius around a clickable point. */\r
+  private int selectableBuffer = 15;\r
+  /** If the chart should display the values (available for pie chart). */\r
+  private boolean mDisplayValues;\r
+\r
+  /**\r
+   * A flag to be set if the chart is inside a scroll and doesn't need to shrink\r
+   * when not enough space.\r
+   */\r
+  private boolean mInScroll;\r
+  /** The start angle for circular charts such as pie, doughnut, etc. */\r
+  private float mStartAngle = 0;\r
+\r
+  /**\r
+   * Returns the chart title.\r
+   * \r
+   * @return the chart title\r
+   */\r
+  public String getChartTitle() {\r
+    return mChartTitle;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart title.\r
+   * \r
+   * @param title the chart title\r
+   */\r
+  public void setChartTitle(String title) {\r
+    mChartTitle = title;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart title text size.\r
+   * \r
+   * @return the chart title text size\r
+   */\r
+  public float getChartTitleTextSize() {\r
+    return mChartTitleTextSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart title text size.\r
+   * \r
+   * @param textSize the chart title text size\r
+   */\r
+  public void setChartTitleTextSize(float textSize) {\r
+    mChartTitleTextSize = textSize;\r
+  }\r
+\r
+  /**\r
+   * Adds a simple renderer to the multiple renderer.\r
+   * \r
+   * @param renderer the renderer to be added\r
+   */\r
+  public void addSeriesRenderer(SimpleSeriesRenderer renderer) {\r
+    mRenderers.add(renderer);\r
+  }\r
+\r
+  /**\r
+   * Adds a simple renderer to the multiple renderer.\r
+   * \r
+   * @param index the index in the renderers list\r
+   * @param renderer the renderer to be added\r
+   */\r
+  public void addSeriesRenderer(int index, SimpleSeriesRenderer renderer) {\r
+    mRenderers.add(index, renderer);\r
+  }\r
+\r
+  /**\r
+   * Removes a simple renderer from the multiple renderer.\r
+   * \r
+   * @param renderer the renderer to be removed\r
+   */\r
+  public void removeSeriesRenderer(SimpleSeriesRenderer renderer) {\r
+    mRenderers.remove(renderer);\r
+  }\r
+\r
+  /**\r
+   * Removes all renderers from the multiple renderer.\r
+   */\r
+  public void removeAllRenderers() {\r
+    mRenderers.clear();\r
+  }\r
+\r
+  /**\r
+   * Returns the simple renderer from the multiple renderer list.\r
+   * \r
+   * @param index the index in the simple renderers list\r
+   * @return the simple renderer at the specified index\r
+   */\r
+  public SimpleSeriesRenderer getSeriesRendererAt(int index) {\r
+    return mRenderers.get(index);\r
+  }\r
+\r
+  /**\r
+   * Returns the simple renderers count in the multiple renderer list.\r
+   * \r
+   * @return the simple renderers count\r
+   */\r
+  public int getSeriesRendererCount() {\r
+    return mRenderers.size();\r
+  }\r
+\r
+  /**\r
+   * Returns an array of the simple renderers in the multiple renderer list.\r
+   * \r
+   * @return the simple renderers array\r
+   */\r
+  public SimpleSeriesRenderer[] getSeriesRenderers() {\r
+    return mRenderers.toArray(new SimpleSeriesRenderer[0]);\r
+  }\r
+\r
+  /**\r
+   * Returns the background color.\r
+   * \r
+   * @return the background color\r
+   */\r
+  public int getBackgroundColor() {\r
+    return mBackgroundColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the background color.\r
+   * \r
+   * @param color the background color\r
+   */\r
+  public void setBackgroundColor(int color) {\r
+    mBackgroundColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns if the background color should be applied.\r
+   * \r
+   * @return the apply flag for the background color.\r
+   */\r
+  public boolean isApplyBackgroundColor() {\r
+    return mApplyBackgroundColor;\r
+  }\r
+\r
+  /**\r
+   * Sets if the background color should be applied.\r
+   * \r
+   * @param apply the apply flag for the background color\r
+   */\r
+  public void setApplyBackgroundColor(boolean apply) {\r
+    mApplyBackgroundColor = apply;\r
+  }\r
+\r
+  /**\r
+   * Returns the axes color.\r
+   * \r
+   * @return the axes color\r
+   */\r
+  public int getAxesColor() {\r
+    return mAxesColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the axes color.\r
+   * \r
+   * @param color the axes color\r
+   */\r
+  public void setAxesColor(int color) {\r
+    mAxesColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the labels color.\r
+   * \r
+   * @return the labels color\r
+   */\r
+  public int getLabelsColor() {\r
+    return mLabelsColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the labels color.\r
+   * \r
+   * @param color the labels color\r
+   */\r
+  public void setLabelsColor(int color) {\r
+    mLabelsColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the labels text size.\r
+   * \r
+   * @return the labels text size\r
+   */\r
+  public float getLabelsTextSize() {\r
+    return mLabelsTextSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the labels text size.\r
+   * \r
+   * @param textSize the labels text size\r
+   */\r
+  public void setLabelsTextSize(float textSize) {\r
+    mLabelsTextSize = textSize;\r
+  }\r
+\r
+  /**\r
+   * Returns if the axes should be visible.\r
+   * \r
+   * @return the visibility flag for the axes\r
+   */\r
+  public boolean isShowAxes() {\r
+    return mShowAxes;\r
+  }\r
+\r
+  /**\r
+   * Sets if the axes should be visible.\r
+   * \r
+   * @param showAxes the visibility flag for the axes\r
+   */\r
+  public void setShowAxes(boolean showAxes) {\r
+    mShowAxes = showAxes;\r
+  }\r
+\r
+  /**\r
+   * Returns if the labels should be visible.\r
+   * \r
+   * @return the visibility flag for the labels\r
+   */\r
+  public boolean isShowLabels() {\r
+    return mShowLabels;\r
+  }\r
+\r
+  /**\r
+   * Sets if the labels should be visible.\r
+   * \r
+   * @param showLabels the visibility flag for the labels\r
+   */\r
+  public void setShowLabels(boolean showLabels) {\r
+    mShowLabels = showLabels;\r
+  }\r
+\r
+  /**\r
+   * Returns if the X axis grid should be visible.\r
+   * \r
+   * @return the visibility flag for the X axis grid\r
+   */\r
+  public boolean isShowGridX() {\r
+    return mShowGridX;\r
+  }\r
+\r
+  /**\r
+   * Returns if the Y axis grid should be visible.\r
+   * \r
+   * @return the visibility flag for the Y axis grid\r
+   */\r
+  public boolean isShowGridY() {\r
+    return mShowGridY;\r
+  }\r
+\r
+  /**\r
+   * Sets if the X axis grid should be visible.\r
+   * \r
+   * @param showGrid the visibility flag for the X axis grid\r
+   */\r
+  public void setShowGridX(boolean showGrid) {\r
+    mShowGridX = showGrid;\r
+  }\r
+\r
+  /**\r
+   * Sets if the Y axis grid should be visible.\r
+   * \r
+   * @param showGrid the visibility flag for the Y axis grid\r
+   */\r
+  public void setShowGridY(boolean showGrid) {\r
+    mShowGridY = showGrid;\r
+  }\r
+\r
+  /**\r
+   * Sets if the grid should be visible.\r
+   * \r
+   * @param showGrid the visibility flag for the grid\r
+   */\r
+  public void setShowGrid(boolean showGrid) {\r
+    setShowGridX(showGrid);\r
+    setShowGridY(showGrid);\r
+  }\r
+\r
+  /**\r
+   * Returns if the grid should be visible for custom X or Y labels.\r
+   * \r
+   * @return the visibility flag for the custom text grid\r
+   */\r
+  public boolean isShowCustomTextGrid() {\r
+    return mShowCustomTextGrid;\r
+  }\r
+\r
+  /**\r
+   * Sets if the grid for custom X or Y labels should be visible.\r
+   * \r
+   * @param showGrid the visibility flag for the custom text grid\r
+   */\r
+  public void setShowCustomTextGrid(boolean showGrid) {\r
+    mShowCustomTextGrid = showGrid;\r
+  }\r
+\r
+  /**\r
+   * Returns if the legend should be visible.\r
+   * \r
+   * @return the visibility flag for the legend\r
+   */\r
+  public boolean isShowLegend() {\r
+    return mShowLegend;\r
+  }\r
+\r
+  /**\r
+   * Sets if the legend should be visible.\r
+   * \r
+   * @param showLegend the visibility flag for the legend\r
+   */\r
+  public void setShowLegend(boolean showLegend) {\r
+    mShowLegend = showLegend;\r
+  }\r
+\r
+  /**\r
+   * Returns if the legend should size to fit.\r
+   * \r
+   * @return the fit behavior\r
+   */\r
+  public boolean isFitLegend() {\r
+    return mFitLegend;\r
+  }\r
+\r
+  /**\r
+   * Sets if the legend should size to fit.\r
+   * \r
+   * @param fit the fit behavior\r
+   */\r
+  public void setFitLegend(boolean fit) {\r
+    mFitLegend = fit;\r
+  }\r
+\r
+  /**\r
+   * Returns the text typeface name.\r
+   * \r
+   * @return the text typeface name\r
+   */\r
+  public String getTextTypefaceName() {\r
+    return mTextTypefaceName;\r
+  }\r
+\r
+  /**\r
+   * Returns the text typeface style.\r
+   * \r
+   * @return the text typeface style\r
+   */\r
+  public int getTextTypefaceStyle() {\r
+    return mTextTypefaceStyle;\r
+  }\r
+\r
+  /**\r
+   * Returns the legend text size.\r
+   * \r
+   * @return the legend text size\r
+   */\r
+  public float getLegendTextSize() {\r
+    return mLegendTextSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the legend text size.\r
+   * \r
+   * @param textSize the legend text size\r
+   */\r
+  public void setLegendTextSize(float textSize) {\r
+    mLegendTextSize = textSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the text typeface name and style.\r
+   * \r
+   * @param typefaceName the text typeface name\r
+   * @param style the text typeface style\r
+   */\r
+  public void setTextTypeface(String typefaceName, int style) {\r
+    mTextTypefaceName = typefaceName;\r
+    mTextTypefaceStyle = style;\r
+  }\r
+\r
+  /**\r
+   * Returns the antialiasing flag value.\r
+   * \r
+   * @return the antialiasing value\r
+   */\r
+  public boolean isAntialiasing() {\r
+    return mAntialiasing;\r
+  }\r
+\r
+  /**\r
+   * Sets the antialiasing value.\r
+   * \r
+   * @param antialiasing the antialiasing\r
+   */\r
+  public void setAntialiasing(boolean antialiasing) {\r
+    mAntialiasing = antialiasing;\r
+  }\r
+\r
+  /**\r
+   * Returns the value to be used for scaling the chart.\r
+   * \r
+   * @return the scale value\r
+   */\r
+  public float getScale() {\r
+    return mScale;\r
+  }\r
+\r
+  /**\r
+   * Returns the original value to be used for scaling the chart.\r
+   * \r
+   * @return the original scale value\r
+   */\r
+  public float getOriginalScale() {\r
+    return mOriginalScale;\r
+  }\r
+\r
+  /**\r
+   * Sets the value to be used for scaling the chart. It works on some charts\r
+   * like pie, doughnut, dial.\r
+   * \r
+   * @param scale the scale value\r
+   */\r
+  public void setScale(float scale) {\r
+    mScale = scale;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the zoom.\r
+   * \r
+   * @return if zoom is enabled\r
+   */\r
+  public boolean isZoomEnabled() {\r
+    return mZoomEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the zoom.\r
+   * \r
+   * @param enabled zoom enabled\r
+   */\r
+  public void setZoomEnabled(boolean enabled) {\r
+    mZoomEnabled = enabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the visible state of the zoom buttons.\r
+   * \r
+   * @return if zoom buttons are visible\r
+   */\r
+  public boolean isZoomButtonsVisible() {\r
+    return mZoomButtonsVisible;\r
+  }\r
+\r
+  /**\r
+   * Sets the visible state of the zoom buttons.\r
+   * \r
+   * @param visible if the zoom buttons are visible\r
+   */\r
+  public void setZoomButtonsVisible(boolean visible) {\r
+    mZoomButtonsVisible = visible;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the external (application implemented) zoom.\r
+   * \r
+   * @return if external zoom is enabled\r
+   */\r
+  public boolean isExternalZoomEnabled() {\r
+    return mExternalZoomEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the external (application implemented) zoom.\r
+   * \r
+   * @param enabled external zoom enabled\r
+   */\r
+  public void setExternalZoomEnabled(boolean enabled) {\r
+    mExternalZoomEnabled = enabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the zoom rate.\r
+   * \r
+   * @return the zoom rate\r
+   */\r
+  public float getZoomRate() {\r
+    return mZoomRate;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the pan.\r
+   * \r
+   * @return if pan is enabled\r
+   */\r
+  public boolean isPanEnabled() {\r
+    return mPanEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the pan.\r
+   * \r
+   * @param enabled pan enabled\r
+   */\r
+  public void setPanEnabled(boolean enabled) {\r
+    mPanEnabled = enabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the zoom rate.\r
+   * \r
+   * @param rate the zoom rate\r
+   */\r
+  public void setZoomRate(float rate) {\r
+    mZoomRate = rate;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the click.\r
+   * \r
+   * @return if click is enabled\r
+   */\r
+  public boolean isClickEnabled() {\r
+    return mClickEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the click.\r
+   * \r
+   * @param enabled click enabled\r
+   */\r
+  public void setClickEnabled(boolean enabled) {\r
+    mClickEnabled = enabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the selectable radius value around clickable points.\r
+   * \r
+   * @return the selectable radius\r
+   */\r
+  public int getSelectableBuffer() {\r
+    return selectableBuffer;\r
+  }\r
+\r
+  /**\r
+   * Sets the selectable radius value around clickable points.\r
+   * \r
+   * @param buffer the selectable radius\r
+   */\r
+  public void setSelectableBuffer(int buffer) {\r
+    selectableBuffer = buffer;\r
+  }\r
+\r
+  /**\r
+   * Returns the legend height.\r
+   * \r
+   * @return the legend height\r
+   */\r
+  public int getLegendHeight() {\r
+    return mLegendHeight;\r
+  }\r
+\r
+  /**\r
+   * Sets the legend height, in pixels.\r
+   * \r
+   * @param height the legend height\r
+   */\r
+  public void setLegendHeight(int height) {\r
+    mLegendHeight = height;\r
+  }\r
+\r
+  /**\r
+   * Returns the margin sizes. An array containing the margins in this order:\r
+   * top, left, bottom, right\r
+   * \r
+   * @return the margin sizes\r
+   */\r
+  public int[] getMargins() {\r
+    return mMargins;\r
+  }\r
+\r
+  /**\r
+   * Sets the margins, in pixels.\r
+   * \r
+   * @param margins an array containing the margin size values, in this order:\r
+   *          top, left, bottom, right\r
+   */\r
+  public void setMargins(int[] margins) {\r
+    mMargins = margins;\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart is inside a scroll view and doesn't need to shrink.\r
+   * \r
+   * @return if it is inside a scroll view\r
+   */\r
+  public boolean isInScroll() {\r
+    return mInScroll;\r
+  }\r
+\r
+  /**\r
+   * To be set if the chart is inside a scroll view and doesn't need to shrink\r
+   * when not enough space.\r
+   * \r
+   * @param inScroll if it is inside a scroll view\r
+   */\r
+  public void setInScroll(boolean inScroll) {\r
+    mInScroll = inScroll;\r
+  }\r
+\r
+  /**\r
+   * Returns the start angle for circular charts such as pie, doughnut. An angle\r
+   * of 0 degrees correspond to the geometric angle of 0 degrees (3 o'clock on a\r
+   * watch.)\r
+   * \r
+   * @return the start angle in degrees\r
+   */\r
+  public float getStartAngle() {\r
+    return mStartAngle;\r
+  }\r
+\r
+  /**\r
+   * Sets the start angle for circular charts such as pie, doughnut, etc. An\r
+   * angle of 0 degrees correspond to the geometric angle of 0 degrees (3\r
+   * o'clock on a watch.)\r
+   * \r
+   * @param startAngle the start angle in degrees\r
+   */\r
+  public void setStartAngle(float startAngle) {\r
+    mStartAngle = startAngle;\r
+  }\r
+\r
+  /**\r
+   * Returns if the values should be displayed as text.\r
+   * \r
+   * @return if the values should be displayed as text\r
+   */\r
+  public boolean isDisplayValues() {\r
+    return mDisplayValues;\r
+  }\r
+\r
+  /**\r
+   * Sets if the values should be displayed as text (supported by pie chart).\r
+   * \r
+   * @param display if the values should be displayed as text\r
+   */\r
+  public void setDisplayValues(boolean display) {\r
+    mDisplayValues = display;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/DialRenderer.java b/android-libraries/achartengine/src/org/achartengine/renderer/DialRenderer.java
new file mode 100644 (file)
index 0000000..1ed8461
--- /dev/null
@@ -0,0 +1,196 @@
+/**\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.renderer;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+import org.achartengine.util.MathHelper;\r
+\r
+/**\r
+ * Dial chart renderer.\r
+ */\r
+public class DialRenderer extends DefaultRenderer {\r
+  /** The start angle in the dial range. */\r
+  private double mAngleMin = 330;\r
+  /** The end angle in the dial range. */\r
+  private double mAngleMax = 30;\r
+  /** The start value in dial range. */\r
+  private double mMinValue = MathHelper.NULL_VALUE;\r
+  /** The end value in dial range. */\r
+  private double mMaxValue = -MathHelper.NULL_VALUE;\r
+  /** The spacing for the minor ticks. */\r
+  private double mMinorTickSpacing = MathHelper.NULL_VALUE;\r
+  /** The spacing for the major ticks. */\r
+  private double mMajorTickSpacing = MathHelper.NULL_VALUE;\r
+  /** An array of the renderers types (default is NEEDLE). */\r
+  private List<Type> mVisualTypes = new ArrayList<Type>();\r
+\r
+  public enum Type {\r
+    NEEDLE, ARROW;\r
+  }\r
+\r
+  /**\r
+   * Returns the start angle value of the dial.\r
+   * \r
+   * @return the angle start value\r
+   */\r
+  public double getAngleMin() {\r
+    return mAngleMin;\r
+  }\r
+\r
+  /**\r
+   * Sets the start angle value of the dial.\r
+   * \r
+   * @param min the dial angle start value\r
+   */\r
+  public void setAngleMin(double min) {\r
+    mAngleMin = min;\r
+  }\r
+\r
+  /**\r
+   * Returns the end angle value of the dial.\r
+   * \r
+   * @return the angle end value\r
+   */\r
+  public double getAngleMax() {\r
+    return mAngleMax;\r
+  }\r
+\r
+  /**\r
+   * Sets the end angle value of the dial.\r
+   * \r
+   * @param max the dial angle end value\r
+   */\r
+  public void setAngleMax(double max) {\r
+    mAngleMax = max;\r
+  }\r
+\r
+  /**\r
+   * Returns the start value to be rendered on the dial.\r
+   * \r
+   * @return the start value on dial\r
+   */\r
+  public double getMinValue() {\r
+    return mMinValue;\r
+  }\r
+\r
+  /**\r
+   * Sets the start value to be rendered on the dial.\r
+   * \r
+   * @param min the start value on the dial\r
+   */\r
+  public void setMinValue(double min) {\r
+    mMinValue = min;\r
+  }\r
+\r
+  /**\r
+   * Returns if the minimum dial value was set.\r
+   * \r
+   * @return the minimum dial value was set or not\r
+   */\r
+  public boolean isMinValueSet() {\r
+    return mMinValue != MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the end value to be rendered on the dial.\r
+   * \r
+   * @return the end value on the dial\r
+   */\r
+  public double getMaxValue() {\r
+    return mMaxValue;\r
+  }\r
+\r
+  /**\r
+   * Sets the end value to be rendered on the dial.\r
+   * \r
+   * @param max the end value on the dial\r
+   */\r
+  public void setMaxValue(double max) {\r
+    mMaxValue = max;\r
+  }\r
+\r
+  /**\r
+   * Returns if the maximum dial value was set.\r
+   * \r
+   * @return the maximum dial was set or not\r
+   */\r
+  public boolean isMaxValueSet() {\r
+    return mMaxValue != -MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the minor ticks spacing.\r
+   * \r
+   * @return the minor ticks spacing\r
+   */\r
+  public double getMinorTicksSpacing() {\r
+    return mMinorTickSpacing;\r
+  }\r
+\r
+  /**\r
+   * Sets the minor ticks spacing.\r
+   * \r
+   * @param spacing the minor ticks spacing\r
+   */\r
+  public void setMinorTicksSpacing(double spacing) {\r
+    mMinorTickSpacing = spacing;\r
+  }\r
+\r
+  /**\r
+   * Returns the major ticks spacing.\r
+   * \r
+   * @return the major ticks spacing\r
+   */\r
+  public double getMajorTicksSpacing() {\r
+    return mMajorTickSpacing;\r
+  }\r
+\r
+  /**\r
+   * Sets the major ticks spacing.\r
+   * \r
+   * @param spacing the major ticks spacing\r
+   */\r
+  public void setMajorTicksSpacing(double spacing) {\r
+    mMajorTickSpacing = spacing;\r
+  }\r
+\r
+  /**\r
+   * Returns the visual type at the specified index.\r
+   * \r
+   * @param index the index\r
+   * @return the visual type\r
+   */\r
+  public Type getVisualTypeForIndex(int index) {\r
+    if (index < mVisualTypes.size()) {\r
+      return mVisualTypes.get(index);\r
+    }\r
+    return Type.NEEDLE;\r
+  }\r
+\r
+  /**\r
+   * Sets the visual types.\r
+   * \r
+   * @param types the visual types\r
+   */\r
+  public void setVisualTypes(Type[] types) {\r
+    mVisualTypes.clear();\r
+    mVisualTypes.addAll(Arrays.asList(types));\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/SimpleSeriesRenderer.java b/android-libraries/achartengine/src/org/achartengine/renderer/SimpleSeriesRenderer.java
new file mode 100644 (file)
index 0000000..0763fc5
--- /dev/null
@@ -0,0 +1,235 @@
+/**\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.renderer;\r
+\r
+import java.io.Serializable;\r
+\r
+import android.graphics.Color;\r
+import android.graphics.Paint.Align;\r
+\r
+/**\r
+ * A simple series renderer.\r
+ */\r
+public class SimpleSeriesRenderer implements Serializable {\r
+  /** The series color. */\r
+  private int mColor = Color.BLUE;\r
+  /** If the values should be displayed above the chart points. */\r
+  private boolean mDisplayChartValues;\r
+  /** The chart values text size. */\r
+  private float mChartValuesTextSize = 10;\r
+  /** The chart values text alignment. */\r
+  private Align mChartValuesTextAlign = Align.CENTER;\r
+  /** The chart values spacing from the data point. */\r
+  private float mChartValuesSpacing = 5f;\r
+  /** The stroke style. */\r
+  private BasicStroke mStroke;\r
+  /** If gradient is enabled. */\r
+  private boolean mGradientEnabled = false;\r
+  /** The gradient start value. */\r
+  private double mGradientStartValue;\r
+  /** The gradient start color. */\r
+  private int mGradientStartColor;\r
+  /** The gradient stop value. */\r
+  private double mGradientStopValue;\r
+  /** The gradient stop color. */\r
+  private int mGradientStopColor;\r
+\r
+  /**\r
+   * Returns the series color.\r
+   * \r
+   * @return the series color\r
+   */\r
+  public int getColor() {\r
+    return mColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the series color.\r
+   * \r
+   * @param color the series color\r
+   */\r
+  public void setColor(int color) {\r
+    mColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart point values should be displayed as text.\r
+   * \r
+   * @return if the chart point values should be displayed as text\r
+   */\r
+  public boolean isDisplayChartValues() {\r
+    return mDisplayChartValues;\r
+  }\r
+\r
+  /**\r
+   * Sets if the chart point values should be displayed as text.\r
+   * \r
+   * @param display if the chart point values should be displayed as text\r
+   */\r
+  public void setDisplayChartValues(boolean display) {\r
+    mDisplayChartValues = display;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart values text size.\r
+   * \r
+   * @return the chart values text size\r
+   */\r
+  public float getChartValuesTextSize() {\r
+    return mChartValuesTextSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart values text size.\r
+   * \r
+   * @param textSize the chart values text size\r
+   */\r
+  public void setChartValuesTextSize(float textSize) {\r
+    mChartValuesTextSize = textSize;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart values text align.\r
+   * \r
+   * @return the chart values text align\r
+   */\r
+  public Align getChartValuesTextAlign() {\r
+    return mChartValuesTextAlign;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart values text align.\r
+   * \r
+   * @param align the chart values text align\r
+   */\r
+  public void setChartValuesTextAlign(Align align) {\r
+    mChartValuesTextAlign = align;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart values spacing from the data point.\r
+   * \r
+   * @return the chart values spacing\r
+   */\r
+  public float getChartValuesSpacing() {\r
+    return mChartValuesSpacing;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart values spacing from the data point.\r
+   * \r
+   * @param spacing the chart values spacing (in pixels) from the chart data\r
+   *          point\r
+   */\r
+  public void setChartValuesSpacing(float spacing) {\r
+    mChartValuesSpacing = spacing;\r
+  }\r
+\r
+  /**\r
+   * Returns the stroke style.\r
+   * \r
+   * @return the stroke style\r
+   */\r
+  public BasicStroke getStroke() {\r
+    return mStroke;\r
+  }\r
+\r
+  /**\r
+   * Sets the stroke style.\r
+   * \r
+   * @param stroke the stroke style\r
+   */\r
+  public void setStroke(BasicStroke stroke) {\r
+    mStroke = stroke;\r
+  }\r
+\r
+  /**\r
+   * Returns the gradient is enabled value.\r
+   * \r
+   * @return the gradient enabled\r
+   */\r
+  public boolean isGradientEnabled() {\r
+    return mGradientEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the gradient enabled value.\r
+   * \r
+   * @param enabled the gradient enabled\r
+   */\r
+  public void setGradientEnabled(boolean enabled) {\r
+    mGradientEnabled = enabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the gradient start value.\r
+   * \r
+   * @return the gradient start value\r
+   */\r
+  public double getGradientStartValue() {\r
+    return mGradientStartValue;\r
+  }\r
+\r
+  /**\r
+   * Returns the gradient start color.\r
+   * \r
+   * @return the gradient start color\r
+   */\r
+  public int getGradientStartColor() {\r
+    return mGradientStartColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the gradient start value and color.\r
+   * \r
+   * @param start the gradient start value\r
+   * @param color the gradient start color\r
+   */\r
+  public void setGradientStart(double start, int color) {\r
+    mGradientStartValue = start;\r
+    mGradientStartColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the gradient stop value.\r
+   * \r
+   * @return the gradient stop value\r
+   */\r
+  public double getGradientStopValue() {\r
+    return mGradientStopValue;\r
+  }\r
+\r
+  /**\r
+   * Returns the gradient stop color.\r
+   * \r
+   * @return the gradient stop color\r
+   */\r
+  public int getGradientStopColor() {\r
+    return mGradientStopColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the gradient stop value and color.\r
+   * \r
+   * @param start the gradient stop value\r
+   * @param color the gradient stop color\r
+   */\r
+  public void setGradientStop(double start, int color) {\r
+    mGradientStopValue = start;\r
+    mGradientStopColor = color;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/XYMultipleSeriesRenderer.java b/android-libraries/achartengine/src/org/achartengine/renderer/XYMultipleSeriesRenderer.java
new file mode 100644 (file)
index 0000000..64b3421
--- /dev/null
@@ -0,0 +1,1101 @@
+/**\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.renderer;\r
+\r
+import java.util.HashMap;\r
+import java.util.LinkedHashMap;\r
+import java.util.Map;\r
+\r
+import org.achartengine.util.MathHelper;\r
+\r
+import android.graphics.Color;\r
+import android.graphics.Paint.Align;\r
+\r
+/**\r
+ * Multiple XY series renderer.\r
+ */\r
+public class XYMultipleSeriesRenderer extends DefaultRenderer {\r
+  /** The X axis title. */\r
+  private String mXTitle = "";\r
+  /** The Y axis title. */\r
+  private String[] mYTitle;\r
+  /** The axis title text size. */\r
+  private float mAxisTitleTextSize = 12;\r
+  /** The start value in the X axis range. */\r
+  private double[] mMinX;\r
+  /** The end value in the X axis range. */\r
+  private double[] mMaxX;\r
+  /** The start value in the Y axis range. */\r
+  private double[] mMinY;\r
+  /** The end value in the Y axis range. */\r
+  private double[] mMaxY;\r
+  /** The approximative number of labels on the x axis. */\r
+  private int mXLabels = 5;\r
+  /** The approximative number of labels on the y axis. */\r
+  private int mYLabels = 5;\r
+  /** The current orientation of the chart. */\r
+  private Orientation mOrientation = Orientation.HORIZONTAL;\r
+  /** The X axis text labels. */\r
+  private Map<Double, String> mXTextLabels = new HashMap<Double, String>();\r
+  /** The Y axis text labels. */\r
+  private Map<Integer, Map<Double, String>> mYTextLabels = new LinkedHashMap<Integer, Map<Double, String>>();\r
+  /** A flag for enabling or not the pan on the X axis. */\r
+  private boolean mPanXEnabled = true;\r
+  /** A flag for enabling or not the pan on the Y axis. */\r
+  private boolean mPanYEnabled = true;\r
+  /** A flag for enabling or not the zoom on the X axis. */\r
+  private boolean mZoomXEnabled = true;\r
+  /** A flag for enabling or not the zoom on the Y axis . */\r
+  private boolean mZoomYEnabled = true;\r
+  /** The spacing between bars, in bar charts. */\r
+  private double mBarSpacing = 0;\r
+  /** The margins colors. */\r
+  private int mMarginsColor = NO_COLOR;\r
+  /** The pan limits. */\r
+  private double[] mPanLimits;\r
+  /** The zoom limits. */\r
+  private double[] mZoomLimits;\r
+  /** The X axis labels rotation angle. */\r
+  private float mXLabelsAngle;\r
+  /** The Y axis labels rotation angle. */\r
+  private float mYLabelsAngle;\r
+  /** The initial axis range. */\r
+  private Map<Integer, double[]> initialRange = new LinkedHashMap<Integer, double[]>();\r
+  /** The point size for charts displaying points. */\r
+  private float mPointSize = 3;\r
+  /** The grid color. */\r
+  private int mGridColor = Color.argb(75, 200, 200, 200);\r
+  /** The number of scales. */\r
+  private int scalesCount;\r
+  /** The X axis labels alignment. */\r
+  private Align xLabelsAlign = Align.CENTER;\r
+  /** The Y axis labels alignment. */\r
+  private Align[] yLabelsAlign;\r
+  /** The Y axis alignment. */\r
+  private Align[] yAxisAlign;\r
+  /** The X axis labels color. */\r
+  private int mXLabelsColor = TEXT_COLOR;\r
+  /** The Y axis labels color. */\r
+  private int[] mYLabelsColor = new int[] { TEXT_COLOR };\r
+  /**\r
+   * If X axis value selection algorithm to be used. Only used by the time\r
+   * charts.\r
+   */\r
+  private boolean mXRoundedLabels = true;\r
+\r
+  /**\r
+   * An enum for the XY chart orientation of the X axis.\r
+   */\r
+  public enum Orientation {\r
+    HORIZONTAL(0), VERTICAL(90);\r
+    /** The rotate angle. */\r
+    private int mAngle = 0;\r
+\r
+    private Orientation(int angle) {\r
+      mAngle = angle;\r
+    }\r
+\r
+    /**\r
+     * Return the orientation rotate angle.\r
+     * \r
+     * @return the orientaion rotate angle\r
+     */\r
+    public int getAngle() {\r
+      return mAngle;\r
+    }\r
+  }\r
+\r
+  public XYMultipleSeriesRenderer() {\r
+    this(1);\r
+  }\r
+\r
+  public XYMultipleSeriesRenderer(int scaleNumber) {\r
+    scalesCount = scaleNumber;\r
+    initAxesRange(scaleNumber);\r
+  }\r
+\r
+  public void initAxesRange(int scales) {\r
+    mYTitle = new String[scales];\r
+    yLabelsAlign = new Align[scales];\r
+    yAxisAlign = new Align[scales];\r
+    mYLabelsColor = new int[scales];\r
+    mMinX = new double[scales];\r
+    mMaxX = new double[scales];\r
+    mMinY = new double[scales];\r
+    mMaxY = new double[scales];\r
+    for (int i = 0; i < scales; i++) {\r
+      mYLabelsColor[i] = TEXT_COLOR;\r
+      initAxesRangeForScale(i);\r
+    }\r
+  }\r
+\r
+  public void initAxesRangeForScale(int i) {\r
+    mMinX[i] = MathHelper.NULL_VALUE;\r
+    mMaxX[i] = -MathHelper.NULL_VALUE;\r
+    mMinY[i] = MathHelper.NULL_VALUE;\r
+    mMaxY[i] = -MathHelper.NULL_VALUE;\r
+    double[] range = new double[] { mMinX[i], mMaxX[i], mMinY[i], mMaxY[i] };\r
+    initialRange.put(i, range);\r
+    mYTitle[i] = "";\r
+    mYTextLabels.put(i, new HashMap<Double, String>());\r
+    yLabelsAlign[i] = Align.CENTER;\r
+    yAxisAlign[i] = Align.LEFT;\r
+  }\r
+\r
+  /**\r
+   * Returns the current orientation of the chart X axis.\r
+   * \r
+   * @return the chart orientation\r
+   */\r
+  public Orientation getOrientation() {\r
+    return mOrientation;\r
+  }\r
+\r
+  /**\r
+   * Sets the current orientation of the chart X axis.\r
+   * \r
+   * @param orientation the chart orientation\r
+   */\r
+  public void setOrientation(Orientation orientation) {\r
+    mOrientation = orientation;\r
+  }\r
+\r
+  /**\r
+   * Returns the title for the X axis.\r
+   * \r
+   * @return the X axis title\r
+   */\r
+  public String getXTitle() {\r
+    return mXTitle;\r
+  }\r
+\r
+  /**\r
+   * Sets the title for the X axis.\r
+   * \r
+   * @param title the X axis title\r
+   */\r
+  public void setXTitle(String title) {\r
+    mXTitle = title;\r
+  }\r
+\r
+  /**\r
+   * Returns the title for the Y axis.\r
+   * \r
+   * @return the Y axis title\r
+   */\r
+  public String getYTitle() {\r
+    return getYTitle(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the title for the Y axis.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the Y axis title\r
+   */\r
+  public String getYTitle(int scale) {\r
+    return mYTitle[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the title for the Y axis.\r
+   * \r
+   * @param title the Y axis title\r
+   */\r
+  public void setYTitle(String title) {\r
+    setYTitle(title, 0);\r
+  }\r
+\r
+  /**\r
+   * Sets the title for the Y axis.\r
+   * \r
+   * @param title the Y axis title\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setYTitle(String title, int scale) {\r
+    mYTitle[scale] = title;\r
+  }\r
+\r
+  /**\r
+   * Returns the axis title text size.\r
+   * \r
+   * @return the axis title text size\r
+   */\r
+  public float getAxisTitleTextSize() {\r
+    return mAxisTitleTextSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the axis title text size.\r
+   * \r
+   * @param textSize the chart axis text size\r
+   */\r
+  public void setAxisTitleTextSize(float textSize) {\r
+    mAxisTitleTextSize = textSize;\r
+  }\r
+\r
+  /**\r
+   * Returns the start value of the X axis range.\r
+   * \r
+   * @return the X axis range start value\r
+   */\r
+  public double getXAxisMin() {\r
+    return getXAxisMin(0);\r
+  }\r
+\r
+  /**\r
+   * Sets the start value of the X axis range.\r
+   * \r
+   * @param min the X axis range start value\r
+   */\r
+  public void setXAxisMin(double min) {\r
+    setXAxisMin(min, 0);\r
+  }\r
+\r
+  /**\r
+   * Returns if the minimum X value was set.\r
+   * \r
+   * @return the minX was set or not\r
+   */\r
+  public boolean isMinXSet() {\r
+    return isMinXSet(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the end value of the X axis range.\r
+   * \r
+   * @return the X axis range end value\r
+   */\r
+  public double getXAxisMax() {\r
+    return getXAxisMax(0);\r
+  }\r
+\r
+  /**\r
+   * Sets the end value of the X axis range.\r
+   * \r
+   * @param max the X axis range end value\r
+   */\r
+  public void setXAxisMax(double max) {\r
+    setXAxisMax(max, 0);\r
+  }\r
+\r
+  /**\r
+   * Returns if the maximum X value was set.\r
+   * \r
+   * @return the maxX was set or not\r
+   */\r
+  public boolean isMaxXSet() {\r
+    return isMaxXSet(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the start value of the Y axis range.\r
+   * \r
+   * @return the Y axis range end value\r
+   */\r
+  public double getYAxisMin() {\r
+    return getYAxisMin(0);\r
+  }\r
+\r
+  /**\r
+   * Sets the start value of the Y axis range.\r
+   * \r
+   * @param min the Y axis range start value\r
+   */\r
+  public void setYAxisMin(double min) {\r
+    setYAxisMin(min, 0);\r
+  }\r
+\r
+  /**\r
+   * Returns if the minimum Y value was set.\r
+   * \r
+   * @return the minY was set or not\r
+   */\r
+  public boolean isMinYSet() {\r
+    return isMinYSet(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the end value of the Y axis range.\r
+   * \r
+   * @return the Y axis range end value\r
+   */\r
+  public double getYAxisMax() {\r
+    return getYAxisMax(0);\r
+  }\r
+\r
+  /**\r
+   * Sets the end value of the Y axis range.\r
+   * \r
+   * @param max the Y axis range end value\r
+   */\r
+  public void setYAxisMax(double max) {\r
+    setYAxisMax(max, 0);\r
+  }\r
+\r
+  /**\r
+   * Returns if the maximum Y value was set.\r
+   * \r
+   * @return the maxY was set or not\r
+   */\r
+  public boolean isMaxYSet() {\r
+    return isMaxYSet(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the start value of the X axis range.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the X axis range start value\r
+   */\r
+  public double getXAxisMin(int scale) {\r
+    return mMinX[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the start value of the X axis range.\r
+   * \r
+   * @param min the X axis range start value\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setXAxisMin(double min, int scale) {\r
+    if (!isMinXSet(scale)) {\r
+      initialRange.get(scale)[0] = min;\r
+    }\r
+    mMinX[scale] = min;\r
+  }\r
+\r
+  /**\r
+   * Returns if the minimum X value was set.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the minX was set or not\r
+   */\r
+  public boolean isMinXSet(int scale) {\r
+    return mMinX[scale] != MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the end value of the X axis range.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the X axis range end value\r
+   */\r
+  public double getXAxisMax(int scale) {\r
+    return mMaxX[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the end value of the X axis range.\r
+   * \r
+   * @param max the X axis range end value\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setXAxisMax(double max, int scale) {\r
+    if (!isMaxXSet(scale)) {\r
+      initialRange.get(scale)[1] = max;\r
+    }\r
+    mMaxX[scale] = max;\r
+  }\r
+\r
+  /**\r
+   * Returns if the maximum X value was set.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the maxX was set or not\r
+   */\r
+  public boolean isMaxXSet(int scale) {\r
+    return mMaxX[scale] != -MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the start value of the Y axis range.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the Y axis range end value\r
+   */\r
+  public double getYAxisMin(int scale) {\r
+    return mMinY[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the start value of the Y axis range.\r
+   * \r
+   * @param min the Y axis range start value\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setYAxisMin(double min, int scale) {\r
+    if (!isMinYSet(scale)) {\r
+      initialRange.get(scale)[2] = min;\r
+    }\r
+    mMinY[scale] = min;\r
+  }\r
+\r
+  /**\r
+   * Returns if the minimum Y value was set.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the minY was set or not\r
+   */\r
+  public boolean isMinYSet(int scale) {\r
+    return mMinY[scale] != MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the end value of the Y axis range.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the Y axis range end value\r
+   */\r
+  public double getYAxisMax(int scale) {\r
+    return mMaxY[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the end value of the Y axis range.\r
+   * \r
+   * @param max the Y axis range end value\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setYAxisMax(double max, int scale) {\r
+    if (!isMaxYSet(scale)) {\r
+      initialRange.get(scale)[3] = max;\r
+    }\r
+    mMaxY[scale] = max;\r
+  }\r
+\r
+  /**\r
+   * Returns if the maximum Y value was set.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the maxY was set or not\r
+   */\r
+  public boolean isMaxYSet(int scale) {\r
+    return mMaxY[scale] != -MathHelper.NULL_VALUE;\r
+  }\r
+\r
+  /**\r
+   * Returns the approximate number of labels for the X axis.\r
+   * \r
+   * @return the approximate number of labels for the X axis\r
+   */\r
+  public int getXLabels() {\r
+    return mXLabels;\r
+  }\r
+\r
+  /**\r
+   * Sets the approximate number of labels for the X axis.\r
+   * \r
+   * @param xLabels the approximate number of labels for the X axis\r
+   */\r
+  public void setXLabels(int xLabels) {\r
+    mXLabels = xLabels;\r
+  }\r
+\r
+  /**\r
+   * Adds a new text label for the specified X axis value.\r
+   * \r
+   * @param x the X axis value\r
+   * @param text the text label\r
+   * @deprecated use addXTextLabel instead\r
+   */\r
+  public void addTextLabel(double x, String text) {\r
+    addXTextLabel(x, text);\r
+  }\r
+\r
+  /**\r
+   * Adds a new text label for the specified X axis value.\r
+   * \r
+   * @param x the X axis value\r
+   * @param text the text label\r
+   */\r
+  public void addXTextLabel(double x, String text) {\r
+    mXTextLabels.put(x, text);\r
+  }\r
+\r
+  /**\r
+   * Returns the X axis text label at the specified X axis value.\r
+   * \r
+   * @param x the X axis value\r
+   * @return the X axis text label\r
+   */\r
+  public String getXTextLabel(Double x) {\r
+    return mXTextLabels.get(x);\r
+  }\r
+\r
+  /**\r
+   * Returns the X text label locations.\r
+   * \r
+   * @return the X text label locations\r
+   */\r
+  public Double[] getXTextLabelLocations() {\r
+    return mXTextLabels.keySet().toArray(new Double[0]);\r
+  }\r
+\r
+  /**\r
+   * Clears the existing text labels.\r
+   * \r
+   * @deprecated use clearXTextLabels instead\r
+   */\r
+  public void clearTextLabels() {\r
+    clearXTextLabels();\r
+  }\r
+\r
+  /**\r
+   * Clears the existing text labels on the X axis.\r
+   */\r
+  public void clearXTextLabels() {\r
+    mXTextLabels.clear();\r
+  }\r
+\r
+  /**\r
+   * If X axis labels should be rounded.\r
+   * \r
+   * @return if rounded time values to be used\r
+   */\r
+  public boolean isXRoundedLabels() {\r
+    return mXRoundedLabels;\r
+  }\r
+\r
+  /**\r
+   * Sets if X axis rounded time values to be used.\r
+   * \r
+   * @param rounded rounded values to be used\r
+   */\r
+  public void setXRoundedLabels(boolean rounded) {\r
+    mXRoundedLabels = rounded;\r
+  }\r
+\r
+  /**\r
+   * Adds a new text label for the specified Y axis value.\r
+   * \r
+   * @param y the Y axis value\r
+   * @param text the text label\r
+   */\r
+  public void addYTextLabel(double y, String text) {\r
+    addYTextLabel(y, text, 0);\r
+  }\r
+\r
+  /**\r
+   * Adds a new text label for the specified Y axis value.\r
+   * \r
+   * @param y the Y axis value\r
+   * @param text the text label\r
+   * @param scale the renderer scale\r
+   */\r
+  public void addYTextLabel(double y, String text, int scale) {\r
+    mYTextLabels.get(scale).put(y, text);\r
+  }\r
+\r
+  /**\r
+   * Returns the Y axis text label at the specified Y axis value.\r
+   * \r
+   * @param y the Y axis value\r
+   * @return the Y axis text label\r
+   */\r
+  public String getYTextLabel(Double y) {\r
+    return getYTextLabel(y, 0);\r
+  }\r
+\r
+  /**\r
+   * Returns the Y axis text label at the specified Y axis value.\r
+   * \r
+   * @param y the Y axis value\r
+   * @param scale the renderer scale\r
+   * @return the Y axis text label\r
+   */\r
+  public String getYTextLabel(Double y, int scale) {\r
+    return mYTextLabels.get(scale).get(y);\r
+  }\r
+\r
+  /**\r
+   * Returns the Y text label locations.\r
+   * \r
+   * @return the Y text label locations\r
+   */\r
+  public Double[] getYTextLabelLocations() {\r
+    return getYTextLabelLocations(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the Y text label locations.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the Y text label locations\r
+   */\r
+  public Double[] getYTextLabelLocations(int scale) {\r
+    return mYTextLabels.get(scale).keySet().toArray(new Double[0]);\r
+  }\r
+\r
+  /**\r
+   * Clears the existing text labels on the Y axis.\r
+   */\r
+  public void clearYTextLabels() {\r
+    clearYTextLabels(0);\r
+  }\r
+\r
+  /**\r
+   * Clears the existing text labels on the Y axis.\r
+   * \r
+   * @param scale the renderer scale\r
+   */\r
+  public void clearYTextLabels(int scale) {\r
+    mYTextLabels.get(scale).clear();\r
+  }\r
+\r
+  /**\r
+   * Returns the approximate number of labels for the Y axis.\r
+   * \r
+   * @return the approximate number of labels for the Y axis\r
+   */\r
+  public int getYLabels() {\r
+    return mYLabels;\r
+  }\r
+\r
+  /**\r
+   * Sets the approximate number of labels for the Y axis.\r
+   * \r
+   * @param yLabels the approximate number of labels for the Y axis\r
+   */\r
+  public void setYLabels(int yLabels) {\r
+    mYLabels = yLabels;\r
+  }\r
+\r
+  /**\r
+   * Sets if the chart point values should be displayed as text.\r
+   * \r
+   * @param display if the chart point values should be displayed as text\r
+   * @deprecated use SimpleSeriesRenderer.setDisplayChartValues() instead\r
+   */\r
+  public void setDisplayChartValues(boolean display) {\r
+    SimpleSeriesRenderer[] renderers = getSeriesRenderers();\r
+    for (SimpleSeriesRenderer renderer : renderers) {\r
+      renderer.setDisplayChartValues(display);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Sets the chart values text size.\r
+   * \r
+   * @param textSize the chart values text size\r
+   * @deprecated use SimpleSeriesRenderer.setChartValuesTextSize() instead\r
+   */\r
+  public void setChartValuesTextSize(float textSize) {\r
+    SimpleSeriesRenderer[] renderers = getSeriesRenderers();\r
+    for (SimpleSeriesRenderer renderer : renderers) {\r
+      renderer.setChartValuesTextSize(textSize);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the pan on at least one axis.\r
+   * \r
+   * @return if pan is enabled\r
+   */\r
+  public boolean isPanEnabled() {\r
+    return isPanXEnabled() || isPanYEnabled();\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the pan on X axis.\r
+   * \r
+   * @return if pan is enabled on X axis\r
+   */\r
+  public boolean isPanXEnabled() {\r
+    return mPanXEnabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the pan on Y axis.\r
+   * \r
+   * @return if pan is enabled on Y axis\r
+   */\r
+  public boolean isPanYEnabled() {\r
+    return mPanYEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the pan.\r
+   * \r
+   * @param enabledX pan enabled on X axis\r
+   * @param enabledY pan enabled on Y axis\r
+   */\r
+  public void setPanEnabled(boolean enabledX, boolean enabledY) {\r
+    mPanXEnabled = enabledX;\r
+    mPanYEnabled = enabledY;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the zoom on at least one axis.\r
+   * \r
+   * @return if zoom is enabled\r
+   */\r
+  public boolean isZoomEnabled() {\r
+    return isZoomXEnabled() || isZoomYEnabled();\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the zoom on X axis.\r
+   * \r
+   * @return if zoom is enabled on X axis\r
+   */\r
+  public boolean isZoomXEnabled() {\r
+    return mZoomXEnabled;\r
+  }\r
+\r
+  /**\r
+   * Returns the enabled state of the zoom on Y axis.\r
+   * \r
+   * @return if zoom is enabled on Y axis\r
+   */\r
+  public boolean isZoomYEnabled() {\r
+    return mZoomYEnabled;\r
+  }\r
+\r
+  /**\r
+   * Sets the enabled state of the zoom.\r
+   * \r
+   * @param enabledX zoom enabled on X axis\r
+   * @param enabledY zoom enabled on Y axis\r
+   */\r
+  public void setZoomEnabled(boolean enabledX, boolean enabledY) {\r
+    mZoomXEnabled = enabledX;\r
+    mZoomYEnabled = enabledY;\r
+  }\r
+\r
+  /**\r
+   * Returns the spacing between bars, in bar charts.\r
+   * \r
+   * @return the spacing between bars\r
+   * @deprecated use getBarSpacing instead\r
+   */\r
+  public double getBarsSpacing() {\r
+    return getBarSpacing();\r
+  }\r
+\r
+  /**\r
+   * Returns the spacing between bars, in bar charts.\r
+   * \r
+   * @return the spacing between bars\r
+   */\r
+  public double getBarSpacing() {\r
+    return mBarSpacing;\r
+  }\r
+\r
+  /**\r
+   * Sets the spacing between bars, in bar charts. Only available for bar\r
+   * charts. This is a coefficient of the bar width. For instance, if you want\r
+   * the spacing to be a half of the bar width, set this value to 0.5.\r
+   * \r
+   * @param spacing the spacing between bars coefficient\r
+   */\r
+  public void setBarSpacing(double spacing) {\r
+    mBarSpacing = spacing;\r
+  }\r
+\r
+  /**\r
+   * Returns the margins color.\r
+   * \r
+   * @return the margins color\r
+   */\r
+  public int getMarginsColor() {\r
+    return mMarginsColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the color of the margins.\r
+   * \r
+   * @param color the margins color\r
+   */\r
+  public void setMarginsColor(int color) {\r
+    mMarginsColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the grid color.\r
+   * \r
+   * @return the grid color\r
+   */\r
+  public int getGridColor() {\r
+    return mGridColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the color of the grid.\r
+   * \r
+   * @param color the grid color\r
+   */\r
+  public void setGridColor(int color) {\r
+    mGridColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the pan limits.\r
+   * \r
+   * @return the pan limits\r
+   */\r
+  public double[] getPanLimits() {\r
+    return mPanLimits;\r
+  }\r
+\r
+  /**\r
+   * Sets the pan limits as an array of 4 values. Setting it to null or a\r
+   * different size array will disable the panning limitation. Values:\r
+   * [panMinimumX, panMaximumX, panMinimumY, panMaximumY]\r
+   * \r
+   * @param panLimits the pan limits\r
+   */\r
+  public void setPanLimits(double[] panLimits) {\r
+    mPanLimits = panLimits;\r
+  }\r
+\r
+  /**\r
+   * Returns the zoom limits.\r
+   * \r
+   * @return the zoom limits\r
+   */\r
+  public double[] getZoomLimits() {\r
+    return mZoomLimits;\r
+  }\r
+\r
+  /**\r
+   * Sets the zoom limits as an array of 4 values. Setting it to null or a\r
+   * different size array will disable the zooming limitation. Values:\r
+   * [zoomMinimumX, zoomMaximumX, zoomMinimumY, zoomMaximumY]\r
+   * \r
+   * @param zoomLimits the zoom limits\r
+   */\r
+  public void setZoomLimits(double[] zoomLimits) {\r
+    mZoomLimits = zoomLimits;\r
+  }\r
+\r
+  /**\r
+   * Returns the rotation angle of labels for the X axis.\r
+   * \r
+   * @return the rotation angle of labels for the X axis\r
+   */\r
+  public float getXLabelsAngle() {\r
+    return mXLabelsAngle;\r
+  }\r
+\r
+  /**\r
+   * Sets the rotation angle (in degrees) of labels for the X axis.\r
+   * \r
+   * @param angle the rotation angle of labels for the X axis\r
+   */\r
+  public void setXLabelsAngle(float angle) {\r
+    mXLabelsAngle = angle;\r
+  }\r
+\r
+  /**\r
+   * Returns the rotation angle of labels for the Y axis.\r
+   * \r
+   * @return the approximate number of labels for the Y axis\r
+   */\r
+  public float getYLabelsAngle() {\r
+    return mYLabelsAngle;\r
+  }\r
+\r
+  /**\r
+   * Sets the rotation angle (in degrees) of labels for the Y axis.\r
+   * \r
+   * @param angle the rotation angle of labels for the Y axis\r
+   */\r
+  public void setYLabelsAngle(float angle) {\r
+    mYLabelsAngle = angle;\r
+  }\r
+\r
+  /**\r
+   * Returns the size of the points, for charts displaying points.\r
+   * \r
+   * @return the point size\r
+   */\r
+  public float getPointSize() {\r
+    return mPointSize;\r
+  }\r
+\r
+  /**\r
+   * Sets the size of the points, for charts displaying points.\r
+   * \r
+   * @param size the point size\r
+   */\r
+  public void setPointSize(float size) {\r
+    mPointSize = size;\r
+  }\r
+\r
+  public void setRange(double[] range) {\r
+    setRange(range, 0);\r
+  }\r
+\r
+  /**\r
+   * Sets the axes range values.\r
+   * \r
+   * @param range an array having the values in this order: minX, maxX, minY,\r
+   *          maxY\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setRange(double[] range, int scale) {\r
+    setXAxisMin(range[0], scale);\r
+    setXAxisMax(range[1], scale);\r
+    setYAxisMin(range[2], scale);\r
+    setYAxisMax(range[3], scale);\r
+  }\r
+\r
+  public boolean isInitialRangeSet() {\r
+    return isInitialRangeSet(0);\r
+  }\r
+\r
+  /**\r
+   * Returns if the initial range is set.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the initial range was set or not\r
+   */\r
+  public boolean isInitialRangeSet(int scale) {\r
+    return initialRange.get(scale) != null;\r
+  }\r
+\r
+  /**\r
+   * Returns the initial range.\r
+   * \r
+   * @return the initial range\r
+   */\r
+  public double[] getInitialRange() {\r
+    return getInitialRange(0);\r
+  }\r
+\r
+  /**\r
+   * Returns the initial range.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return the initial range\r
+   */\r
+  public double[] getInitialRange(int scale) {\r
+    return initialRange.get(scale);\r
+  }\r
+\r
+  /**\r
+   * Sets the axes initial range values. This will be used in the zoom fit tool.\r
+   * \r
+   * @param range an array having the values in this order: minX, maxX, minY,\r
+   *          maxY\r
+   */\r
+  public void setInitialRange(double[] range) {\r
+    setInitialRange(range, 0);\r
+  }\r
+\r
+  /**\r
+   * Sets the axes initial range values. This will be used in the zoom fit tool.\r
+   * \r
+   * @param range an array having the values in this order: minX, maxX, minY,\r
+   *          maxY\r
+   * @param scale the renderer scale\r
+   */\r
+  public void setInitialRange(double[] range, int scale) {\r
+    initialRange.put(scale, range);\r
+  }\r
+\r
+  /**\r
+   * Returns the X axis labels color.\r
+   * \r
+   * @return the X axis labels color\r
+   */\r
+  public int getXLabelsColor() {\r
+    return mXLabelsColor;\r
+  }\r
+\r
+  /**\r
+   * Returns the Y axis labels color.\r
+   * \r
+   * @return the Y axis labels color\r
+   */\r
+  public int getYLabelsColor(int scale) {\r
+    return mYLabelsColor[scale];\r
+  }\r
+\r
+  /**\r
+   * Sets the X axis labels color.\r
+   * \r
+   * @param color the X axis labels color\r
+   */\r
+  public void setXLabelsColor(int color) {\r
+    mXLabelsColor = color;\r
+  }\r
+\r
+  /**\r
+   * Sets the Y axis labels color.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @param color the Y axis labels color\r
+   */\r
+  public void setYLabelsColor(int scale, int color) {\r
+    mYLabelsColor[scale] = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the X axis labels alignment.\r
+   * \r
+   * @return X labels alignment\r
+   */\r
+  public Align getXLabelsAlign() {\r
+    return xLabelsAlign;\r
+  }\r
+\r
+  /**\r
+   * Sets the X axis labels alignment.\r
+   * \r
+   * @param align the X labels alignment\r
+   */\r
+  public void setXLabelsAlign(Align align) {\r
+    xLabelsAlign = align;\r
+  }\r
+\r
+  /**\r
+   * Returns the Y axis labels alignment.\r
+   * \r
+   * @param scale the renderer scale\r
+   * @return Y labels alignment\r
+   */\r
+  public Align getYLabelsAlign(int scale) {\r
+    return yLabelsAlign[scale];\r
+  }\r
+\r
+  public void setYLabelsAlign(Align align) {\r
+    setYLabelsAlign(align, 0);\r
+  }\r
+\r
+  public Align getYAxisAlign(int scale) {\r
+    return yAxisAlign[scale];\r
+  }\r
+\r
+  public void setYAxisAlign(Align align, int scale) {\r
+    yAxisAlign[scale] = align;\r
+  }\r
+\r
+  /**\r
+   * Sets the Y axis labels alignment.\r
+   * \r
+   * @param align the Y labels alignment\r
+   */\r
+  public void setYLabelsAlign(Align align, int scale) {\r
+    yLabelsAlign[scale] = align;\r
+  }\r
+\r
+  public int getScalesCount() {\r
+    return scalesCount;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/XYSeriesRenderer.java b/android-libraries/achartengine/src/org/achartengine/renderer/XYSeriesRenderer.java
new file mode 100644 (file)
index 0000000..42e4808
--- /dev/null
@@ -0,0 +1,128 @@
+/**\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.renderer;\r
+\r
+import org.achartengine.chart.PointStyle;\r
+\r
+import android.graphics.Color;\r
+\r
+/**\r
+ * A renderer for the XY type series.\r
+ */\r
+public class XYSeriesRenderer extends SimpleSeriesRenderer {\r
+  /** If the chart points should be filled. */\r
+  private boolean mFillPoints = false;\r
+  /** If the chart should be filled below its line. */\r
+  private boolean mFillBelowLine = false;\r
+  /** The fill below the chart line color. */\r
+  private int mFillColor = Color.argb(125, 0, 0, 200);\r
+  /** The point style. */\r
+  private PointStyle mPointStyle = PointStyle.POINT;\r
+  /** The chart line width. */\r
+  private float mLineWidth = 1;\r
+\r
+  /**\r
+   * Returns if the chart should be filled below the line.\r
+   * \r
+   * @return the fill below line status\r
+   */\r
+  public boolean isFillBelowLine() {\r
+    return mFillBelowLine;\r
+  }\r
+\r
+  /**\r
+   * Sets if the line chart should be filled below its line. Filling below the\r
+   * line transforms a line chart into an area chart.\r
+   * \r
+   * @param fill the fill below line flag value\r
+   */\r
+  public void setFillBelowLine(boolean fill) {\r
+    mFillBelowLine = fill;\r
+  }\r
+\r
+  /**\r
+   * Returns if the chart points should be filled.\r
+   * \r
+   * @return the points fill status\r
+   */\r
+  public boolean isFillPoints() {\r
+    return mFillPoints;\r
+  }\r
+\r
+  /**\r
+   * Sets if the chart points should be filled.\r
+   * \r
+   * @param fill the points fill flag value\r
+   */\r
+  public void setFillPoints(boolean fill) {\r
+    mFillPoints = fill;\r
+  }\r
+\r
+  /**\r
+   * Returns the fill below line color.\r
+   * \r
+   * @return the fill below line color\r
+   */\r
+  public int getFillBelowLineColor() {\r
+    return mFillColor;\r
+  }\r
+\r
+  /**\r
+   * Sets the fill below the line color.\r
+   * \r
+   * @param color the fill below line color\r
+   */\r
+  public void setFillBelowLineColor(int color) {\r
+    mFillColor = color;\r
+  }\r
+\r
+  /**\r
+   * Returns the point style.\r
+   * \r
+   * @return the point style\r
+   */\r
+  public PointStyle getPointStyle() {\r
+    return mPointStyle;\r
+  }\r
+\r
+  /**\r
+   * Sets the point style.\r
+   * \r
+   * @param style the point style\r
+   */\r
+  public void setPointStyle(PointStyle style) {\r
+    mPointStyle = style;\r
+  }\r
+\r
+  /**\r
+   * Returns the chart line width.\r
+   * \r
+   * @return the line width\r
+   */\r
+  public float getLineWidth() {\r
+    return mLineWidth;\r
+  }\r
+\r
+  /**\r
+   * Sets the chart line width.\r
+   * \r
+   * @param lineWidth the line width\r
+   */\r
+  public void setLineWidth(float lineWidth) {\r
+    mLineWidth = lineWidth;\r
+  }\r
+  \r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/renderer/package.html b/android-libraries/achartengine/src/org/achartengine/renderer/package.html
new file mode 100644 (file)
index 0000000..c9db0a4
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<title>AChartEngine</title>\r
+<body>\r
+Provides renderer classes that keep the chart rendering / drawing styles.\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/AbstractTool.java b/android-libraries/achartengine/src/org/achartengine/tools/AbstractTool.java
new file mode 100644 (file)
index 0000000..99841ed
--- /dev/null
@@ -0,0 +1,111 @@
+/**\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.tools;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.renderer.XYMultipleSeriesRenderer;\r
+\r
+/**\r
+ * Abstract class for being extended by graphical view tools.\r
+ */\r
+public abstract class AbstractTool {\r
+  /** The chart. */\r
+  protected AbstractChart mChart;\r
+  /** The renderer. */\r
+  protected XYMultipleSeriesRenderer mRenderer;\r
+\r
+  /**\r
+   * Abstract tool constructor.\r
+   * \r
+   * @param chart the chart\r
+   */\r
+  public AbstractTool(AbstractChart chart) {\r
+    mChart = chart;\r
+    if (chart instanceof XYChart) {\r
+      mRenderer = ((XYChart) chart).getRenderer();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Returns the current chart range.\r
+   * \r
+   * @param scale the scale\r
+   * @return the chart range\r
+   */\r
+  public double[] getRange(int scale) {\r
+    double minX = mRenderer.getXAxisMin(scale);\r
+    double maxX = mRenderer.getXAxisMax(scale);\r
+    double minY = mRenderer.getYAxisMin(scale);\r
+    double maxY = mRenderer.getYAxisMax(scale);\r
+    return new double[] { minX, maxX, minY, maxY };\r
+  }\r
+\r
+  /**\r
+   * Sets the range to the calculated one, if not already set.\r
+   * \r
+   * @param range the range\r
+   * @param scale the scale\r
+   */\r
+  public void checkRange(double[] range, int scale) {\r
+    if (mChart instanceof XYChart) {\r
+      double[] calcRange = ((XYChart) mChart).getCalcRange(scale);\r
+      if (calcRange != null) {\r
+        if (!mRenderer.isMinXSet(scale)) {\r
+          range[0] = calcRange[0];\r
+          mRenderer.setXAxisMin(range[0], scale);\r
+        }\r
+        if (!mRenderer.isMaxXSet(scale)) {\r
+          range[1] = calcRange[1];\r
+          mRenderer.setXAxisMax(range[1], scale);\r
+        }\r
+        if (!mRenderer.isMinYSet(scale)) {\r
+          range[2] = calcRange[2];\r
+          mRenderer.setYAxisMin(range[2], scale);\r
+        }\r
+        if (!mRenderer.isMaxYSet(scale)) {\r
+          range[3] = calcRange[3];\r
+          mRenderer.setYAxisMax(range[3], scale);\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Sets a new range on the X axis.\r
+   * \r
+   * @param min the minimum value\r
+   * @param max the maximum value\r
+   * @param scale the scale\r
+   */\r
+  protected void setXRange(double min, double max, int scale) {\r
+    mRenderer.setXAxisMin(min, scale);\r
+    mRenderer.setXAxisMax(max, scale);\r
+  }\r
+\r
+  /**\r
+   * Sets a new range on the Y axis.\r
+   * \r
+   * @param min the minimum value\r
+   * @param max the maximum value\r
+   * @param scale the scale\r
+   */\r
+  protected void setYRange(double min, double max, int scale) {\r
+    mRenderer.setYAxisMin(min, scale);\r
+    mRenderer.setYAxisMax(max, scale);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/FitZoom.java b/android-libraries/achartengine/src/org/achartengine/tools/FitZoom.java
new file mode 100644 (file)
index 0000000..92f67b8
--- /dev/null
@@ -0,0 +1,78 @@
+/**\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.tools;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.model.XYSeries;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+import org.achartengine.util.MathHelper;\r
+\r
+public class FitZoom extends AbstractTool {\r
+  /**\r
+   * Builds an instance of the fit zoom tool.\r
+   * \r
+   * @param chart the XY chart\r
+   */\r
+  public FitZoom(AbstractChart chart) {\r
+    super(chart);\r
+  }\r
+\r
+  /**\r
+   * Apply the tool.\r
+   */\r
+  public void apply() {\r
+    if (mChart instanceof XYChart) {\r
+      if (((XYChart) mChart).getDataset() == null) {\r
+        return;\r
+      }\r
+      int scales = mRenderer.getScalesCount();\r
+      if (mRenderer.isInitialRangeSet()) {\r
+        for (int i = 0; i < scales; i++) {\r
+          if (mRenderer.isInitialRangeSet(i)) {\r
+            mRenderer.setRange(mRenderer.getInitialRange(i), i);\r
+          }\r
+        }\r
+      } else {\r
+        XYSeries[] series = ((XYChart) mChart).getDataset().getSeries();\r
+        double[] range = null;\r
+        int length = series.length;\r
+        if (length > 0) {\r
+          for (int i = 0; i < scales; i++) {\r
+            range = new double[] { MathHelper.NULL_VALUE, -MathHelper.NULL_VALUE,\r
+                MathHelper.NULL_VALUE, -MathHelper.NULL_VALUE };\r
+            for (int j = 0; j < length; j++) {\r
+              if (i == series[j].getScaleNumber()) {\r
+                range[0] = Math.min(range[0], series[j].getMinX());\r
+                range[1] = Math.max(range[1], series[j].getMaxX());\r
+                range[2] = Math.min(range[2], series[j].getMinY());\r
+                range[3] = Math.max(range[3], series[j].getMaxY());\r
+              }\r
+            }\r
+            double marginX = Math.abs(range[1] - range[0]) / 40;\r
+            double marginY = Math.abs(range[3] - range[2]) / 40;\r
+            mRenderer.setRange(new double[] { range[0] - marginX, range[1] + marginX,\r
+                range[2] - marginY, range[3] + marginY }, i);\r
+          }\r
+        }\r
+      }\r
+    } else {\r
+      DefaultRenderer renderer = ((RoundChart) mChart).getRenderer();\r
+      renderer.setScale(renderer.getOriginalScale());\r
+    }\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/Pan.java b/android-libraries/achartengine/src/org/achartengine/tools/Pan.java
new file mode 100644 (file)
index 0000000..2d4ea28
--- /dev/null
@@ -0,0 +1,163 @@
+/**\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.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+\r
+/**\r
+ * The pan tool.\r
+ */\r
+public class Pan extends AbstractTool {\r
+  /** The pan listeners. */\r
+  private List<PanListener> mPanListeners = new ArrayList<PanListener>();\r
+  /** Pan limits reached on the X axis. */\r
+  private boolean limitsReachedX = false;\r
+  /** Pan limits reached on the X axis. */\r
+  private boolean limitsReachedY = false;\r
+\r
+  /**\r
+   * Builds and instance of the pan tool.\r
+   * \r
+   * @param chart the XY chart\r
+   */\r
+  public Pan(AbstractChart chart) {\r
+    super(chart);\r
+  }\r
+\r
+  /**\r
+   * Apply the tool.\r
+   * \r
+   * @param oldX the previous location on X axis\r
+   * @param oldY the previous location on Y axis\r
+   * @param newX the current location on X axis\r
+   * @param newY the current location on the Y axis\r
+   */\r
+  public void apply(float oldX, float oldY, float newX, float newY) {\r
+    boolean notLimitedUp = true;\r
+    boolean notLimitedBottom = true;\r
+    boolean notLimitedLeft = true;\r
+    boolean notLimitedRight = true;\r
+    if (mChart instanceof XYChart) {\r
+      int scales = mRenderer.getScalesCount();\r
+      double[] limits = mRenderer.getPanLimits();\r
+      boolean limited = limits != null && limits.length == 4;\r
+      XYChart chart = (XYChart) mChart;\r
+      for (int i = 0; i < scales; i++) {\r
+        double[] range = getRange(i);\r
+        double[] calcRange = chart.getCalcRange(i);\r
+        if (limitsReachedX\r
+            && limitsReachedY\r
+            && (range[0] == range[1] && calcRange[0] == calcRange[1] || range[2] == range[3]\r
+                && calcRange[2] == calcRange[3])) {\r
+          return;\r
+        }\r
+        checkRange(range, i);\r
+\r
+        double[] realPoint = chart.toRealPoint(oldX, oldY, i);\r
+        double[] realPoint2 = chart.toRealPoint(newX, newY, i);\r
+        double deltaX = realPoint[0] - realPoint2[0];\r
+        double deltaY = realPoint[1] - realPoint2[1];\r
+        double ratio = getAxisRatio(range);\r
+        if (chart.isVertical(mRenderer)) {\r
+          double newDeltaX = -deltaY * ratio;\r
+          double newDeltaY = deltaX / ratio;\r
+          deltaX = newDeltaX;\r
+          deltaY = newDeltaY;\r
+        }\r
+        if (mRenderer.isPanXEnabled()) {\r
+          if (limits != null) {\r
+            if (notLimitedLeft) {\r
+              notLimitedLeft = limits[0] <= range[0] + deltaX;\r
+            }\r
+            if (notLimitedRight) {\r
+              notLimitedRight = limits[1] >= range[1] + deltaX;\r
+            }\r
+          }\r
+          if (!limited || (notLimitedLeft && notLimitedRight)) {\r
+            setXRange(range[0] + deltaX, range[1] + deltaX, i);\r
+            limitsReachedX = false;\r
+          } else {\r
+            limitsReachedX = true;\r
+          }\r
+        }\r
+        if (mRenderer.isPanYEnabled()) {\r
+          if (limits != null) {\r
+            if (notLimitedBottom) {\r
+              notLimitedBottom = limits[2] <= range[2] + deltaY;\r
+            }\r
+            if (notLimitedUp) {\r
+              notLimitedUp = limits[3] >= range[3] + deltaY;\r
+            }\r
+          }\r
+          if (!limited || (notLimitedBottom && notLimitedUp)) {\r
+            setYRange(range[2] + deltaY, range[3] + deltaY, i);\r
+            limitsReachedY = false;\r
+          } else {\r
+            limitsReachedY = true;\r
+          }\r
+        }\r
+      }\r
+    } else {\r
+      RoundChart chart = (RoundChart) mChart;\r
+      chart.setCenterX(chart.getCenterX() + (int) (newX - oldX));\r
+      chart.setCenterY(chart.getCenterY() + (int) (newY - oldY));\r
+    }\r
+    notifyPanListeners();\r
+  }\r
+\r
+  /**\r
+   * Return the X / Y axis range ratio.\r
+   * \r
+   * @param range the axis range\r
+   * @return the ratio\r
+   */\r
+  private double getAxisRatio(double[] range) {\r
+    return Math.abs(range[1] - range[0]) / Math.abs(range[3] - range[2]);\r
+  }\r
+\r
+  /**\r
+   * Notify the pan listeners about a pan.\r
+   */\r
+  private synchronized void notifyPanListeners() {\r
+    for (PanListener listener : mPanListeners) {\r
+      listener.panApplied();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Adds a new pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public synchronized void addPanListener(PanListener listener) {\r
+    mPanListeners.add(listener);\r
+  }\r
+\r
+  /**\r
+   * Removes a pan listener.\r
+   * \r
+   * @param listener pan listener\r
+   */\r
+  public synchronized void removePanListener(PanListener listener) {\r
+    mPanListeners.add(listener);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/PanListener.java b/android-libraries/achartengine/src/org/achartengine/tools/PanListener.java
new file mode 100644 (file)
index 0000000..d3d136c
--- /dev/null
@@ -0,0 +1,28 @@
+/**\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.tools;\r
+\r
+/**\r
+ * A pan listener.\r
+ */\r
+public interface PanListener {\r
+\r
+  /**\r
+   * Called when a pan change is triggered.\r
+   */\r
+  void panApplied();\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/Zoom.java b/android-libraries/achartengine/src/org/achartengine/tools/Zoom.java
new file mode 100644 (file)
index 0000000..0abee92
--- /dev/null
@@ -0,0 +1,189 @@
+/**\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.tools;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.achartengine.chart.AbstractChart;\r
+import org.achartengine.chart.RoundChart;\r
+import org.achartengine.chart.XYChart;\r
+import org.achartengine.renderer.DefaultRenderer;\r
+\r
+/**\r
+ * The zoom tool.\r
+ */\r
+public class Zoom extends AbstractTool {\r
+  /** A flag to be used to know if this is a zoom in or out. */\r
+  private boolean mZoomIn;\r
+  /** The zoom rate. */\r
+  private float mZoomRate;\r
+  /** The zoom listeners. */\r
+  private List<ZoomListener> mZoomListeners = new ArrayList<ZoomListener>();\r
+  /** Zoom limits reached on the X axis. */\r
+  private boolean limitsReachedX = false;\r
+  /** Zoom limits reached on the Y axis. */\r
+  private boolean limitsReachedY = false;\r
+\r
+  /** Zoom on X axis and Y axis */\r
+  public static final int ZOOM_AXIS_XY = 0;\r
+  /** Zoom on X axis independently */\r
+  public static final int ZOOM_AXIS_X = 1;\r
+  /** Zoom on Y axis independently */\r
+  public static final int ZOOM_AXIS_Y = 2;\r
+\r
+\r
+  /**\r
+   * Builds the zoom tool.\r
+   * \r
+   * @param chart the chart\r
+   * @param in zoom in or out\r
+   * @param rate the zoom rate\r
+   */\r
+  public Zoom(AbstractChart chart, boolean in, float rate) {\r
+    super(chart);\r
+    mZoomIn = in;\r
+    setZoomRate(rate);\r
+  }\r
+\r
+  /**\r
+   * Sets the zoom rate.\r
+   * \r
+   * @param rate\r
+   */\r
+  public void setZoomRate(float rate) {\r
+    mZoomRate = rate;\r
+  }\r
+\r
+  /**\r
+   * Apply the zoom.\r
+   */\r
+  public void apply(int zoom_axis) {\r
+    if (mChart instanceof XYChart) {\r
+      int scales = mRenderer.getScalesCount();\r
+      for (int i = 0; i < scales; i++) {\r
+        double[] range = getRange(i);\r
+        checkRange(range, i);\r
+        double[] limits = mRenderer.getZoomLimits();\r
+\r
+        double centerX = (range[0] + range[1]) / 2;\r
+        double centerY = (range[2] + range[3]) / 2;\r
+        double newWidth = range[1] - range[0];\r
+        double newHeight = range[3] - range[2];\r
+        double newXMin = centerX - newWidth / 2;\r
+        double newXMax = centerX + newWidth / 2;\r
+        double newYMin = centerY - newHeight / 2;\r
+        double newYMax = centerY + newHeight / 2;\r
+\r
+        // if already reached last zoom, then it will always set to reached\r
+        if (i == 0) {\r
+          limitsReachedX = limits != null && (newXMin <= limits[0] || newXMax >= limits[1]);\r
+          limitsReachedY = limits != null && (newYMin <= limits[2] || newYMax >= limits[3]);\r
+        }\r
+\r
+        if (mZoomIn) {\r
+          if (mRenderer.isZoomXEnabled() &&     // zoom in on X axis\r
+              (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+            if (limitsReachedX && mZoomRate < 1) {     \r
+              // ignore pinch zoom out once reached X limit\r
+            } else {\r
+              newWidth /= mZoomRate;\r
+            }\r
+          }\r
+\r
+          if (mRenderer.isZoomYEnabled() && // zoom in on Y axis\r
+              (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+            if (limitsReachedY && mZoomRate < 1) {\r
+            } else {\r
+              newHeight /= mZoomRate;\r
+            }\r
+          }\r
+        } else {\r
+          if (mRenderer.isZoomXEnabled() &&     !limitsReachedX &&         // zoom out on X axis\r
+              (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+            newWidth *= mZoomRate;\r
+          }\r
+\r
+          if (mRenderer.isZoomYEnabled() &&     !limitsReachedY &&     // zoom out on Y axis\r
+              (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+            newHeight *= mZoomRate;\r
+          }\r
+        }\r
+\r
+        if (mRenderer.isZoomXEnabled() && \r
+            (zoom_axis == ZOOM_AXIS_X || zoom_axis == ZOOM_AXIS_XY)) {\r
+          newXMin = centerX - newWidth / 2;\r
+          newXMax = centerX + newWidth / 2;\r
+          setXRange(newXMin, newXMax, i);\r
+        }\r
+        if (mRenderer.isZoomYEnabled() &&\r
+            (zoom_axis == ZOOM_AXIS_Y || zoom_axis == ZOOM_AXIS_XY)) {\r
+          newYMin = centerY - newHeight / 2;\r
+          newYMax = centerY + newHeight / 2;\r
+          setYRange(newYMin, newYMax, i);\r
+        }\r
+      }\r
+    } else {\r
+      DefaultRenderer renderer = ((RoundChart) mChart).getRenderer();\r
+      if (mZoomIn) {\r
+        renderer.setScale(renderer.getScale() * mZoomRate);\r
+      } else {\r
+        renderer.setScale(renderer.getScale() / mZoomRate);\r
+      }\r
+    }\r
+    notifyZoomListeners(new ZoomEvent(mZoomIn, mZoomRate));\r
+  }\r
+\r
+\r
+  /**\r
+   * Notify the zoom listeners about a zoom change.\r
+   * \r
+   * @param e the zoom event\r
+   */\r
+  private synchronized void notifyZoomListeners(ZoomEvent e) {\r
+    for (ZoomListener listener : mZoomListeners) {\r
+      listener.zoomApplied(e);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Notify the zoom listeners about a zoom reset.\r
+   */\r
+  public synchronized void notifyZoomResetListeners() {\r
+    for (ZoomListener listener : mZoomListeners) {\r
+      listener.zoomReset();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Adds a new zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public synchronized void addZoomListener(ZoomListener listener) {\r
+    mZoomListeners.add(listener);\r
+  }\r
+\r
+  /**\r
+   * Removes a zoom listener.\r
+   * \r
+   * @param listener zoom listener\r
+   */\r
+  public synchronized void removeZoomListener(ZoomListener listener) {\r
+    mZoomListeners.add(listener);\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/ZoomEvent.java b/android-libraries/achartengine/src/org/achartengine/tools/ZoomEvent.java
new file mode 100644 (file)
index 0000000..bd8fb68
--- /dev/null
@@ -0,0 +1,56 @@
+/**\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.tools;\r
+\r
+\r
+/**\r
+ * A zoom event.\r
+ */\r
+public class ZoomEvent {\r
+  /** A flag to be used to know if this is a zoom in or out. */\r
+  private boolean mZoomIn;\r
+  /** The zoom rate. */\r
+  private float mZoomRate;\r
+\r
+  /**\r
+   * Builds the zoom tool.\r
+   * \r
+   * @param in zoom in or out\r
+   * @param rate the zoom rate\r
+   */\r
+  public ZoomEvent(boolean in, float rate) {\r
+    mZoomIn = in;\r
+    mZoomRate = rate;\r
+  }\r
+\r
+  /**\r
+   * Returns the zoom type.\r
+   * \r
+   * @return true if zoom in, false otherwise\r
+   */\r
+  public boolean isZoomIn() {\r
+    return mZoomIn;\r
+  }\r
+  \r
+  /**\r
+   * Returns the zoom rate.\r
+   * \r
+   * @return the zoom rate\r
+   */\r
+  public float getZoomRate() {\r
+    return mZoomRate;\r
+  }\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/tools/ZoomListener.java b/android-libraries/achartengine/src/org/achartengine/tools/ZoomListener.java
new file mode 100644 (file)
index 0000000..4827483
--- /dev/null
@@ -0,0 +1,33 @@
+/**\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.tools;\r
+\r
+/**\r
+ * A zoom listener.\r
+ */\r
+public interface ZoomListener {\r
+  \r
+  /**\r
+   * Called when a zoom change is triggered.\r
+   * @param e the zoom event\r
+   */\r
+  void zoomApplied(ZoomEvent e);\r
+  \r
+  /**\r
+   * Called when a zoom reset is done.\r
+   */\r
+  void zoomReset();\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/util/IndexXYMap.java b/android-libraries/achartengine/src/org/achartengine/util/IndexXYMap.java
new file mode 100644 (file)
index 0000000..f957262
--- /dev/null
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.util;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.TreeMap;
+
+/**
+ * This class requires sorted x values
+ */
+public class IndexXYMap<K, V> extends TreeMap<K, V> {
+  private final List<K> indexList = new ArrayList<K>();
+
+  private double maxXDifference = 0;
+
+  public IndexXYMap() {
+    super();
+  }
+
+  public V put(K key, V value) {
+    indexList.add(key);
+    updateMaxXDifference();
+    return super.put(key, value);
+  }
+
+  private void updateMaxXDifference() {
+    if (indexList.size() < 2) {
+      maxXDifference = 0;
+      return;
+    }
+
+    if (Math.abs((Double) indexList.get(indexList.size() - 1)
+        - (Double) indexList.get(indexList.size() - 2)) > maxXDifference)
+      maxXDifference = Math.abs((Double) indexList.get(indexList.size() - 1)
+          - (Double) indexList.get(indexList.size() - 2));
+  }
+
+  public double getMaxXDifference() {
+    return maxXDifference;
+  }
+
+  public void clear() {
+    updateMaxXDifference();
+    super.clear();
+    indexList.clear();
+  }
+
+  /**
+   * Returns X-value according to the given index
+   * 
+   * @param index
+   * @return the X value
+   */
+  public K getXByIndex(int index) {
+    return indexList.get(index);
+  }
+
+  /**
+   * Returns Y-value according to the given index
+   * 
+   * @param index
+   * @return the Y value
+   */
+  public V getYByIndex(int index) {
+    K key = indexList.get(index);
+    return this.get(key);
+  }
+
+  /**
+   * Returns XY-entry according to the given index
+   * 
+   * @param index
+   * @return the X and Y values
+   */
+  public XYEntry<K, V> getByIndex(int index) {
+    K key = indexList.get(index);
+    return new XYEntry<K, V>(key, this.get(key));
+  }
+
+  /**
+   * Removes entry from map by index
+   * 
+   * @param index
+   */
+  public XYEntry<K, V> removeByIndex(int index) {
+    K key = indexList.remove(index);
+    return new XYEntry<K, V>(key, this.remove(key));
+  }
+
+  public int getIndexForKey(K key) {
+    return Collections.binarySearch(indexList, key, null);
+  }
+}
diff --git a/android-libraries/achartengine/src/org/achartengine/util/MathHelper.java b/android-libraries/achartengine/src/org/achartengine/util/MathHelper.java
new file mode 100644 (file)
index 0000000..f5b893b
--- /dev/null
@@ -0,0 +1,174 @@
+/**\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.util;\r
+\r
+import java.text.NumberFormat;\r
+import java.text.ParseException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+/**\r
+ * Utility class for math operations.\r
+ */\r
+public class MathHelper {\r
+  /** A value that is used a null value. */\r
+  public static final double NULL_VALUE = Double.MAX_VALUE;\r
+  /**\r
+   * A number formatter to be used to make sure we have a maximum number of\r
+   * fraction digits in the labels.\r
+   */\r
+  private static final NumberFormat FORMAT = NumberFormat.getNumberInstance();\r
+\r
+  private MathHelper() {\r
+    // empty constructor\r
+  }\r
+\r
+  /**\r
+   * Calculate the minimum and maximum values out of a list of doubles.\r
+   * \r
+   * @param values the input values\r
+   * @return an array with the minimum and maximum values\r
+   */\r
+  public static double[] minmax(List<Double> values) {\r
+    if (values.size() == 0) {\r
+      return new double[2];\r
+    }\r
+    double min = values.get(0);\r
+    double max = min;\r
+    int length = values.size();\r
+    for (int i = 1; i < length; i++) {\r
+      double value = values.get(i);\r
+      min = Math.min(min, value);\r
+      max = Math.max(max, value);\r
+    }\r
+    return new double[] { min, max };\r
+  }\r
+\r
+  /**\r
+   * Computes a reasonable set of labels for a data interval and number of\r
+   * labels.\r
+   * \r
+   * @param start start value\r
+   * @param end final value\r
+   * @param approxNumLabels desired number of labels\r
+   * @return collection containing {start value, end value, increment}\r
+   */\r
+  public static List<Double> getLabels(final double start, final double end,\r
+      final int approxNumLabels) {\r
+    FORMAT.setMaximumFractionDigits(5);\r
+    List<Double> labels = new ArrayList<Double>();\r
+    double[] labelParams = computeLabels(start, end, approxNumLabels);\r
+    // when the start > end the inc will be negative so it will still work\r
+    int numLabels = 1 + (int) ((labelParams[1] - labelParams[0]) / labelParams[2]);\r
+    // we want the range to be inclusive but we don't want to blow up when\r
+    // looping for the case where the min and max are the same. So we loop\r
+    // on\r
+    // numLabels not on the values.\r
+    for (int i = 0; i < numLabels; i++) {\r
+      double z = labelParams[0] + i * labelParams[2];\r
+      try {\r
+        // this way, we avoid a label value like 0.4000000000000000001 instead\r
+        // of 0.4\r
+        z = FORMAT.parse(FORMAT.format(z)).doubleValue();\r
+      } catch (ParseException e) {\r
+        // do nothing here\r
+      }\r
+      labels.add(z);\r
+    }\r
+    return labels;\r
+  }\r
+\r
+  /**\r
+   * Computes a reasonable number of labels for a data range.\r
+   * \r
+   * @param start start value\r
+   * @param end final value\r
+   * @param approxNumLabels desired number of labels\r
+   * @return double[] array containing {start value, end value, increment}\r
+   */\r
+  private static double[] computeLabels(final double start, final double end,\r
+      final int approxNumLabels) {\r
+    if (Math.abs(start - end) < 0.0000001f) {\r
+      return new double[] { start, start, 0 };\r
+    }\r
+    double s = start;\r
+    double e = end;\r
+    boolean switched = false;\r
+    if (s > e) {\r
+      switched = true;\r
+      double tmp = s;\r
+      s = e;\r
+      e = tmp;\r
+    }\r
+    double xStep = roundUp(Math.abs(s - e) / approxNumLabels);\r
+    // Compute x starting point so it is a multiple of xStep.\r
+    double xStart = xStep * Math.ceil(s / xStep);\r
+    double xEnd = xStep * Math.floor(e / xStep);\r
+    if (switched) {\r
+      return new double[] { xEnd, xStart, -1.0 * xStep };\r
+    }\r
+    return new double[] { xStart, xEnd, xStep };\r
+  }\r
+\r
+  /**\r
+   * Given a number, round up to the nearest power of ten times 1, 2, or 5. The\r
+   * argument must be strictly positive.\r
+   */\r
+  private static double roundUp(final double val) {\r
+    int exponent = (int) Math.floor(Math.log10(val));\r
+    double rval = val * Math.pow(10, -exponent);\r
+    if (rval > 5.0) {\r
+      rval = 10.0;\r
+    } else if (rval > 2.0) {\r
+      rval = 5.0;\r
+    } else if (rval > 1.0) {\r
+      rval = 2.0;\r
+    }\r
+    rval *= Math.pow(10, exponent);\r
+    return rval;\r
+  }\r
+\r
+  /**\r
+   * Transforms a list of Float values into an array of float.\r
+   * \r
+   * @param values the list of Float\r
+   * @return the array of floats\r
+   */\r
+  public static float[] getFloats(List<Float> values) {\r
+    int length = values.size();\r
+    float[] result = new float[length];\r
+    for (int i = 0; i < length; i++) {\r
+      result[i] = values.get(i).floatValue();\r
+    }\r
+    return result;\r
+  }\r
+\r
+  /**\r
+   * Transforms a list of Double values into an array of double.\r
+   * \r
+   * @param values the list of Double\r
+   * @return the array of doubles\r
+   */\r
+  public static double[] getDoubles(List<Double> values) {\r
+    int length = values.size();\r
+    double[] result = new double[length];\r
+    for (int i = 0; i < length; i++) {\r
+      result[i] = values.get(i).doubleValue();\r
+    }\r
+    return result;\r
+  }\r
+\r
+}\r
diff --git a/android-libraries/achartengine/src/org/achartengine/util/XYEntry.java b/android-libraries/achartengine/src/org/achartengine/util/XYEntry.java
new file mode 100644 (file)
index 0000000..53761a4
--- /dev/null
@@ -0,0 +1,45 @@
+/**
+ * Copyright (C) 2009 - 2012 SC 4ViewSoft SRL
+ *  
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *  
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.achartengine.util;
+
+import java.util.Map.Entry;
+
+/**
+ * A map entry value encapsulating an XY point.
+ */
+public class XYEntry<K, V> implements Entry<K, V> {
+  private final K key;
+  
+  private V value;
+
+  public XYEntry(K key, V value) {
+    this.key = key;
+    this.value = value;
+  }
+
+  public K getKey() {
+    return key;
+  }
+
+  public V getValue() {
+    return value;
+  }
+
+  public V setValue(V object) {
+    this.value = object;
+    return this.value;
+  }
+}
\ No newline at end of file
diff --git a/android-libraries/achartengine/src/org/achartengine/util/package.html b/android-libraries/achartengine/src/org/achartengine/util/package.html
new file mode 100644 (file)
index 0000000..da92e91
--- /dev/null
@@ -0,0 +1,6 @@
+<html>\r
+<title>AChartEngine</title>\r
+<body>\r
+Utility classes that provide helper methods used by most of the other packages.\r
+</body>\r
+</html>
\ No newline at end of file
index 3288939d2215bce05500f1bf50e3c3af467e0e92..1772b2eff66f1cdac194dd3b9ecf20bff7d6cb90 100644 (file)
@@ -8,6 +8,5 @@
        <classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>\r
        <classpathentry kind="lib" path="libs/android-support-v4.jar"/>\r
        <classpathentry kind="lib" path="/OpenRocket/lib/exp4j-0.2.9.jar"/>\r
-       <classpathentry kind="lib" path="libs/achartengine-1.0.0.jar" sourcepath="/AChartEngine/src"/>\r
        <classpathentry kind="output" path="bin/classes"/>\r
 </classpath>\r
diff --git a/android/libs/achartengine-1.0.0.jar b/android/libs/achartengine-1.0.0.jar
deleted file mode 100644 (file)
index fe75dc3..0000000
Binary files a/android/libs/achartengine-1.0.0.jar and /dev/null differ
index 0c951984f714faabd63ce1a2e8ead2204960ad64..8202ea55fd7440524a64b2bef9ded1432344b6e0 100644 (file)
@@ -11,3 +11,4 @@
 target=android-15
 android.library.reference.1=../ActionBarSherlock
 android.library.reference.2=../TreeViewList
+android.library.reference.3=../achartengine