Initial checkin of androidplot v0.6.0
This commit is a snapshot of androidplot at tag 0.6.0:
commit 24dfe5d708dd409611fff1aa803ce3324a00db85
Author: bamboo <[email protected]>
Date: Sat Jul 20 20:06:07 2013 +0000
[maven-release-plugin] prepare release 0.6.0
Change-Id: I84fb6af3e0c96b1d3d14e21f518a9b49e1126cef
diff --git a/Examples/DemoApp/.classpath b/Examples/DemoApp/.classpath
new file mode 100644
index 0000000..c64ee78
--- /dev/null
+++ b/Examples/DemoApp/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry kind="src" output="bin/classes" path="src"/>
+ <classpathentry kind="src" output="bin/classes" path="gen"/>
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/AndroidPlot-Core"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/Examples/DemoApp/.project b/Examples/DemoApp/.project
new file mode 100644
index 0000000..185fcd4
--- /dev/null
+++ b/Examples/DemoApp/.project
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>AndroidPlotDemo</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.m2e.core.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.m2e.core.maven2Nature</nature>
+ </natures>
+</projectDescription>
diff --git a/Examples/DemoApp/AndroidManifest.xml b/Examples/DemoApp/AndroidManifest.xml
new file mode 100644
index 0000000..765336b
--- /dev/null
+++ b/Examples/DemoApp/AndroidManifest.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.androidplot.demos"
+ android:versionCode="8"
+ android:versionName="0.6.0.1">
+ <uses-sdk android:minSdkVersion="6" android:targetSdkVersion="16"/>
+
+ <!-- We must disable hardware acceleration otherwise some lines will not appear in our plots. -->
+ <application android:label="AndroidPlot API DemoApp"
+ android:icon="@drawable/icon">
+ <activity android:name=".MainActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".SimplePieChartActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".SimpleXYPlotActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".BarPlotExampleActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".DynamicXYPlotActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".OrientationSensorExampleActivity"
+ android:label="@string/app_name"
+ android:screenOrientation="landscape">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".StepChartExampleActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".TouchZoomExampleActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".ListViewActivity" android:label="ListView Example"/>
+ <activity android:name=".XYRegionExampleActivity" android:label="XYRegion Example">
+ <intent-filter>
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".TimeSeriesActivity"/>
+ <activity android:name=".DualScaleXYPlotExampleActivity"/>
+ <activity android:name=".XYPlotWithBgImgActivity"/>
+
+ <!-- receiver for demo app widget -->
+ <receiver
+ android:icon="@drawable/icon"
+ android:label="Example Widget"
+ android:name="com.androidplot.demos.widget.DemoAppWidgetProvider" >
+ <intent-filter >
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+
+ <meta-data
+ android:name="android.appwidget.provider"
+ android:resource="@xml/demo_app_widget_provider_info" />
+ </receiver>
+ </application>
+</manifest>
diff --git a/Examples/DemoApp/DemoApp.iml b/Examples/DemoApp/DemoApp.iml
new file mode 100644
index 0000000..c4b2db2
--- /dev/null
+++ b/Examples/DemoApp/DemoApp.iml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+ <component name="FacetManager">
+ <facet type="android" name="Android">
+ <configuration>
+ <option name="RUN_PROCESS_RESOURCES_MAVEN_TASK" value="false" />
+ <includeSystemProguardFile>false</includeSystemProguardFile>
+ <includeAssetsFromLibraries>true</includeAssetsFromLibraries>
+ <resOverlayFolders />
+ </configuration>
+ </facet>
+ </component>
+ <component name="NewModuleRootManager" inherit-compiler-output="false">
+ <output url="file://$MODULE_DIR$/target/classes" />
+ <output-test url="file://$MODULE_DIR$/target/test-classes" />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/gen" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/target/generated-sources/r" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <excludeFolder url="file://$MODULE_DIR$/target/classes" />
+ <excludeFolder url="file://$MODULE_DIR$/target/generated-sources/combined-assets" />
+ <excludeFolder url="file://$MODULE_DIR$/target/generated-sources/combined-resources" />
+ <excludeFolder url="file://$MODULE_DIR$/target/generated-sources/extracted-dependencies" />
+ </content>
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: com.google.android:android:4.1.1.4" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: commons-logging:commons-logging:1.1.1" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.httpcomponents:httpclient:4.0.1" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: org.apache.httpcomponents:httpcore:4.0.1" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: commons-codec:commons-codec:1.3" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: org.khronos:opengl-api:gl1.1-android-2.1_r1" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: xerces:xmlParserAPIs:2.6.2" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: xpp3:xpp3:1.1.4c" level="project" />
+ <orderEntry type="library" scope="PROVIDED" name="Maven: org.json:json:20080701" level="project" />
+ <orderEntry type="module" module-name="androidplot-core" />
+ </component>
+</module>
+
diff --git a/Examples/DemoApp/ant.properties b/Examples/DemoApp/ant.properties
new file mode 100644
index 0000000..87c820a
--- /dev/null
+++ b/Examples/DemoApp/ant.properties
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2012 AndroidPlot.com. All rights reserved.
+#
+# Redistribution and use of source without modification and derived binaries with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY ANDROIDPLOT.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANDROIDPLOT.COM OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and documentation are those of the
+# authors and should not be interpreted as representing official policies, either expressed
+# or implied, of AndroidPlot.com.
+#
+
+# This file is used to override default values used by the Ant build system.
+#
+# This file must be checked into Version Control Systems, as it is
+# integral to the build system of your project.
+
+# This file is only used by the Ant script.
+
+# You can use this to override default values such as
+# 'source.dir' for the location of your java source folder and
+# 'out.dir' for the location of your output folder.
+
+# You can also use it define how the release builds are signed by declaring
+# the following properties:
+# 'key.store' for the location of your keystore and
+# 'key.alias' for the name of the key to use.
+# The password will be asked during the build when you use the 'release' target.
+jar.libs.dir=..\\..\\AndroidPlot-Core\\target\\obfuscated
+
diff --git a/Examples/DemoApp/build.xml b/Examples/DemoApp/build.xml
new file mode 100644
index 0000000..45987d1
--- /dev/null
+++ b/Examples/DemoApp/build.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="testapp" default="help">
+
+ <!-- The local.properties file is created and updated by the 'android' tool.
+ It contains the path to the SDK. It should *NOT* be checked into
+ Version Control Systems. -->
+ <property file="local.properties" />
+
+ <!-- The ant.properties file can be created by you. It is only edited by the
+ 'android' tool to add properties to it.
+ This is the place to change some Ant specific build properties.
+ Here are some properties you may want to change/update:
+
+ source.dir
+ The name of the source directory. Default is 'src'.
+ out.dir
+ The name of the output directory. Default is 'bin'.
+
+ For other overridable properties, look at the beginning of the rules
+ files in the SDK, at tools/ant/build.xml
+
+ Properties related to the SDK location or the project target should
+ be updated using the 'android' tool with the 'update' action.
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems.
+
+ -->
+ <property file="ant.properties" />
+
+ <!-- if sdk.dir was not set from one of the property file, then
+ get it from the ANDROID_HOME env var.
+ This must be done before we load project.properties since
+ the proguard config can use sdk.dir -->
+ <property environment="env" />
+ <condition property="sdk.dir" value="${env.ANDROID_HOME}">
+ <isset property="env.ANDROID_HOME" />
+ </condition>
+
+ <!-- The project.properties file is created and updated by the 'android'
+ tool, as well as ADT.
+
+ This contains project specific properties such as project target, and library
+ dependencies. Lower level build properties are stored in ant.properties
+ (or in .classpath for Eclipse projects).
+
+ This file is an integral part of the build system for your
+ application and should be checked into Version Control Systems. -->
+ <loadproperties srcFile="project.properties" />
+
+ <!-- quick check on sdk.dir -->
+ <fail
+ message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
+ unless="sdk.dir"
+ />
+
+ <!--
+ Import per project custom build rules if present at the root of the project.
+ This is the place to put custom intermediary targets such as:
+ -pre-build
+ -pre-compile
+ -post-compile (This is typically used for code obfuscation.
+ Compiled code location: ${out.classes.absolute.dir}
+ If this is not done in place, override ${out.dex.input.absolute.dir})
+ -post-package
+ -post-build
+ -pre-clean
+ -->
+ <import file="custom_rules.xml" optional="true" />
+
+ <!-- Import the actual build file.
+
+ To customize existing targets, there are two options:
+ - Customize only one target:
+ - copy/paste the target into this file, *before* the
+ <import> task.
+ - customize it to your needs.
+ - Customize the whole content of build.xml
+ - copy/paste the content of the rules files (minus the top node)
+ into this file, replacing the <import> task.
+ - customize to your needs.
+
+ ***********************
+ ****** IMPORTANT ******
+ ***********************
+ In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
+ in order to avoid having your file be overridden by tools such as "android update project"
+ -->
+ <!-- version-tag: 1 -->
+ <import file="${sdk.dir}/tools/ant/build.xml" />
+
+</project>
diff --git a/Examples/DemoApp/pom.xml b/Examples/DemoApp/pom.xml
new file mode 100644
index 0000000..3ce1b3f
--- /dev/null
+++ b/Examples/DemoApp/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.androidplot</groupId>
+ <artifactId>androidplot</artifactId>
+ <version>0.6.0</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>com.androidplot</groupId>
+ <artifactId>androidplot-demoapp</artifactId>
+ <packaging>apk</packaging>
+ <name>AndroidPlot-DemoApp</name>
+ <!--<version>1.0-SNAPSHOT</version>-->
+
+ <dependencies>
+ <!--<dependency>
+ <groupId>com.google.android</groupId>
+ <artifactId>android</artifactId>
+ <version>4.1.1.4</version>
+ <scope>provided</scope>
+ </dependency>-->
+ <dependency>
+ <groupId>com.google.android</groupId>
+ <artifactId>android</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.androidplot</groupId>
+ <artifactId>androidplot-core</artifactId>
+ <version>0.6.0</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <sourceDirectory>src</sourceDirectory>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>com.jayway.maven.plugins.android.generation2</groupId>
+ <artifactId>android-maven-plugin</artifactId>
+ <version>3.6.0</version>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>com.jayway.maven.plugins.android.generation2</groupId>
+ <artifactId>android-maven-plugin</artifactId>
+ <configuration>
+ <sdk>
+ <!-- platform or api level (api level 4 = platform 1.6)-->
+ <platform>16</platform>
+ </sdk>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/Examples/DemoApp/proguard-project.txt b/Examples/DemoApp/proguard-project.txt
new file mode 100644
index 0000000..2c0da18
--- /dev/null
+++ b/Examples/DemoApp/proguard-project.txt
@@ -0,0 +1,26 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# remove all debug and verbose level logging statements:
+-assumenosideeffects class android.util.Log {
+ public static *** d(...);
+ public static *** v(...);
+}
diff --git a/Examples/DemoApp/project.properties b/Examples/DemoApp/project.properties
new file mode 100644
index 0000000..29656f2
--- /dev/null
+++ b/Examples/DemoApp/project.properties
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2012 AndroidPlot.com. All rights reserved.
+#
+# Redistribution and use of source without modification and derived binaries with or without modification,
+# are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY ANDROIDPLOT.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANDROIDPLOT.COM OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# The views and conclusions contained in the software and documentation are those of the
+# authors and should not be interpreted as representing official policies, either expressed
+# or implied, of AndroidPlot.com.
+#
+
+# 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 edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
+# using config with optimization enabled so that things like log statement removal will work:
+proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt
+# Project target.
+target=android-16
diff --git a/Examples/DemoApp/res/drawable/graph_background.png b/Examples/DemoApp/res/drawable/graph_background.png
new file mode 100755
index 0000000..47523c2
--- /dev/null
+++ b/Examples/DemoApp/res/drawable/graph_background.png
Binary files differ
diff --git a/Examples/DemoApp/res/drawable/icon.png b/Examples/DemoApp/res/drawable/icon.png
new file mode 100644
index 0000000..6557d3a
--- /dev/null
+++ b/Examples/DemoApp/res/drawable/icon.png
Binary files differ
diff --git a/Examples/DemoApp/res/layout/bar_plot_example.xml b/Examples/DemoApp/res/layout/bar_plot_example.xml
new file mode 100644
index 0000000..76ac666
--- /dev/null
+++ b/Examples/DemoApp/res/layout/bar_plot_example.xml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/mySimpleXYPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="Growth"
+ androidPlot.domainLabel="Month"
+ androidPlot.rangeLabel="Revenue (millions)"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.gridBackgroundPaint.color="#000000"
+ androidPlot.graphWidget.domainGridLinePaint.alpha="0"
+ androidPlot.graphWidget.domainOriginLinePaint.alpha="0"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
+ android:layout_weight="1"
+ androidPlot.graphWidget.gridLinePaint.color="#000000"/>
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <Spinner
+ android:id="@+id/spRenderStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <Spinner
+ android:id="@+id/spSeriesSize"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <Spinner
+ android:id="@+id/spWidthStyle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <RelativeLayout
+ android:id="@+id/sectionGraph"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <SeekBar
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:max="300"
+ android:progress="10"
+ android:id="@+id/sbFixed"/>
+ <SeekBar
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:max="50"
+ android:progress="1"
+ android:id="@+id/sbVariable"/>
+ </RelativeLayout>
+ </LinearLayout>
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <CheckBox android:id="@+id/s1CheckBox"
+ android:text="Series 1"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/s2CheckBox"
+ android:text="Series 2"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/demo_app_widget.xml b/Examples/DemoApp/res/layout/demo_app_widget.xml
new file mode 100644
index 0000000..817e0a4
--- /dev/null
+++ b/Examples/DemoApp/res/layout/demo_app_widget.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/imgView"
+ android:background="@android:drawable/alert_dark_frame"
+ android:scaleType="centerInside"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ </ImageView>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/dual_scale_xy_plot_example.xml b/Examples/DemoApp/res/layout/dual_scale_xy_plot_example.xml
new file mode 100644
index 0000000..f21eac2
--- /dev/null
+++ b/Examples/DemoApp/res/layout/dual_scale_xy_plot_example.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <RelativeLayout
+ android:id="@+id/sectionGraph"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:layout_marginTop="0px"
+ android:layout_marginBottom="0px"
+ android:layout_marginLeft="0px"
+ android:layout_marginRight="0px">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/mySimpleXYPlot_L"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="A Simple XY Plot"
+ androidPlot.graphWidget.gridLinePaint.color="#000000"/>
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/mySimpleXYPlot_R"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="A Simple XY Plot"
+ androidPlot.graphWidget.gridLinePaint.color="#000000"/>
+
+ </RelativeLayout>
+
+ <Button android:id="@+id/toggleSeries2"
+ style="@style/toc_button"
+ android:text="Toggle position of Series2"
+ android:enabled="true"/>
+
+</LinearLayout>
diff --git a/Examples/DemoApp/res/layout/dynamicxyplot_example.xml b/Examples/DemoApp/res/layout/dynamicxyplot_example.xml
new file mode 100644
index 0000000..0276fce
--- /dev/null
+++ b/Examples/DemoApp/res/layout/dynamicxyplot_example.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/dynamicXYPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidplot.renderMode="use_background_thread"
+ androidPlot.title="A Dynamic XY Plot"
+ androidPlot.domainLabel="Domain"
+ androidPlot.rangeLabel="Range"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ androidPlot.legendWidget.positionMetrics.anchor="right_bottom"/>
+
+</LinearLayout>
diff --git a/Examples/DemoApp/res/layout/listview_example.xml b/Examples/DemoApp/res/layout/listview_example.xml
new file mode 100644
index 0000000..5ba50bc
--- /dev/null
+++ b/Examples/DemoApp/res/layout/listview_example.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout android:id="@+id/LinearLayout01"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <ListView android:id="@+id/listView1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/listview_example_item.xml b/Examples/DemoApp/res/layout/listview_example_item.xml
new file mode 100644
index 0000000..d1aa023
--- /dev/null
+++ b/Examples/DemoApp/res/layout/listview_example_item.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/xyplot"
+ android:layout_width="fill_parent"
+ android:layout_height="250dp"
+ title="an xy plot"/>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/main.xml b/Examples/DemoApp/res/layout/main.xml
new file mode 100644
index 0000000..779b2f3
--- /dev/null
+++ b/Examples/DemoApp/res/layout/main.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ScrollView android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <Button android:id="@+id/startSimplePieExButton"
+ style="@style/toc_button"
+ android:text="A Pie Chart"/>
+ <Button android:id="@+id/startSimpleXYExButton"
+ style="@style/toc_button"
+ android:text="A Simple XY Plot"/>
+ <Button android:id="@+id/startDynamicXYExButton"
+ style="@style/toc_button"
+ android:text="A Dynamic XY Plot"/>
+ <Button android:id="@+id/startOrSensorExButton"
+ style="@style/toc_button"
+ android:text="Realtime Orientation Sensor Plot"/>
+ <Button android:id="@+id/startTimeSeriesExButton"
+ style="@style/toc_button"
+ android:text="@string/ts_title"/>
+ <Button android:id="@+id/startStepChartExButton"
+ style="@style/toc_button"
+ android:text="Step Chart"
+ />
+ <Button android:id="@+id/startScrollZoomButton"
+ style="@style/toc_button"
+ android:text="Scroll and Zoom"
+ />
+ <Button android:id="@+id/startBarPlotExButton"
+ style="@style/toc_button"
+ android:text="Bar Plot"/>
+ <Button android:id="@+id/startXyScatterExButton"
+ style="@style/toc_button"
+ android:text="XY Scatter"
+ android:enabled="false"/>
+ <Button android:id="@+id/startXyScatterLineExButton"
+ style="@style/toc_button"
+ android:text="XY Scatter With Lines"
+ android:enabled="false"/>
+ <Button android:id="@+id/startXyRegionExampleButton"
+ style="@style/toc_button"
+ android:text="XYRegion Example"
+ android:enabled="true"/>
+ <Button android:id="@+id/startXyListViewExButton"
+ style="@style/toc_button"
+ android:text="ListView of XYPlots"
+ android:enabled="true"/>
+ <Button android:id="@+id/startDualScaleExampleButton"
+ style="@style/toc_button"
+ android:text="Dual Scale Example"
+ android:enabled="true"/>
+ <Button android:id="@+id/startXYPlotWithBgImgExample"
+ style="@style/toc_button"
+ android:text="XY Background Example"
+ android:enabled="true"/>
+ </LinearLayout>
+ </ScrollView>
+ <TextView android:id="@+id/text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:autoLink="web"
+ android:gravity="center"
+ android:text="http://androidplot.com"/>
+</LinearLayout>
+
diff --git a/Examples/DemoApp/res/layout/orientation_sensor_example.xml b/Examples/DemoApp/res/layout/orientation_sensor_example.xml
new file mode 100644
index 0000000..85fa45f
--- /dev/null
+++ b/Examples/DemoApp/res/layout/orientation_sensor_example.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <LinearLayout android:orientation="horizontal"
+ android:gravity="center"
+ android:layout_weight="1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/aprLevelsPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_margin="0dp"
+ android:layout_weight="3"
+ android:layout_marginTop="10px"
+ android:layout_marginLeft="10px"
+ android:layout_marginRight="10px"
+ androidPlot.backgroundPaint.color="#000000"
+ androidPlot.borderPaint.color="#000000"
+ androidplot.renderMode="use_background_thread"
+ androidPlot.title="Levels"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.backgroundPaint.color="#000000"
+ androidPlot.graphWidget.gridBackgroundPaint.color="#000000"
+ androidPlot.graphWidget.domainGridLinePaint.color="#00000000"
+ androidPlot.graphWidget.domainOriginLinePaint.color="#00000000"
+ androidPlot.graphWidget.domainOriginLabelPaint.color="#00000000"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="10dp"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ />
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/aprHistoryPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_margin="0dp"
+ android:layout_weight="1"
+ android:layout_marginTop="10px"
+ android:layout_marginLeft="10px"
+ android:layout_marginRight="10px"
+ androidPlot.backgroundPaint.color="#000000"
+ androidPlot.borderPaint.color="#000000"
+ androidplot.renderMode="use_background_thread"
+ androidPlot.title="History"
+ androidPlot.domainLabel="Domain"
+ androidPlot.rangeLabel="Range"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.backgroundPaint.color="#000000"
+ androidPlot.graphWidget.gridBackgroundPaint.color="#000000"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ />
+
+ </LinearLayout>
+
+ <LinearLayout android:orientation="horizontal"
+ android:gravity="center"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <CheckBox android:id="@+id/hwAccelerationCb"
+ android:visibility="gone"
+ android:text="HW Acceleration"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ <CheckBox android:id="@+id/showFpsCb"
+ android:text="Show FPS"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/pie_chart.xml b/Examples/DemoApp/res/layout/pie_chart.xml
new file mode 100644
index 0000000..010bcfc
--- /dev/null
+++ b/Examples/DemoApp/res/layout/pie_chart.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <com.androidplot.pie.PieChart
+ android:id="@+id/mySimplePieChart"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ androidPlot.title="A Simple Pie Chart"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"/>
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:layout_gravity="center"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center"
+ android:text="Donut Size"
+ android:id="@+id/donutSizeSeekLabel"/>
+ <SeekBar
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:max="90"
+ android:progress="50"
+ android:id="@+id/donutSizeSeekBar"/>
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_gravity="center"
+ android:text="unknown"
+ android:id="@+id/donutSizeTextView"/>
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/simple_xy_plot_example.xml b/Examples/DemoApp/res/layout/simple_xy_plot_example.xml
new file mode 100644
index 0000000..fe54c57
--- /dev/null
+++ b/Examples/DemoApp/res/layout/simple_xy_plot_example.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/mySimpleXYPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="A Simple XY Plot"
+ androidPlot.domainLabel="Domain"
+ androidPlot.rangeLabel="Range"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
+ androidPlot.graphWidget.gridLinePaint.color="#000000"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/step_chart_example.xml b/Examples/DemoApp/res/layout/step_chart_example.xml
new file mode 100644
index 0000000..fadc79b
--- /dev/null
+++ b/Examples/DemoApp/res/layout/step_chart_example.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ style="@style/sample_activity"
+ >
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/stepChartExamplePlot"
+ style="@style/plotStyle1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidplot.title="HTTP Server State (15 Sec)"
+ androidplot.domainLabel="time (secs)"
+ androidplot.rangeLabel="server state"
+ androidplot.markupEnabled="false"
+ renderMode="use_main_thread"
+ />
+</LinearLayout>
+
diff --git a/Examples/DemoApp/res/layout/time_series_example.xml b/Examples/DemoApp/res/layout/time_series_example.xml
new file mode 100644
index 0000000..847b381
--- /dev/null
+++ b/Examples/DemoApp/res/layout/time_series_example.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/plot1"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ title="@string/ts_plot1_title"
+ renderMode="use_main_thread"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/touch_zoom_example.xml b/Examples/DemoApp/res/layout/touch_zoom_example.xml
new file mode 100644
index 0000000..71d0e33
--- /dev/null
+++ b/Examples/DemoApp/res/layout/touch_zoom_example.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/sample_activity"
+ android:orientation="vertical">
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/mySimpleXYPlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="ScrollZoom Example"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.widthMetric.value="1"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ androidPlot.legendWidget.positionMetrics.xPositionMetric.value="0"
+ androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
+ android:layout_weight="1"/>
+
+ <Button android:id="@+id/resetButton"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="Reset"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/xy_plot_with_bq_img_example.xml b/Examples/DemoApp/res/layout/xy_plot_with_bq_img_example.xml
new file mode 100644
index 0000000..04e4315
--- /dev/null
+++ b/Examples/DemoApp/res/layout/xy_plot_with_bq_img_example.xml
@@ -0,0 +1,48 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".GraphMetricsActivity" >
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/graph_metrics"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_centerHorizontal="true"
+ androidPlot.title="BG Image Example"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="15dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="@dimen/legend_text_font_size"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="25dp"
+ androidPlot.legendWidget.positionMetrics.xPositionMetric.value="0"
+ androidPlot.legendWidget.positionMetrics.anchor="right_bottom"
+ android:layout_centerVertical="true"/>
+
+ <ToggleButton
+ android:id="@+id/style_toggle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignTop="@id/graph_metrics"
+ android:layout_alignRight="@id/graph_metrics"
+ android:layout_marginTop="15dp"
+ android:layout_marginRight="15dp"
+ android:textOn="bg on"
+ android:textOff="bg off"
+ android:onClick="onGraphStyleToggle" />
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/layout/xyregion_example.xml b/Examples/DemoApp/res/layout/xyregion_example.xml
new file mode 100644
index 0000000..db0bbf8
--- /dev/null
+++ b/Examples/DemoApp/res/layout/xyregion_example.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+
+ <com.androidplot.xy.XYPlot
+ android:id="@+id/xyRegionExamplePlot"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ androidPlot.title="Batting Practice Stats"
+ androidPlot.domainLabel="Pitch #"
+ androidPlot.rangeLabel="Distance"
+ androidPlot.titleWidget.labelPaint.textSize="@dimen/title_font_size"
+ androidPlot.domainLabelWidget.labelPaint.textSize="@dimen/domain_label_font_size"
+ androidPlot.rangeLabelWidget.labelPaint.textSize="@dimen/range_label_font_size"
+ androidPlot.graphWidget.marginTop="20dp"
+ androidPlot.graphWidget.marginLeft="35dp"
+ androidPlot.graphWidget.marginBottom="25dp"
+ androidPlot.graphWidget.marginRight="10dp"
+ androidPlot.graphWidget.rangeLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.rangeOriginLabelPaint.textSize="@dimen/range_tick_label_font_size"
+ androidPlot.graphWidget.domainLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.graphWidget.domainOriginLabelPaint.textSize="@dimen/domain_tick_label_font_size"
+ androidPlot.legendWidget.textPaint.textSize="12dp"
+ androidPlot.legendWidget.iconSizeMetrics.heightMetric.value="15dp"
+ androidPlot.legendWidget.iconSizeMetrics.widthMetric.value="15dp"
+ androidPlot.legendWidget.heightMetric.value="40dp"
+ androidPlot.legendWidget.widthMetric.value="40dp"
+ android:layout_weight="1"
+ />
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <CheckBox android:id="@+id/s1CheckBox"
+ android:text="Tim"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/s2CheckBox"
+ android:text="Nick"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/s3CheckBox"
+ android:text="Joe"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/s4CheckBox"
+ android:text="James"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <CheckBox android:id="@+id/r1CheckBox"
+ android:text="R1"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/r2CheckBox"
+ android:text="R2"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/r3CheckBox"
+ android:text="R3"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/r4CheckBox"
+ android:text="R4"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ <CheckBox android:id="@+id/r5CheckBox"
+ android:text="R5"
+ android:checked="true"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"/>
+ </LinearLayout>
+
+</LinearLayout>
+
diff --git a/Examples/DemoApp/res/values-hdpi/dimens.xml b/Examples/DemoApp/res/values-hdpi/dimens.xml
new file mode 100644
index 0000000..79fac2c
--- /dev/null
+++ b/Examples/DemoApp/res/values-hdpi/dimens.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- HDPI DIMENSIONS -->
+<resources>
+ <dimen name="title_font_size">30dp</dimen>
+ <dimen name="pie_segment_label_font_size">20dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/values-ldpi/dimens.xml b/Examples/DemoApp/res/values-ldpi/dimens.xml
new file mode 100644
index 0000000..81033f3
--- /dev/null
+++ b/Examples/DemoApp/res/values-ldpi/dimens.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- LDPI DIMENSIONS -->
+<resources>
+</resources>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/values/attrs.xml b/Examples/DemoApp/res/values/attrs.xml
new file mode 100644
index 0000000..b88cddf
--- /dev/null
+++ b/Examples/DemoApp/res/values/attrs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <declare-styleable name="XYPlot">
+ <attr name="androidplot.title" format="string"/>
+ </declare-styleable>
+</resources>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/values/dimens.xml b/Examples/DemoApp/res/values/dimens.xml
new file mode 100644
index 0000000..379e32b
--- /dev/null
+++ b/Examples/DemoApp/res/values/dimens.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- DEFAULT DIMENSIONS -->
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+ <dimen name="pie_segment_label_font_size">10dp</dimen>
+ <dimen name="title_font_size">20dp</dimen>
+ <dimen name="domain_label_font_size">13dp</dimen>
+ <dimen name="range_label_font_size">13dp</dimen>
+ <dimen name="range_tick_label_font_size">15dp</dimen>
+ <dimen name="domain_tick_label_font_size">15dp</dimen>
+ <dimen name="legend_text_font_size">20dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/values/strings.xml b/Examples/DemoApp/res/values/strings.xml
new file mode 100644
index 0000000..0bde0cd
--- /dev/null
+++ b/Examples/DemoApp/res/values/strings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">AndroidPlot Demo</string>
+
+ <string name="sxy_title">A Simple XY Plot</string>
+
+ <string name="ts_title">Time Series</string>
+ <string name="ts_plot1_title">Yearly UFO Sightings</string>
+</resources>
diff --git a/Examples/DemoApp/res/values/style.xml b/Examples/DemoApp/res/values/style.xml
new file mode 100644
index 0000000..d465715
--- /dev/null
+++ b/Examples/DemoApp/res/values/style.xml
@@ -0,0 +1,34 @@
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<resources xmlns="http://schemas.android.com/apk/lib/com.androidplot.xy">
+ <style name="sample_activity">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">fill_parent</item>
+ </style>
+
+ <style name="toc_button">
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ </style>
+
+ <style name="plotStyle1">
+ <!--<item name="androidplot.title">Default Title</item>
+ <item name="androidplot.domainLabel">my domain</item>-->
+ <!--<item name="XYPlot:androidplot.title">my domain</item>-->
+ </style>
+
+</resources>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/demo_app_widget_provider_info.xml b/Examples/DemoApp/res/xml/demo_app_widget_provider_info.xml
new file mode 100644
index 0000000..771c246
--- /dev/null
+++ b/Examples/DemoApp/res/xml/demo_app_widget_provider_info.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright 2012 AndroidPlot.com
+ ~
+ ~ 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.
+ -->
+
+<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
+ android:minWidth="294dp"
+ android:minHeight="72dp"
+ android:updatePeriodMillis="86400000"
+ android:previewImage="@drawable/icon"
+ android:initialLayout="@layout/demo_app_widget"
+ android:resizeMode="horizontal|vertical">
+</appwidget-provider>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/line_point_formatter_with_plf1.xml b/Examples/DemoApp/res/xml/line_point_formatter_with_plf1.xml
new file mode 100644
index 0000000..47bf5f5
--- /dev/null
+++ b/Examples/DemoApp/res/xml/line_point_formatter_with_plf1.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ linePaint.strokeWidth="3dp"
+ linePaint.color="#00AA00"
+ vertexPaint.color="#007700"
+ fillPaint.color="#00000000"
+ pointLabelFormatter.textPaint.color="#FFFFFF"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/line_point_formatter_with_plf2.xml b/Examples/DemoApp/res/xml/line_point_formatter_with_plf2.xml
new file mode 100644
index 0000000..31894cd
--- /dev/null
+++ b/Examples/DemoApp/res/xml/line_point_formatter_with_plf2.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ linePaint.strokeWidth="3dp"
+ linePaint.color="#0000AA"
+ vertexPaint.color="#000077"
+ fillPaint.color="#00000000"
+ pointLabelFormatter.textPaint.color="#FFFFFF"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/pie_segment_formatter1.xml b/Examples/DemoApp/res/xml/pie_segment_formatter1.xml
new file mode 100644
index 0000000..1b0c7e0
--- /dev/null
+++ b/Examples/DemoApp/res/xml/pie_segment_formatter1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ fillPaint.color="#FF0000"
+ labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/pie_segment_formatter2.xml b/Examples/DemoApp/res/xml/pie_segment_formatter2.xml
new file mode 100644
index 0000000..ad7a225
--- /dev/null
+++ b/Examples/DemoApp/res/xml/pie_segment_formatter2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ fillPaint.color="#00FF00"
+ labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/pie_segment_formatter3.xml b/Examples/DemoApp/res/xml/pie_segment_formatter3.xml
new file mode 100644
index 0000000..5e02a39
--- /dev/null
+++ b/Examples/DemoApp/res/xml/pie_segment_formatter3.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ fillPaint.color="#0000FF"
+ labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/res/xml/pie_segment_formatter4.xml b/Examples/DemoApp/res/xml/pie_segment_formatter4.xml
new file mode 100644
index 0000000..2cf1171
--- /dev/null
+++ b/Examples/DemoApp/res/xml/pie_segment_formatter4.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<config
+ fillPaint.color="#FF00FF"
+ labelPaint.textSize="@dimen/pie_segment_label_font_size"/>
\ No newline at end of file
diff --git a/Examples/DemoApp/src/com/androidplot/demos/BarPlotExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/BarPlotExampleActivity.java
new file mode 100644
index 0000000..4c79dd8
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/BarPlotExampleActivity.java
@@ -0,0 +1,425 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.util.Pair;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+
+import com.androidplot.LineRegion;
+import com.androidplot.ui.AnchorPosition;
+import com.androidplot.ui.SeriesRenderer;
+import com.androidplot.ui.SizeLayoutType;
+import com.androidplot.ui.SizeMetrics;
+import com.androidplot.ui.TextOrientationType;
+import com.androidplot.ui.widget.TextLabelWidget;
+import com.androidplot.util.PixelUtils;
+import com.androidplot.xy.*;
+import com.androidplot.ui.XLayoutStyle;
+import com.androidplot.ui.YLayoutStyle;
+
+/**
+ * The simplest possible example of using AndroidPlot to plot some data.
+ */
+public class BarPlotExampleActivity extends Activity
+{
+
+ private static final String NO_SELECTION_TXT = "Touch bar to select.";
+ private XYPlot plot;
+
+ private CheckBox series1CheckBox;
+ private CheckBox series2CheckBox;
+ private Spinner spRenderStyle, spWidthStyle, spSeriesSize;
+ private SeekBar sbFixedWidth, sbVariableWidth;
+
+ private XYSeries series1;
+ private XYSeries series2;
+ private enum SeriesSize {
+ TEN,
+ TWENTY,
+ SIXTY
+ }
+
+ // Create a couple arrays of y-values to plot:
+ Number[] series1Numbers10 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5};
+ Number[] series2Numbers10 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4};
+ Number[] series1Numbers20 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3};
+ Number[] series2Numbers20 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9};
+ Number[] series1Numbers60 = {2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3, 2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3, 2, null, 5, 2, 7, 4, 3, 7, 4, 5, 7, 4, 5, 8, 5, 3, 6, 3, 9, 3};
+ Number[] series2Numbers60 = {4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9, 4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9, 4, 6, 3, null, 2, 0, 7, 4, 5, 4, 9, 6, 2, 8, 4, 0, 7, 4, 7, 9};
+ Number[] series1Numbers = series1Numbers10;
+ Number[] series2Numbers = series2Numbers10;
+
+ private MyBarFormatter formatter1 =
+ new MyBarFormatter(Color.argb(200, 100, 150, 100), Color.LTGRAY);
+
+ private MyBarFormatter formatter2 =
+ new MyBarFormatter(Color.argb(200, 100, 100, 150), Color.LTGRAY);
+
+ private MyBarFormatter selectionFormatter =
+ new MyBarFormatter(Color.YELLOW, Color.WHITE);
+
+ private TextLabelWidget selectionWidget;
+
+ private Pair<Integer, XYSeries> selection;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.bar_plot_example);
+
+ // initialize our XYPlot reference:
+ plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
+
+ selectionWidget = new TextLabelWidget(plot.getLayoutManager(), NO_SELECTION_TXT,
+ new SizeMetrics(
+ PixelUtils.dpToPix(100), SizeLayoutType.ABSOLUTE,
+ PixelUtils.dpToPix(100), SizeLayoutType.ABSOLUTE),
+ TextOrientationType.HORIZONTAL);
+
+ selectionWidget.getLabelPaint().setTextSize(PixelUtils.dpToPix(16));
+
+ // add a dark, semi-transparent background to the selection label widget:
+ Paint p = new Paint();
+ p.setARGB(100, 0, 0, 0);
+ selectionWidget.setBackgroundPaint(p);
+
+ selectionWidget.position(
+ 0, XLayoutStyle.RELATIVE_TO_CENTER,
+ PixelUtils.dpToPix(45), YLayoutStyle.ABSOLUTE_FROM_TOP,
+ AnchorPosition.TOP_MIDDLE);
+ selectionWidget.pack();
+
+
+ // reduce the number of range labels
+ plot.setTicksPerRangeLabel(3);
+ plot.setRangeLowerBoundary(0, BoundaryMode.FIXED);
+ plot.getGraphWidget().setGridPadding(30, 10, 30, 0);
+
+ plot.setTicksPerDomainLabel(2);
+
+
+ // setup checkbox listers:
+ series1CheckBox = (CheckBox) findViewById(R.id.s1CheckBox);
+ series1CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onS1CheckBoxClicked(b);
+ }
+ });
+
+ series2CheckBox = (CheckBox) findViewById(R.id.s2CheckBox);
+ series2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {onS2CheckBoxClicked(b);
+ }
+ });
+
+ plot.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
+ onPlotClicked(new PointF(motionEvent.getX(), motionEvent.getY()));
+ }
+ return true;
+ }
+ });
+
+ spRenderStyle = (Spinner) findViewById(R.id.spRenderStyle);
+ ArrayAdapter <BarRenderer.BarRenderStyle> adapter = new ArrayAdapter <BarRenderer.BarRenderStyle> (this, android.R.layout.simple_spinner_item, BarRenderer.BarRenderStyle.values() );
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spRenderStyle.setAdapter(adapter);
+ spRenderStyle.setSelection(BarRenderer.BarRenderStyle.OVERLAID.ordinal());
+ spRenderStyle.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
+ updatePlot();
+ }
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+ });
+
+ spWidthStyle = (Spinner) findViewById(R.id.spWidthStyle);
+ ArrayAdapter <BarRenderer.BarWidthStyle> adapter1 = new ArrayAdapter <BarRenderer.BarWidthStyle> (this, android.R.layout.simple_spinner_item, BarRenderer.BarWidthStyle.values() );
+ adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spWidthStyle.setAdapter(adapter1);
+ spWidthStyle.setSelection(BarRenderer.BarWidthStyle.FIXED_WIDTH.ordinal());
+ spWidthStyle.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
+ if (BarRenderer.BarWidthStyle.FIXED_WIDTH.equals(spWidthStyle.getSelectedItem())) {
+ sbFixedWidth.setVisibility(View.VISIBLE);
+ sbVariableWidth.setVisibility(View.INVISIBLE);
+ } else {
+ sbFixedWidth.setVisibility(View.INVISIBLE);
+ sbVariableWidth.setVisibility(View.VISIBLE);
+ }
+ updatePlot();
+ }
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+ });
+
+ spSeriesSize = (Spinner) findViewById(R.id.spSeriesSize);
+ ArrayAdapter <SeriesSize> adapter11 = new ArrayAdapter <SeriesSize> (this, android.R.layout.simple_spinner_item, SeriesSize.values() );
+ adapter11.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ spSeriesSize.setAdapter(adapter11);
+ spSeriesSize.setSelection(SeriesSize.TEN.ordinal());
+ spSeriesSize.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> arg0, View arg1,int arg2, long arg3) {
+ switch ((SeriesSize)arg0.getSelectedItem()) {
+ case TEN:
+ series1Numbers = series1Numbers10;
+ series2Numbers = series2Numbers10;
+ break;
+ case TWENTY:
+ series1Numbers = series1Numbers20;
+ series2Numbers = series2Numbers20;
+ break;
+ case SIXTY:
+ series1Numbers = series1Numbers60;
+ series2Numbers = series2Numbers60;
+ break;
+ default:
+ break;
+ }
+ updatePlot();
+ }
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ }
+ });
+
+
+ sbFixedWidth = (SeekBar) findViewById(R.id.sbFixed);
+ sbFixedWidth.setProgress(50);
+ sbFixedWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int i, boolean b) {updatePlot();}
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+ });
+
+
+ sbVariableWidth = (SeekBar) findViewById(R.id.sbVariable);
+ sbVariableWidth.setProgress(1);
+ sbVariableWidth.setVisibility(View.INVISIBLE);
+ sbVariableWidth.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int i, boolean b) {updatePlot();}
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {}
+ });
+
+ plot.setDomainValueFormat(new NumberFormat() {
+ @Override
+ public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {
+ int year = (int) (value + 0.5d) / 12;
+ int month = (int) ((value + 0.5d) % 12);
+ return new StringBuffer(DateFormatSymbols.getInstance().getShortMonths()[month] + " '0" + year);
+ }
+
+ @Override
+ public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public Number parse(String string, ParsePosition position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+ });
+ updatePlot();
+
+ }
+
+ private void updatePlot() {
+
+ // Remove all current series from each plot
+ Iterator<XYSeries> iterator1 = plot.getSeriesSet().iterator();
+ while(iterator1.hasNext()) {
+ XYSeries setElement = iterator1.next();
+ plot.removeSeries(setElement);
+ }
+
+ // Setup our Series with the selected number of elements
+ series1 = new SimpleXYSeries(Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Us");
+ series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Them");
+
+ // add a new series' to the xyplot:
+ if (series1CheckBox.isChecked()) plot.addSeries(series1, formatter1);
+ if (series2CheckBox.isChecked()) plot.addSeries(series2, formatter2);
+
+ // Setup the BarRenderer with our selected options
+ MyBarRenderer renderer = ((MyBarRenderer)plot.getRenderer(MyBarRenderer.class));
+ renderer.setBarRenderStyle((BarRenderer.BarRenderStyle)spRenderStyle.getSelectedItem());
+ renderer.setBarWidthStyle((BarRenderer.BarWidthStyle)spWidthStyle.getSelectedItem());
+ renderer.setBarWidth(sbFixedWidth.getProgress());
+ renderer.setBarGap(sbVariableWidth.getProgress());
+
+ if (BarRenderer.BarRenderStyle.STACKED.equals(spRenderStyle.getSelectedItem())) {
+ plot.setRangeTopMin(15);
+ } else {
+ plot.setRangeTopMin(0);
+ }
+
+ plot.redraw();
+
+ }
+
+ private void onPlotClicked(PointF point) {
+
+ // make sure the point lies within the graph area. we use gridrect
+ // because it accounts for margins and padding as well.
+ if (plot.getGraphWidget().getGridRect().contains(point.x, point.y)) {
+ Number x = plot.getXVal(point);
+ Number y = plot.getYVal(point);
+
+
+ selection = null;
+ double xDistance = 0;
+ double yDistance = 0;
+
+ // find the closest value to the selection:
+ for (XYSeries series : plot.getSeriesSet()) {
+ for (int i = 0; i < series.size(); i++) {
+ Number thisX = series.getX(i);
+ Number thisY = series.getY(i);
+ if (thisX != null && thisY != null) {
+ double thisXDistance =
+ LineRegion.measure(x, thisX).doubleValue();
+ double thisYDistance =
+ LineRegion.measure(y, thisY).doubleValue();
+ if (selection == null) {
+ selection = new Pair<Integer, XYSeries>(i, series);
+ xDistance = thisXDistance;
+ yDistance = thisYDistance;
+ } else if (thisXDistance < xDistance) {
+ selection = new Pair<Integer, XYSeries>(i, series);
+ xDistance = thisXDistance;
+ yDistance = thisYDistance;
+ } else if (thisXDistance == xDistance &&
+ thisYDistance < yDistance &&
+ thisY.doubleValue() >= y.doubleValue()) {
+ selection = new Pair<Integer, XYSeries>(i, series);
+ xDistance = thisXDistance;
+ yDistance = thisYDistance;
+ }
+ }
+ }
+ }
+
+ } else {
+ // if the press was outside the graph area, deselect:
+ selection = null;
+ }
+
+ if(selection == null) {
+ selectionWidget.setText(NO_SELECTION_TXT);
+ } else {
+ selectionWidget.setText("Selected: " + selection.second.getTitle() +
+ " Value: " + selection.second.getY(selection.first));
+ }
+ plot.redraw();
+ }
+
+ private void onS1CheckBoxClicked(boolean checked) {
+ if (checked) {
+ plot.addSeries(series1, formatter1);
+ } else {
+ plot.removeSeries(series1);
+ }
+ plot.redraw();
+ }
+
+ private void onS2CheckBoxClicked(boolean checked) {
+ if (checked) {
+ plot.addSeries(series2, formatter2);
+ } else {
+ plot.removeSeries(series2);
+ }
+ plot.redraw();
+ }
+
+ class MyBarFormatter extends BarFormatter {
+ public MyBarFormatter(int fillColor, int borderColor) {
+ super(fillColor, borderColor);
+ }
+
+ @Override
+ public Class<? extends SeriesRenderer> getRendererClass() {
+ return MyBarRenderer.class;
+ }
+
+ @Override
+ public SeriesRenderer getRendererInstance(XYPlot plot) {
+ return new MyBarRenderer(plot);
+ }
+ }
+
+ class MyBarRenderer extends BarRenderer<MyBarFormatter> {
+
+ public MyBarRenderer(XYPlot plot) {
+ super(plot);
+ }
+
+ /**
+ * Implementing this method to allow us to inject our
+ * special selection formatter.
+ * @param index index of the point being rendered.
+ * @param series XYSeries to which the point being rendered belongs.
+ * @return
+ */
+ //@Override
+ // TODO: figure out why using @Override screws up the Maven builds
+ protected MyBarFormatter getFormatter(int index, XYSeries series) {
+ if(selection != null &&
+ selection.second == series &&
+ selection.first == index) {
+ return selectionFormatter;
+ } else {
+ return getFormatter(series);
+ }
+ }
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/DualScaleXYPlotExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/DualScaleXYPlotExampleActivity.java
new file mode 100644
index 0000000..d06581e
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/DualScaleXYPlotExampleActivity.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+import com.androidplot.ui.AnchorPosition;
+import com.androidplot.ui.DynamicTableModel;
+import com.androidplot.ui.SizeLayoutType;
+import com.androidplot.ui.SizeMetrics;
+import com.androidplot.xy.LineAndPointFormatter;
+import com.androidplot.xy.PointLabelFormatter;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.ui.XLayoutStyle;
+import com.androidplot.xy.XYGraphWidget;
+import com.androidplot.xy.XYLegendWidget;
+import com.androidplot.xy.XYPlot;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.ui.YLayoutStyle;
+
+/**
+ * The simplest possible example of using AndroidPlot to plot some data.
+ */
+public class DualScaleXYPlotExampleActivity extends Activity implements OnClickListener
+{
+
+ private XYPlot myXYPlot_LEFT, myXYPlot_RIGHT;
+ private Boolean series2_onRight = true;
+ private LineAndPointFormatter series1Format, series2Format;
+ private Button button;
+
+ // Declare and enable buttons to toggle whether the 2nd series is on left or right.
+
+ // Create a couple arrays of y-values to plot:
+ private Number[] series1Numbers = {1, 8, 5, 2, 7, 4};
+ private Number[] series2Numbers = {444, 613, 353, 876, 924, 1004};
+ XYSeries series1, series2;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dual_scale_xy_plot_example);
+
+ // Setup the LEFT Plot as normal
+ myXYPlot_LEFT = (XYPlot) findViewById(R.id.mySimpleXYPlot_L);
+ myXYPlot_RIGHT = (XYPlot) findViewById(R.id.mySimpleXYPlot_R);
+
+ // Disable Hardware Acceleration on the xyPlot view object.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ myXYPlot_LEFT.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ myXYPlot_RIGHT.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+
+ XYGraphWidget graphWidget_LEFT = myXYPlot_LEFT.getGraphWidget();
+ graphWidget_LEFT.setRangeAxisPosition(true, false, 4, "10");
+ graphWidget_LEFT.setMarginRight(0);
+ graphWidget_LEFT.setPaddingRight(30);
+ graphWidget_LEFT.setRangeLabelVerticalOffset(-3);
+ graphWidget_LEFT.setRangeLabelWidth(50);
+
+ // Setup the second Plot with Right-hand Scale and otherwise invisible.
+ myXYPlot_RIGHT.getDomainLabelWidget().setVisible(false);
+ myXYPlot_RIGHT.getRangeLabelWidget().setVisible(false);
+ myXYPlot_RIGHT.getTitleWidget().setVisible(false);
+ myXYPlot_RIGHT.getBorderPaint().setAlpha(0);
+ myXYPlot_RIGHT.getBackgroundPaint().setAlpha(0);
+ XYGraphWidget graphWidget_RIGHT = myXYPlot_RIGHT.getGraphWidget();
+ graphWidget_RIGHT.getBackgroundPaint().setAlpha(0);
+ graphWidget_RIGHT.getDomainLabelPaint().setAlpha(0);
+ graphWidget_RIGHT.getGridBackgroundPaint().setAlpha(0);
+ graphWidget_RIGHT.getDomainOriginLabelPaint().setAlpha(0);
+ graphWidget_RIGHT.getRangeOriginLinePaint().setAlpha(0);
+ graphWidget_RIGHT.getDomainGridLinePaint().setAlpha(0);
+ graphWidget_RIGHT.getRangeGridLinePaint().setAlpha(0);
+ graphWidget_RIGHT.setRangeAxisPosition(false, false, 4, "10");
+
+ // Copy where possible from the LEFT plot
+ graphWidget_RIGHT.setRangeLabelVerticalOffset(graphWidget_LEFT.getRangeLabelVerticalOffset());
+ graphWidget_RIGHT.setMarginRight(graphWidget_LEFT.getMarginRight());
+ graphWidget_RIGHT.setPaddingRight(graphWidget_LEFT.getPaddingRight());
+ graphWidget_RIGHT.setRangeLabelWidth(graphWidget_LEFT.getRangeLabelWidth());
+
+ // Position the Graphs
+ myXYPlot_LEFT.getGraphWidget().position(
+ 0 ,XLayoutStyle.ABSOLUTE_FROM_LEFT,10,YLayoutStyle.ABSOLUTE_FROM_TOP,AnchorPosition.LEFT_TOP);
+ myXYPlot_RIGHT.getGraphWidget().position(
+ 49,XLayoutStyle.ABSOLUTE_FROM_LEFT,10,YLayoutStyle.ABSOLUTE_FROM_TOP,AnchorPosition.LEFT_TOP);
+
+ // Setup and Position the LEFT Legend
+ XYLegendWidget legendWidget_LEFT = myXYPlot_LEFT.getLegendWidget();
+ legendWidget_LEFT.setTableModel(new DynamicTableModel(1, 3));
+ legendWidget_LEFT.getTextPaint().setTextSize(20);
+ legendWidget_LEFT.setSize(new SizeMetrics(100, SizeLayoutType.ABSOLUTE, 75, SizeLayoutType.FILL));
+ legendWidget_LEFT.setPadding(1, 1, 1, 1);
+ myXYPlot_LEFT.getGraphWidget().position(
+ 55, XLayoutStyle.ABSOLUTE_FROM_LEFT, 15, YLayoutStyle.ABSOLUTE_FROM_TOP, AnchorPosition.LEFT_TOP);
+
+ // Setup and Position the RIGHT Legend
+ XYLegendWidget legendWidget_RIGHT = myXYPlot_RIGHT.getLegendWidget();
+ legendWidget_RIGHT.setTableModel(new DynamicTableModel(1, 3));
+ legendWidget_RIGHT.getTextPaint().setTextSize(20);
+ legendWidget_RIGHT.setSize(new SizeMetrics(100, SizeLayoutType.ABSOLUTE, 110, SizeLayoutType.ABSOLUTE));
+ legendWidget_RIGHT.setPadding(1, 1, 1, 1);
+ myXYPlot_RIGHT.getGraphWidget().position(
+ 25, XLayoutStyle.ABSOLUTE_FROM_RIGHT, 15, YLayoutStyle.ABSOLUTE_FROM_TOP, AnchorPosition.RIGHT_TOP);
+
+ // Setup the Series
+ series1 = new SimpleXYSeries(Arrays.asList(series1Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series1");
+ series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
+
+ // Setup the formatters
+ series1Format = new LineAndPointFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 100, 0), null, new PointLabelFormatter(Color.WHITE));
+ series2Format = new LineAndPointFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 0, 100), null, new PointLabelFormatter(Color.WHITE));
+
+ // Setup the Button
+ button = (Button)findViewById(R.id.toggleSeries2);
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ updateView();
+
+ }
+
+ private void updateView() {
+
+ // Remove all current series from each plot
+ Iterator<XYSeries> iterator1 = myXYPlot_LEFT.getSeriesSet().iterator();
+ while(iterator1.hasNext()) {
+ XYSeries setElement = iterator1.next();
+ myXYPlot_LEFT.removeSeries(setElement);
+ }
+ Iterator<XYSeries> iterator2 = myXYPlot_RIGHT.getSeriesSet().iterator();
+ while(iterator2.hasNext()) {
+ XYSeries setElement = iterator2.next();
+ myXYPlot_RIGHT.removeSeries(setElement);
+ }
+
+ // Add series to each plot as needed.
+ myXYPlot_LEFT.addSeries(series1, series1Format);
+ if (series2_onRight) {
+ myXYPlot_RIGHT.addSeries(series2, series2Format);
+ } else {
+ myXYPlot_LEFT.addSeries(series2, series2Format);
+ }
+
+ // Finalise each Plot based on whether they have any series or not.
+ if (! myXYPlot_RIGHT.getSeriesSet().isEmpty()) {
+ myXYPlot_RIGHT.setVisibility(XYPlot.VISIBLE);
+ myXYPlot_RIGHT.redraw();
+ } else {
+ myXYPlot_RIGHT.setVisibility(XYPlot.INVISIBLE);
+ }
+
+ if (! myXYPlot_LEFT.getSeriesSet().isEmpty()) {
+ myXYPlot_LEFT.setVisibility(XYPlot.VISIBLE);
+ myXYPlot_LEFT.redraw();
+ } else {
+ myXYPlot_LEFT.setVisibility(XYPlot.INVISIBLE);
+ }
+
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (series2_onRight) {
+ series2_onRight = false;
+ } else {
+ series2_onRight = true;
+ }
+ updateView();
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/DynamicXYPlotActivity.java b/Examples/DemoApp/src/com/androidplot/demos/DynamicXYPlotActivity.java
new file mode 100644
index 0000000..b4e6456
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/DynamicXYPlotActivity.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2013 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.os.Bundle;
+import com.androidplot.Plot;
+import com.androidplot.util.PixelUtils;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.*;
+
+import java.text.DecimalFormat;
+import java.util.Observable;
+import java.util.Observer;
+
+public class DynamicXYPlotActivity extends Activity {
+
+ // redraws a plot whenever an update is received:
+ private class MyPlotUpdater implements Observer {
+ Plot plot;
+
+ public MyPlotUpdater(Plot plot) {
+ this.plot = plot;
+ }
+
+ @Override
+ public void update(Observable o, Object arg) {
+ plot.redraw();
+ }
+ }
+
+ private XYPlot dynamicPlot;
+ private MyPlotUpdater plotUpdater;
+ SampleDynamicXYDatasource data;
+ private Thread myThread;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+
+ // android boilerplate stuff
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.dynamicxyplot_example);
+
+ // get handles to our View defined in layout.xml:
+ dynamicPlot = (XYPlot) findViewById(R.id.dynamicXYPlot);
+
+ plotUpdater = new MyPlotUpdater(dynamicPlot);
+
+ // only display whole numbers in domain labels
+ dynamicPlot.getGraphWidget().setDomainValueFormat(new DecimalFormat("0"));
+
+ // getInstance and position datasets:
+ data = new SampleDynamicXYDatasource();
+ SampleDynamicSeries sine1Series = new SampleDynamicSeries(data, 0, "Sine 1");
+ SampleDynamicSeries sine2Series = new SampleDynamicSeries(data, 1, "Sine 2");
+
+ LineAndPointFormatter formatter1 = new LineAndPointFormatter(
+ Color.rgb(0, 0, 0), null, null, null);
+ formatter1.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
+ formatter1.getLinePaint().setStrokeWidth(10);
+ dynamicPlot.addSeries(sine1Series,
+ formatter1);
+
+ LineAndPointFormatter formatter2 =
+ new LineAndPointFormatter(Color.rgb(0, 0, 200), null, null, null);
+ formatter2.getLinePaint().setStrokeWidth(10);
+ formatter2.getLinePaint().setStrokeJoin(Paint.Join.ROUND);
+
+ //formatter2.getFillPaint().setAlpha(220);
+ dynamicPlot.addSeries(sine2Series, formatter2);
+
+ // hook up the plotUpdater to the data model:
+ data.addObserver(plotUpdater);
+
+ // thin out domain tick labels so they dont overlap each other:
+ dynamicPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
+ dynamicPlot.setDomainStepValue(5);
+
+ dynamicPlot.setRangeStepMode(XYStepMode.INCREMENT_BY_VAL);
+ dynamicPlot.setRangeStepValue(10);
+
+ dynamicPlot.setRangeValueFormat(new DecimalFormat("###.#"));
+
+ // uncomment this line to freeze the range boundaries:
+ dynamicPlot.setRangeBoundaries(-100, 100, BoundaryMode.FIXED);
+
+ // create a dash effect for domain and range grid lines:
+ DashPathEffect dashFx = new DashPathEffect(
+ new float[] {PixelUtils.dpToPix(3), PixelUtils.dpToPix(3)}, 0);
+ dynamicPlot.getGraphWidget().getDomainGridLinePaint().setPathEffect(dashFx);
+ dynamicPlot.getGraphWidget().getRangeGridLinePaint().setPathEffect(dashFx);
+
+
+ }
+
+ @Override
+ public void onResume() {
+ // kick off the data generating thread:
+ myThread = new Thread(data);
+ myThread.start();
+ super.onResume();
+ }
+
+ @Override
+ public void onPause() {
+ data.stopThread();
+ super.onPause();
+ }
+
+ class SampleDynamicXYDatasource implements Runnable {
+
+ // encapsulates management of the observers watching this datasource for update events:
+ class MyObservable extends Observable {
+ @Override
+ public void notifyObservers() {
+ setChanged();
+ super.notifyObservers();
+ }
+ }
+
+ private static final double FREQUENCY = 5; // larger is lower frequency
+ private static final int MAX_AMP_SEED = 100;
+ private static final int MIN_AMP_SEED = 10;
+ private static final int AMP_STEP = 1;
+ public static final int SINE1 = 0;
+ public static final int SINE2 = 1;
+ private static final int SAMPLE_SIZE = 30;
+ private int phase = 0;
+ private int sinAmp = 1;
+ private MyObservable notifier;
+ private boolean keepRunning = false;
+
+ {
+ notifier = new MyObservable();
+ }
+
+ public void stopThread() {
+ keepRunning = false;
+ }
+
+ //@Override
+ public void run() {
+ try {
+ keepRunning = true;
+ boolean isRising = true;
+ while (keepRunning) {
+
+ Thread.sleep(10); // decrease or remove to speed up the refresh rate.
+ phase++;
+ if (sinAmp >= MAX_AMP_SEED) {
+ isRising = false;
+ } else if (sinAmp <= MIN_AMP_SEED) {
+ isRising = true;
+ }
+
+ if (isRising) {
+ sinAmp += AMP_STEP;
+ } else {
+ sinAmp -= AMP_STEP;
+ }
+ notifier.notifyObservers();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public int getItemCount(int series) {
+ return SAMPLE_SIZE;
+ }
+
+ public Number getX(int series, int index) {
+ if (index >= SAMPLE_SIZE) {
+ throw new IllegalArgumentException();
+ }
+ return index;
+ }
+
+ public Number getY(int series, int index) {
+ if (index >= SAMPLE_SIZE) {
+ throw new IllegalArgumentException();
+ }
+ double angle = (index + (phase))/FREQUENCY;
+ double amp = sinAmp * Math.sin(angle);
+ switch (series) {
+ case SINE1:
+ return amp;
+ case SINE2:
+ return -amp;
+ default:
+ throw new IllegalArgumentException();
+ }
+ }
+
+ public void addObserver(Observer observer) {
+ notifier.addObserver(observer);
+ }
+
+ public void removeObserver(Observer observer) {
+ notifier.deleteObserver(observer);
+ }
+
+ }
+
+ class SampleDynamicSeries implements XYSeries {
+ private SampleDynamicXYDatasource datasource;
+ private int seriesIndex;
+ private String title;
+
+ public SampleDynamicSeries(SampleDynamicXYDatasource datasource, int seriesIndex, String title) {
+ this.datasource = datasource;
+ this.seriesIndex = seriesIndex;
+ this.title = title;
+ }
+
+ @Override
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
+ public int size() {
+ return datasource.getItemCount(seriesIndex);
+ }
+
+ @Override
+ public Number getX(int index) {
+ return datasource.getX(seriesIndex, index);
+ }
+
+ @Override
+ public Number getY(int index) {
+ return datasource.getY(seriesIndex, index);
+ }
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/GlobalDefs.java b/Examples/DemoApp/src/com/androidplot/demos/GlobalDefs.java
new file mode 100644
index 0000000..28b74d9
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/GlobalDefs.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+public interface GlobalDefs {
+ static final float PLOT_TITLE_FONT_SIZE_DP = 15;
+ static final float PLOT_DOMAIN_LABEL_FONT_SIZE_DP = 10;
+ static final float PLOT_RANGE_LABEL_FONT_SIZE_DP = 10;
+ static final float PLOT_TICK_LABEL_FONT_SIZE_DP = 10;
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/ListViewActivity.java b/Examples/DemoApp/src/com/androidplot/demos/ListViewActivity.java
new file mode 100644
index 0000000..d80ac50
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/ListViewActivity.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import com.androidplot.Plot;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.LineAndPointFormatter;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYPlot;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+public class ListViewActivity extends Activity {
+ private static final int NUM_PLOTS = 10;
+ private static final int NUM_POINTS_PER_SERIES = 10;
+ private static final int NUM_SERIES_PER_PLOT = 5;
+ private ListView lv;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.listview_example);
+ lv = (ListView) findViewById(R.id.listView1);
+ lv.setAdapter(new MyViewAdapter(getApplicationContext(), R.layout.listview_example_item, null));
+ }
+
+ class MyViewAdapter extends ArrayAdapter<View> {
+ public MyViewAdapter(Context context, int resId, List<View> views) {
+ super(context, resId, views);
+ }
+
+ @Override
+ public int getCount() {
+ return 5;
+ }
+
+ @Override
+ public View getView(int pos, View convertView, ViewGroup parent) {
+ LayoutInflater inf = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ View v = convertView;
+ if (v == null) {
+ v = inf.inflate(R.layout.listview_example_item, parent, false);
+ }
+
+ Plot p = (XYPlot) v.findViewById(R.id.xyplot);
+ Random generator = new Random();
+
+ for (int k = 0; k < NUM_SERIES_PER_PLOT; k++) {
+ ArrayList<Number> nums = new ArrayList<Number>();
+ for (int j = 0; j < NUM_POINTS_PER_SERIES; j++) {
+ nums.add(generator.nextFloat());
+ }
+
+ double rl = Math.random();
+ double gl = Math.random();
+ double bl = Math.random();
+
+ double rp = Math.random();
+ double gp = Math.random();
+ double bp = Math.random();
+
+ XYSeries series = new SimpleXYSeries(nums, SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "S" + k);
+ p.addSeries(series, new LineAndPointFormatter(
+ Color.rgb(new Double(rl * 255).intValue(), new Double(gl * 255).intValue(), new Double(bl * 255).intValue()),
+ Color.rgb(new Double(rp * 255).intValue(), new Double(gp * 255).intValue(), new Double(bp * 255).intValue()),
+ null, null));
+ }
+ return v;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Examples/DemoApp/src/com/androidplot/demos/MainActivity.java b/Examples/DemoApp/src/com/androidplot/demos/MainActivity.java
new file mode 100644
index 0000000..51c1441
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/MainActivity.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+public class MainActivity extends Activity
+{
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ Button startSimplePieExButton = (Button) findViewById(R.id.startSimplePieExButton);
+ startSimplePieExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, SimplePieChartActivity.class));
+ }
+ });
+
+ Button startDynamicXYExButton = (Button)findViewById(R.id.startDynamicXYExButton);
+ startDynamicXYExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, DynamicXYPlotActivity.class));
+ }
+ });
+
+ Button startSimpleXYExButton = (Button) findViewById(R.id.startSimpleXYExButton);
+ startSimpleXYExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, SimpleXYPlotActivity.class));
+ }
+ });
+
+ Button startBarPlotExButton = (Button) findViewById(R.id.startBarPlotExButton);
+ startBarPlotExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, BarPlotExampleActivity.class));
+ }
+ });
+
+ Button startOrSensorExButton = (Button) findViewById(R.id.startOrSensorExButton);
+ startOrSensorExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, OrientationSensorExampleActivity.class));
+ }
+ });
+
+ Button startTimeSeriesExButon = (Button)findViewById(R.id.startTimeSeriesExButton);
+ startTimeSeriesExButon.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, TimeSeriesActivity.class));
+ }
+ });
+
+ Button startStepChartExButton = (Button)findViewById(R.id.startStepChartExButton);
+ startStepChartExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, StepChartExampleActivity.class));
+ }
+ });
+
+ Button startScrollZoomExButton = (Button)findViewById(R.id.startScrollZoomButton);
+ startScrollZoomExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, TouchZoomExampleActivity.class));
+ }
+ });
+
+ Button startXyRegionExampleButton = (Button)findViewById(R.id.startXyRegionExampleButton);
+ startXyRegionExampleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, XYRegionExampleActivity.class));
+ }
+ });
+
+
+ Button listViewExButton = (Button)findViewById(R.id.startXyListViewExButton);
+ listViewExButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, ListViewActivity.class));
+ }
+ });
+
+ Button startDualScaleExampleButton = (Button)findViewById(R.id.startDualScaleExampleButton);
+ startDualScaleExampleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, DualScaleXYPlotExampleActivity.class));
+ }
+ });
+
+ Button startXYPlotWithBgImgExampleButton = (Button)findViewById(R.id.startXYPlotWithBgImgExample);
+ startXYPlotWithBgImgExampleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(MainActivity.this, XYPlotWithBgImgActivity.class));
+ }
+ });
+
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/OrientationSensorExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/OrientationSensorExampleActivity.java
new file mode 100644
index 0000000..23012bd
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/OrientationSensorExampleActivity.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Color;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import com.androidplot.Plot;
+import com.androidplot.util.PlotStatistics;
+import com.androidplot.util.Redrawer;
+import com.androidplot.xy.*;
+import java.text.DecimalFormat;
+import java.util.Arrays;
+
+// Monitor the phone's orientation sensor and plot the resulting azimuth pitch and roll values.
+// See: http://developer.android.com/reference/android/hardware/SensorEvent.html
+public class OrientationSensorExampleActivity extends Activity implements SensorEventListener
+{
+
+ private static final int HISTORY_SIZE = 300; // number of points to plot in history
+ private SensorManager sensorMgr = null;
+ private Sensor orSensor = null;
+
+ private XYPlot aprLevelsPlot = null;
+ private XYPlot aprHistoryPlot = null;
+
+ private CheckBox hwAcceleratedCb;
+ private CheckBox showFpsCb;
+ //private SimpleXYSeries aprLevelsSeries = null;
+ private SimpleXYSeries aLvlSeries;
+ private SimpleXYSeries pLvlSeries;
+ private SimpleXYSeries rLvlSeries;
+ private SimpleXYSeries azimuthHistorySeries = null;
+ private SimpleXYSeries pitchHistorySeries = null;
+ private SimpleXYSeries rollHistorySeries = null;
+
+ private Redrawer redrawer;
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.orientation_sensor_example);
+
+ // setup the APR Levels plot:
+ aprLevelsPlot = (XYPlot) findViewById(R.id.aprLevelsPlot);
+ aprLevelsPlot.setDomainBoundaries(-1, 1, BoundaryMode.FIXED);
+ aprLevelsPlot.getGraphWidget().getDomainLabelPaint().setColor(Color.TRANSPARENT);
+
+ aLvlSeries = new SimpleXYSeries("A");
+ pLvlSeries = new SimpleXYSeries("P");
+ rLvlSeries = new SimpleXYSeries("R");
+
+ aprLevelsPlot.addSeries(aLvlSeries,
+ new BarFormatter(Color.rgb(0, 200, 0), Color.rgb(0, 80, 0)));
+ aprLevelsPlot.addSeries(pLvlSeries,
+ new BarFormatter(Color.rgb(200, 0, 0), Color.rgb(0, 80, 0)));
+ aprLevelsPlot.addSeries(rLvlSeries,
+ new BarFormatter(Color.rgb(0, 0, 200), Color.rgb(0, 80, 0)));
+
+ aprLevelsPlot.setDomainStepValue(3);
+ aprLevelsPlot.setTicksPerRangeLabel(3);
+
+ // per the android documentation, the minimum and maximum readings we can get from
+ // any of the orientation sensors is -180 and 359 respectively so we will fix our plot's
+ // boundaries to those values. If we did not do this, the plot would auto-range which
+ // can be visually confusing in the case of dynamic plots.
+ aprLevelsPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
+
+ // update our domain and range axis labels:
+ aprLevelsPlot.setDomainLabel("");
+ aprLevelsPlot.getDomainLabelWidget().pack();
+ aprLevelsPlot.setRangeLabel("Angle (Degs)");
+ aprLevelsPlot.getRangeLabelWidget().pack();
+ aprLevelsPlot.setGridPadding(15, 0, 15, 0);
+ aprLevelsPlot.setRangeValueFormat(new DecimalFormat("#"));
+
+ // setup the APR History plot:
+ aprHistoryPlot = (XYPlot) findViewById(R.id.aprHistoryPlot);
+
+ azimuthHistorySeries = new SimpleXYSeries("Az.");
+ azimuthHistorySeries.useImplicitXVals();
+ pitchHistorySeries = new SimpleXYSeries("Pitch");
+ pitchHistorySeries.useImplicitXVals();
+ rollHistorySeries = new SimpleXYSeries("Roll");
+ rollHistorySeries.useImplicitXVals();
+
+ aprHistoryPlot.setRangeBoundaries(-180, 359, BoundaryMode.FIXED);
+ aprHistoryPlot.setDomainBoundaries(0, HISTORY_SIZE, BoundaryMode.FIXED);
+ aprHistoryPlot.addSeries(azimuthHistorySeries,
+ new LineAndPointFormatter(
+ Color.rgb(100, 100, 200), null, null, null));
+ aprHistoryPlot.addSeries(pitchHistorySeries,
+ new LineAndPointFormatter(
+ Color.rgb(100, 200, 100), null, null, null));
+ aprHistoryPlot.addSeries(rollHistorySeries,
+ new LineAndPointFormatter(
+ Color.rgb(200, 100, 100), null, null, null));
+ aprHistoryPlot.setDomainStepMode(XYStepMode.INCREMENT_BY_VAL);
+ aprHistoryPlot.setDomainStepValue(HISTORY_SIZE/10);
+ aprHistoryPlot.setTicksPerRangeLabel(3);
+ aprHistoryPlot.setDomainLabel("Sample Index");
+ aprHistoryPlot.getDomainLabelWidget().pack();
+ aprHistoryPlot.setRangeLabel("Angle (Degs)");
+ aprHistoryPlot.getRangeLabelWidget().pack();
+
+ aprHistoryPlot.setRangeValueFormat(new DecimalFormat("#"));
+ aprHistoryPlot.setDomainValueFormat(new DecimalFormat("#"));
+
+ // setup checkboxes:
+ hwAcceleratedCb = (CheckBox) findViewById(R.id.hwAccelerationCb);
+ final PlotStatistics levelStats = new PlotStatistics(1000, false);
+ final PlotStatistics histStats = new PlotStatistics(1000, false);
+
+ aprLevelsPlot.addListener(levelStats);
+ aprHistoryPlot.addListener(histStats);
+ hwAcceleratedCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ if(b) {
+ aprLevelsPlot.setLayerType(View.LAYER_TYPE_NONE, null);
+ aprHistoryPlot.setLayerType(View.LAYER_TYPE_NONE, null);
+ } else {
+ aprLevelsPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ aprHistoryPlot.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ }
+ }
+ });
+
+ showFpsCb = (CheckBox) findViewById(R.id.showFpsCb);
+ showFpsCb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ levelStats.setAnnotatePlotEnabled(b);
+ histStats.setAnnotatePlotEnabled(b);
+ }
+ });
+
+ // get a ref to the BarRenderer so we can make some changes to it:
+ BarRenderer barRenderer = (BarRenderer) aprLevelsPlot.getRenderer(BarRenderer.class);
+ if(barRenderer != null) {
+ // make our bars a little thicker than the default so they can be seen better:
+ barRenderer.setBarWidth(25);
+ }
+
+ // register for orientation sensor events:
+ sensorMgr = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
+ for (Sensor sensor : sensorMgr.getSensorList(Sensor.TYPE_ORIENTATION)) {
+ if (sensor.getType() == Sensor.TYPE_ORIENTATION) {
+ orSensor = sensor;
+ }
+ }
+
+ // if we can't access the orientation sensor then exit:
+ if (orSensor == null) {
+ System.out.println("Failed to attach to orSensor.");
+ cleanup();
+ }
+
+ sensorMgr.registerListener(this, orSensor, SensorManager.SENSOR_DELAY_UI);
+
+ redrawer = new Redrawer(
+ Arrays.asList(new Plot[]{aprHistoryPlot, aprLevelsPlot}),
+ 100, false);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ redrawer.start();
+ }
+
+ @Override
+ public void onPause() {
+ redrawer.pause();
+ super.onPause();
+ }
+
+ @Override
+ public void onDestroy() {
+ redrawer.finish();
+ super.onDestroy();
+ }
+
+ private void cleanup() {
+ // aunregister with the orientation sensor before exiting:
+ sensorMgr.unregisterListener(this);
+ finish();
+ }
+
+
+ // Called whenever a new orSensor reading is taken.
+ @Override
+ public synchronized void onSensorChanged(SensorEvent sensorEvent) {
+
+ // update level data:
+ aLvlSeries.setModel(Arrays.asList(
+ new Number[]{sensorEvent.values[0]}),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
+
+ pLvlSeries.setModel(Arrays.asList(
+ new Number[]{sensorEvent.values[1]}),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
+
+ rLvlSeries.setModel(Arrays.asList(
+ new Number[]{sensorEvent.values[2]}),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY);
+
+ // get rid the oldest sample in history:
+ if (rollHistorySeries.size() > HISTORY_SIZE) {
+ rollHistorySeries.removeFirst();
+ pitchHistorySeries.removeFirst();
+ azimuthHistorySeries.removeFirst();
+ }
+
+ // add the latest history sample:
+ azimuthHistorySeries.addLast(null, sensorEvent.values[0]);
+ pitchHistorySeries.addLast(null, sensorEvent.values[1]);
+ rollHistorySeries.addLast(null, sensorEvent.values[2]);
+ }
+
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int i) {
+ // Not interested in this event
+ }
+}
\ No newline at end of file
diff --git a/Examples/DemoApp/src/com/androidplot/demos/SimplePieChartActivity.java b/Examples/DemoApp/src/com/androidplot/demos/SimplePieChartActivity.java
new file mode 100644
index 0000000..f90160b
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/SimplePieChartActivity.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.graphics.*;
+import android.os.Bundle;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import com.androidplot.pie.PieChart;
+import com.androidplot.pie.PieRenderer;
+import com.androidplot.pie.Segment;
+import com.androidplot.pie.SegmentFormatter;
+
+/**
+ * The simplest possible example of using AndroidPlot to plot some data.
+ */
+public class SimplePieChartActivity extends Activity
+{
+
+ private TextView donutSizeTextView;
+ private SeekBar donutSizeSeekBar;
+
+ private PieChart pie;
+
+ private Segment s1;
+ private Segment s2;
+ private Segment s3;
+ private Segment s4;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.pie_chart);
+
+ // initialize our XYPlot reference:
+ pie = (PieChart) findViewById(R.id.mySimplePieChart);
+
+
+ donutSizeSeekBar = (SeekBar) findViewById(R.id.donutSizeSeekBar);
+
+ donutSizeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int i, boolean b) {}
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {}
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ pie.getRenderer(PieRenderer.class).setDonutSize(seekBar.getProgress()/100f,
+ PieRenderer.DonutMode.PERCENT);
+ pie.redraw();
+ updateDonutText();
+ }
+ });
+
+ donutSizeTextView = (TextView) findViewById(R.id.donutSizeTextView);
+ updateDonutText();
+
+ s1 = new Segment("s1", 10);
+ s2 = new Segment("s2", 1);
+ s3 = new Segment("s3", 10);
+ s4 = new Segment("s4", 10);
+
+ EmbossMaskFilter emf = new EmbossMaskFilter(
+ new float[]{1, 1, 1}, 0.4f, 10, 8.2f);
+
+ SegmentFormatter sf1 = new SegmentFormatter();
+ sf1.configure(getApplicationContext(), R.xml.pie_segment_formatter1);
+
+ sf1.getFillPaint().setMaskFilter(emf);
+
+ SegmentFormatter sf2 = new SegmentFormatter();
+ sf2.configure(getApplicationContext(), R.xml.pie_segment_formatter2);
+
+ sf2.getFillPaint().setMaskFilter(emf);
+
+ SegmentFormatter sf3 = new SegmentFormatter();
+ sf3.configure(getApplicationContext(), R.xml.pie_segment_formatter3);
+
+ sf3.getFillPaint().setMaskFilter(emf);
+
+ SegmentFormatter sf4 = new SegmentFormatter();
+ sf4.configure(getApplicationContext(), R.xml.pie_segment_formatter4);
+
+ sf4.getFillPaint().setMaskFilter(emf);
+
+ pie.addSeries(s1, sf1);
+ pie.addSeries(s2, sf2);
+ pie.addSeries(s3, sf3);
+ pie.addSeries(s4, sf4);
+
+ pie.getBorderPaint().setColor(Color.TRANSPARENT);
+ pie.getBackgroundPaint().setColor(Color.TRANSPARENT);
+ }
+
+ protected void updateDonutText() {
+ donutSizeTextView.setText(donutSizeSeekBar.getProgress() + "%");
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/SimpleXYPlotActivity.java b/Examples/DemoApp/src/com/androidplot/demos/SimpleXYPlotActivity.java
new file mode 100644
index 0000000..985e5ff
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/SimpleXYPlotActivity.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.WindowManager;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.*;
+import java.util.Arrays;
+
+/**
+ * A straightforward example of using AndroidPlot to plot some data.
+ */
+public class SimpleXYPlotActivity extends Activity
+{
+
+ private XYPlot plot;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+
+ // fun little snippet that prevents users from taking screenshots
+ // on ICS+ devices :-)
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
+ WindowManager.LayoutParams.FLAG_SECURE);
+ setContentView(R.layout.simple_xy_plot_example);
+
+ // initialize our XYPlot reference:
+ plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
+
+ // Create a couple arrays of y-values to plot:
+ Number[] series1Numbers = {1, 8, 5, 2, 7, 4};
+ Number[] series2Numbers = {4, 6, 3, 8, 2, 10};
+
+ // Turn the above arrays into XYSeries':
+ XYSeries series1 = new SimpleXYSeries(
+ Arrays.asList(series1Numbers), // SimpleXYSeries takes a List so turn our array into a List
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
+ "Series1"); // Set the display title of the series
+
+ // same as above
+ XYSeries series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
+
+ // Create a formatter to use for drawing a series using LineAndPointRenderer
+ // and configure it from xml:
+ LineAndPointFormatter series1Format = new LineAndPointFormatter();
+ series1Format.setPointLabelFormatter(new PointLabelFormatter());
+ series1Format.configure(getApplicationContext(),
+ R.xml.line_point_formatter_with_plf1);
+
+ // add a new series' to the xyplot:
+ plot.addSeries(series1, series1Format);
+
+ // same as above:
+ LineAndPointFormatter series2Format = new LineAndPointFormatter();
+ series2Format.setPointLabelFormatter(new PointLabelFormatter());
+ series2Format.configure(getApplicationContext(),
+ R.xml.line_point_formatter_with_plf2);
+ plot.addSeries(series2, series2Format);
+
+ // reduce the number of range labels
+ plot.setTicksPerRangeLabel(3);
+ plot.getGraphWidget().setDomainLabelOrientation(-45);
+
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/StepChartExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/StepChartExampleActivity.java
new file mode 100644
index 0000000..660d03a
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/StepChartExampleActivity.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+
+import android.app.Activity;
+import android.graphics.*;
+import android.os.Bundle;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.*;
+
+import java.text.DecimalFormat;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+import java.util.Arrays;
+
+public class StepChartExampleActivity extends Activity
+{
+
+ private XYPlot mySimpleXYPlot;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.step_chart_example);
+
+ // initialize our XYPlot reference:
+ mySimpleXYPlot = (XYPlot) findViewById(R.id.stepChartExamplePlot);
+
+ // y-vals to plot:
+ Number[] series1Numbers = {1, 2, 3, 4, 2, 3, 4, 2, 2, 2, 3, 4, 2, 3, 2, 2};
+ // create our series from our array of nums:
+ XYSeries series2 = new SimpleXYSeries(
+ Arrays.asList(series1Numbers),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,
+ "Thread #1");
+
+ //mySimpleXYPlot.getLayoutManager().remove(mySimpleXYPlot.getLegendWidget());
+
+
+ mySimpleXYPlot.getGraphWidget().getGridBackgroundPaint().setColor(Color.WHITE);
+ mySimpleXYPlot.getGraphWidget().getDomainGridLinePaint().setColor(Color.BLACK);
+ mySimpleXYPlot.getGraphWidget().getDomainGridLinePaint().setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
+ mySimpleXYPlot.getGraphWidget().getRangeGridLinePaint().setColor(Color.BLACK);
+ mySimpleXYPlot.getGraphWidget().getRangeGridLinePaint().setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
+ mySimpleXYPlot.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
+ mySimpleXYPlot.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
+ mySimpleXYPlot.getGraphWidget().setMarginRight(5);
+
+ // Create a formatter to use for drawing a series using LineAndPointRenderer:
+ LineAndPointFormatter series1Format = new LineAndPointFormatter(
+ Color.rgb(0, 100, 0), // line color
+ Color.rgb(0, 100, 0), // point color
+ Color.rgb(100, 200, 0), null); // fill color
+
+
+ // setup our line fill paint to be a slightly transparent gradient:
+ Paint lineFill = new Paint();
+ lineFill.setAlpha(200);
+ lineFill.setShader(new LinearGradient(0, 0, 0, 250, Color.WHITE, Color.BLUE, Shader.TileMode.MIRROR));
+
+ StepFormatter stepFormatter = new StepFormatter(Color.rgb(0, 0,0), Color.BLUE);
+ stepFormatter.getLinePaint().setStrokeWidth(1);
+
+ stepFormatter.getLinePaint().setAntiAlias(false);
+ stepFormatter.setFillPaint(lineFill);
+ mySimpleXYPlot.addSeries(series2, stepFormatter);
+
+ // adjust the domain/range ticks to make more sense; label per tick for range and label per 5 ticks domain:
+ mySimpleXYPlot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 1);
+ mySimpleXYPlot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1);
+ mySimpleXYPlot.setTicksPerRangeLabel(1);
+ mySimpleXYPlot.setTicksPerDomainLabel(5);
+
+ // customize our domain/range labels
+ //mySimpleXYPlot.setDomainLabel("Time (Secs)");
+ //mySimpleXYPlot.setRangeLabel("Server State");
+
+ //mySimpleXYPlot.getGraphWidget().getGridLinePaint().setAlpha(0);
+
+
+
+ // get rid of decimal points in our domain labels:
+ mySimpleXYPlot.setDomainValueFormat(new DecimalFormat("0"));
+
+ // create a custom formatter to draw our state names as range tick labels:
+ mySimpleXYPlot.setRangeValueFormat(new Format() {
+ @Override
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+ Number num = (Number) obj;
+ switch(num.intValue()) {
+ case 1:
+ toAppendTo.append("Init");
+ break;
+ case 2:
+ toAppendTo.append("Idle");
+ break;
+ case 3:
+ toAppendTo.append("Recv");
+ break;
+ case 4:
+ toAppendTo.append("Send");
+ break;
+ default:
+ toAppendTo.append("Unknown");
+ break;
+ }
+ return toAppendTo;
+ }
+
+ @Override
+ public Object parseObject(String source, ParsePosition pos) {
+ return null;
+ }
+ });
+
+ // by default, AndroidPlot displays developer guides to aid in laying out your plot.
+ // To get rid of them call disableAllMarkup():
+ //mySimpleXYPlot.disableAllMarkup();
+
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/TimeSeriesActivity.java b/Examples/DemoApp/src/com/androidplot/demos/TimeSeriesActivity.java
new file mode 100644
index 0000000..0e7904c
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/TimeSeriesActivity.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.graphics.*;
+import android.os.Bundle;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.*;
+
+import java.text.*;
+import java.util.Arrays;
+import java.util.Date;
+
+public class TimeSeriesActivity extends Activity
+{
+
+ private XYPlot plot1;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.time_series_example);
+
+ plot1 = (XYPlot) findViewById(R.id.plot1);
+ Number[] numSightings = {5, 8, 9, 2, 5};
+
+ // an array of years in milliseconds:
+ Number[] years = {
+ 978307200, // 2001
+ 1009843200, // 2002
+ 1041379200, // 2003
+ 1072915200, // 2004
+ 1104537600 // 2005
+ };
+ // create our series from our array of nums:
+ XYSeries series2 = new SimpleXYSeries(
+ Arrays.asList(years),
+ Arrays.asList(numSightings),
+ "Sightings in USA");
+
+ plot1.getGraphWidget().getGridBackgroundPaint().setColor(Color.WHITE);
+ plot1.getGraphWidget().getDomainGridLinePaint().setColor(Color.BLACK);
+ plot1.getGraphWidget().getDomainGridLinePaint().
+ setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
+ plot1.getGraphWidget().getRangeGridLinePaint().setColor(Color.BLACK);
+ plot1.getGraphWidget().getRangeGridLinePaint().
+ setPathEffect(new DashPathEffect(new float[]{1, 1}, 1));
+ plot1.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
+ plot1.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
+
+ // Create a formatter to use for drawing a series using LineAndPointRenderer:
+ LineAndPointFormatter series1Format = new LineAndPointFormatter(
+ Color.rgb(0, 100, 0), // line color
+ Color.rgb(0, 100, 0), // point color
+ Color.rgb(100, 200, 0), null); // fill color
+
+
+ // setup our line fill paint to be a slightly transparent gradient:
+ Paint lineFill = new Paint();
+ lineFill.setAlpha(200);
+
+ // ugly usage of LinearGradient. unfortunately there's no way to determine the actual size of
+ // a View from within onCreate. one alternative is to specify a dimension in resources
+ // and use that accordingly. at least then the values can be customized for the device type and orientation.
+ lineFill.setShader(new LinearGradient(0, 0, 200, 200, Color.WHITE, Color.GREEN, Shader.TileMode.CLAMP));
+
+ LineAndPointFormatter formatter =
+ new LineAndPointFormatter(Color.rgb(0, 0,0), Color.BLUE, Color.RED, null);
+ formatter.setFillPaint(lineFill);
+ plot1.getGraphWidget().setPaddingRight(2);
+ plot1.addSeries(series2, formatter);
+
+ // draw a domain tick for each year:
+ plot1.setDomainStep(XYStepMode.SUBDIVIDE, years.length);
+
+ // customize our domain/range labels
+ plot1.setDomainLabel("Year");
+ plot1.setRangeLabel("# of Sightings");
+
+ // get rid of decimal points in our range labels:
+ plot1.setRangeValueFormat(new DecimalFormat("0"));
+
+ plot1.setDomainValueFormat(new Format() {
+
+ // create a simple date format that draws on the year portion of our timestamp.
+ // see http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html
+ // for a full description of SimpleDateFormat.
+ private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy");
+
+ @Override
+ public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+
+ // because our timestamps are in seconds and SimpleDateFormat expects milliseconds
+ // we multiply our timestamp by 1000:
+ long timestamp = ((Number) obj).longValue() * 1000;
+ Date date = new Date(timestamp);
+ return dateFormat.format(date, toAppendTo, pos);
+ }
+
+ @Override
+ public Object parseObject(String source, ParsePosition pos) {
+ return null;
+
+ }
+ });
+
+ // by default, AndroidPlot displays developer guides to aid in laying out your plot.
+ // To get rid of them call disableAllMarkup():
+ //plot1.disableAllMarkup();
+ }
+}
\ No newline at end of file
diff --git a/Examples/DemoApp/src/com/androidplot/demos/TouchZoomExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/TouchZoomExampleActivity.java
new file mode 100644
index 0000000..65c5c71
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/TouchZoomExampleActivity.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import java.text.DecimalFormat;
+import java.util.Random;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.util.FloatMath;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.widget.Button;
+
+import com.androidplot.Plot;
+import com.androidplot.xy.BoundaryMode;
+import com.androidplot.xy.LineAndPointFormatter;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYPlot;
+
+/***********************************
+ * @author David Buezas (david.buezas at gmail.com)
+ * Feel free to copy, modify and use the source as it fits you.
+ * 09/27/2012 nfellows - updated for 0.5.1 and made a few simplifications
+ */
+public class TouchZoomExampleActivity extends Activity implements OnTouchListener {
+ private static final int SERIES_SIZE = 200;
+ private XYPlot mySimpleXYPlot;
+ private Button resetButton;
+ private SimpleXYSeries[] series = null;
+ private PointF minXY;
+ private PointF maxXY;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.touch_zoom_example);
+ resetButton = (Button) findViewById(R.id.resetButton);
+ resetButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ minXY.x = series[0].getX(0).floatValue();
+ maxXY.x = series[3].getX(series[3].size() - 1).floatValue();
+ mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.FIXED);
+
+ // pre 0.5.1 users should use postRedraw() instead.
+ mySimpleXYPlot.redraw();
+ }
+ });
+ mySimpleXYPlot = (XYPlot) findViewById(R.id.mySimpleXYPlot);
+ mySimpleXYPlot.setOnTouchListener(this);
+ mySimpleXYPlot.getGraphWidget().setTicksPerRangeLabel(2);
+ mySimpleXYPlot.getGraphWidget().setTicksPerDomainLabel(2);
+ mySimpleXYPlot.getGraphWidget().getBackgroundPaint().setColor(Color.TRANSPARENT);
+ mySimpleXYPlot.getGraphWidget().setRangeValueFormat(
+ new DecimalFormat("#####"));
+ mySimpleXYPlot.getGraphWidget().setDomainValueFormat(
+ new DecimalFormat("#####.#"));
+ mySimpleXYPlot.getGraphWidget().setRangeLabelWidth(25);
+ mySimpleXYPlot.setRangeLabel("");
+ mySimpleXYPlot.setDomainLabel("");
+
+ mySimpleXYPlot.setBorderStyle(Plot.BorderStyle.NONE, null, null);
+ //mySimpleXYPlot.disableAllMarkup();
+ series = new SimpleXYSeries[4];
+ int scale = 1;
+ for (int i = 0; i < 4; i++, scale *= 5) {
+ series[i] = new SimpleXYSeries("S" + i);
+ populateSeries(series[i], scale);
+ }
+ mySimpleXYPlot.addSeries(series[3],
+ new LineAndPointFormatter(Color.rgb(50, 0, 0), null,
+ Color.rgb(100, 0, 0), null));
+ mySimpleXYPlot.addSeries(series[2],
+ new LineAndPointFormatter(Color.rgb(50, 50, 0), null,
+ Color.rgb(100, 100, 0), null));
+ mySimpleXYPlot.addSeries(series[1],
+ new LineAndPointFormatter(Color.rgb(0, 50, 0), null,
+ Color.rgb(0, 100, 0), null));
+ mySimpleXYPlot.addSeries(series[0],
+ new LineAndPointFormatter(Color.rgb(0, 0, 0), null,
+ Color.rgb(0, 0, 150), null));
+ mySimpleXYPlot.redraw();
+ mySimpleXYPlot.calculateMinMaxVals();
+ minXY = new PointF(mySimpleXYPlot.getCalculatedMinX().floatValue(),
+ mySimpleXYPlot.getCalculatedMinY().floatValue());
+ maxXY = new PointF(mySimpleXYPlot.getCalculatedMaxX().floatValue(),
+ mySimpleXYPlot.getCalculatedMaxY().floatValue());
+ }
+
+ private void populateSeries(SimpleXYSeries series, int max) {
+ Random r = new Random();
+ for(int i = 0; i < SERIES_SIZE; i++) {
+ series.addLast(i, r.nextInt(max));
+ }
+ }
+
+ // Definition of the touch states
+ static final int NONE = 0;
+ static final int ONE_FINGER_DRAG = 1;
+ static final int TWO_FINGERS_DRAG = 2;
+ int mode = NONE;
+
+ PointF firstFinger;
+ float distBetweenFingers;
+ boolean stopThread = false;
+
+ @Override
+ public boolean onTouch(View arg0, MotionEvent event) {
+ switch (event.getAction() & MotionEvent.ACTION_MASK) {
+ case MotionEvent.ACTION_DOWN: // Start gesture
+ firstFinger = new PointF(event.getX(), event.getY());
+ mode = ONE_FINGER_DRAG;
+ stopThread = true;
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ mode = NONE;
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN: // second finger
+ distBetweenFingers = spacing(event);
+ // the distance check is done to avoid false alarms
+ if (distBetweenFingers > 5f) {
+ mode = TWO_FINGERS_DRAG;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mode == ONE_FINGER_DRAG) {
+ PointF oldFirstFinger = firstFinger;
+ firstFinger = new PointF(event.getX(), event.getY());
+ scroll(oldFirstFinger.x - firstFinger.x);
+ mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
+ BoundaryMode.FIXED);
+ mySimpleXYPlot.redraw();
+
+ } else if (mode == TWO_FINGERS_DRAG) {
+ float oldDist = distBetweenFingers;
+ distBetweenFingers = spacing(event);
+ zoom(oldDist / distBetweenFingers);
+ mySimpleXYPlot.setDomainBoundaries(minXY.x, maxXY.x,
+ BoundaryMode.FIXED);
+ mySimpleXYPlot.redraw();
+ }
+ break;
+ }
+ return true;
+ }
+
+ private void zoom(float scale) {
+ float domainSpan = maxXY.x - minXY.x;
+ float domainMidPoint = maxXY.x - domainSpan / 2.0f;
+ float offset = domainSpan * scale / 2.0f;
+
+ minXY.x = domainMidPoint - offset;
+ maxXY.x = domainMidPoint + offset;
+
+ minXY.x = Math.min(minXY.x, series[3].getX(series[3].size() - 3)
+ .floatValue());
+ maxXY.x = Math.max(maxXY.x, series[0].getX(1).floatValue());
+ clampToDomainBounds(domainSpan);
+ }
+
+ private void scroll(float pan) {
+ float domainSpan = maxXY.x - minXY.x;
+ float step = domainSpan / mySimpleXYPlot.getWidth();
+ float offset = pan * step;
+ minXY.x = minXY.x + offset;
+ maxXY.x = maxXY.x + offset;
+ clampToDomainBounds(domainSpan);
+ }
+
+ private void clampToDomainBounds(float domainSpan) {
+ float leftBoundary = series[0].getX(0).floatValue();
+ float rightBoundary = series[3].getX(series[3].size() - 1).floatValue();
+ // enforce left scroll boundary:
+ if (minXY.x < leftBoundary) {
+ minXY.x = leftBoundary;
+ maxXY.x = leftBoundary + domainSpan;
+ } else if (maxXY.x > series[3].getX(series[3].size() - 1).floatValue()) {
+ maxXY.x = rightBoundary;
+ minXY.x = rightBoundary - domainSpan;
+ }
+ }
+
+ private float spacing(MotionEvent event) {
+ float x = event.getX(0) - event.getX(1);
+ float y = event.getY(0) - event.getY(1);
+ return FloatMath.sqrt(x * x + y * y);
+ }
+}
+
diff --git a/Examples/DemoApp/src/com/androidplot/demos/XYPlotWithBgImgActivity.java b/Examples/DemoApp/src/com/androidplot/demos/XYPlotWithBgImgActivity.java
new file mode 100644
index 0000000..2f9de9c
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/XYPlotWithBgImgActivity.java
@@ -0,0 +1,131 @@
+package com.androidplot.demos;
+
+import android.app.Activity;
+import android.graphics.*;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ToggleButton;
+import com.androidplot.xy.*;
+
+import java.text.DecimalFormat;
+import java.util.Arrays;
+
+public class XYPlotWithBgImgActivity extends Activity {
+ private static final String TAG = XYPlotWithBgImgActivity.class.getName();
+
+ private int SERIES_LEN = 50;
+ private Shader WHITE_SHADER = new LinearGradient(1, 1, 1, 1, Color.WHITE, Color.WHITE, Shader.TileMode.REPEAT);
+
+ private XYPlot plot;
+ private SimpleXYSeries series;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.xy_plot_with_bq_img_example);
+
+ plot = (XYPlot) findViewById(R.id.graph_metrics);
+
+ //For debugging.
+ //plot.setMarkupEnabled(true);
+
+ // Format Graph
+ plot.getGraphWidget().getBackgroundPaint().setColor(Color.TRANSPARENT);
+ plot.getGraphWidget().getGridBackgroundPaint().setShader(WHITE_SHADER);
+ plot.getGraphWidget().getDomainGridLinePaint().setColor(Color.BLACK);
+ plot.getGraphWidget().getDomainGridLinePaint().setPathEffect(new DashPathEffect(new float[]{3, 3}, 1));
+ plot.getGraphWidget().getRangeGridLinePaint().setColor(Color.BLACK);
+ plot.getGraphWidget().getRangeGridLinePaint().setPathEffect(new DashPathEffect(new float[]{3, 3}, 1));
+ plot.getGraphWidget().getDomainOriginLinePaint().setColor(Color.BLACK);
+ plot.getGraphWidget().getRangeOriginLinePaint().setColor(Color.BLACK);
+ //plot.getGraphWidget().setMarginTop(10);
+
+ // Customize domain and range labels.
+ plot.setDomainLabel("x-vals");
+ plot.setRangeLabel("y-vals");
+ plot.setRangeValueFormat(new DecimalFormat("0"));
+
+ // Make the domain and range step correctly
+ plot.setRangeBoundaries(40, 160, BoundaryMode.FIXED);
+ plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 20);
+ plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 60);
+ plot.setTicksPerDomainLabel(2);
+
+ series = (SimpleXYSeries) getSeries();
+ LineAndPointFormatter lpFormat = new LineAndPointFormatter(
+ Color.BLACK,
+ Color.BLACK,
+ null, // No fill
+ new PointLabelFormatter(Color.TRANSPARENT) // Don't show text at points
+ );
+ plot.addSeries(series, lpFormat);
+ plot.redraw();
+ }
+
+ private SimpleXYSeries getSeries() {
+ Integer[] xVals = new Integer[SERIES_LEN];
+ Integer[] yVals = new Integer[SERIES_LEN];
+
+ xVals[0] = 0;
+ yVals[0] = 0;
+
+ for (int i = 1; i < SERIES_LEN; i += 1){
+ xVals[i] = xVals[i-1] + (int)(Math.random() * i);
+ yVals[i] = (int)(Math.random() * 140);
+ }
+
+ return new SimpleXYSeries(
+ Arrays.asList(xVals),
+ Arrays.asList(yVals),
+ "Sample Series");
+ }
+
+ public void onGraphStyleToggle(View v) {
+ boolean styleOn = ((ToggleButton) v).isChecked();
+
+ /*RectF graphRect = plot.getGraphWidget().getGridRect();
+ float segmentSize = 1.0f/6.0f;
+ LinearGradient lg = new LinearGradient(
+ 0,
+ graphRect.top,
+ 0,
+ graphRect.bottom,
+ new int[]{
+ Color.RED,
+ Color.YELLOW,
+ Color.GREEN,
+ Color.WHITE},
+ new float[]{
+ 0,
+ segmentSize*2,
+ segmentSize*3,
+ segmentSize*5
+ },
+ Shader.TileMode.REPEAT
+ );
+ plot.getGraphWidget().getGridBackgroundPaint().setShader(lg);*/
+
+ RectF rect = plot.getGraphWidget().getGridRect();
+ BitmapShader myShader = new BitmapShader(
+ Bitmap.createScaledBitmap(
+ BitmapFactory.decodeResource(
+ getResources(),
+ R.drawable.graph_background),
+ 1,
+ (int) rect.height(),
+ false),
+ Shader.TileMode.REPEAT,
+ Shader.TileMode.REPEAT);
+ Matrix m = new Matrix();
+ m.setTranslate(rect.left, rect.top);
+ myShader.setLocalMatrix(m);
+ if (styleOn)
+ plot.getGraphWidget().getGridBackgroundPaint().setShader(
+ myShader);
+ else
+ plot.getGraphWidget().getGridBackgroundPaint().setShader(WHITE_SHADER);
+
+ plot.redraw();
+
+ }
+}
diff --git a/Examples/DemoApp/src/com/androidplot/demos/XYRegionExampleActivity.java b/Examples/DemoApp/src/com/androidplot/demos/XYRegionExampleActivity.java
new file mode 100644
index 0000000..67e1b1b
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/XYRegionExampleActivity.java
@@ -0,0 +1,433 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.DashPathEffect;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import com.androidplot.util.PixelUtils;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.ui.*;
+import com.androidplot.xy.*;
+
+import java.text.DecimalFormat;
+import java.text.FieldPosition;
+import java.text.NumberFormat;
+import java.text.ParsePosition;
+import java.util.Arrays;
+
+/**
+ * Demonstration of the usage of Marker and RectRegion.
+ */
+public class XYRegionExampleActivity extends Activity {
+
+ private static final float HOME_RUN_DIST = 325;
+ private static final int LINE_THICKNESS_DP = 2;
+ private static final int POINT_SIZE_DP = 6;
+ private XYPlot plot;
+ private final Number[] timHits = {105, 252, 220, 350, 12, 250, 353};
+ private final Number[] nickHits = {110, 191, 61, 371, 289, 101, 10};
+ private final Number[] joeHits = {25, 375, 364, 128, 178, 289, 346};
+ private final Number[] jamesHits = {250, 285, 295, 211, 311, 365, 241};
+ private LineAndPointFormatter timFormatter;
+ private LineAndPointFormatter nickFormatter;
+ private LineAndPointFormatter joeFormatter;
+ private LineAndPointFormatter jamesFormatter;
+
+ private XYSeries timSeries;
+ private XYSeries nickSeries;
+ private XYSeries joeSeries;
+ private XYSeries jamesSeries;
+
+ private RectRegion shortRegion;
+ private RectRegion warmupRegion;
+ private RectRegion homeRunRegion;
+
+ //private XYRegionFormatter rf1;
+ private XYRegionFormatter shortRegionFormatter;
+ private XYRegionFormatter warmupRegionFormatter;
+ private XYRegionFormatter homeRunRegionFormatter;
+ //private XYRegionFormatter rf5;
+
+ private CheckBox timCB;
+ private CheckBox nickCB;
+ private CheckBox joeCB;
+ private CheckBox jamesCB;
+
+ private CheckBox r2CheckBox;
+ private CheckBox r3CheckBox;
+ private CheckBox r4CheckBox;
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.xyregion_example);
+ plot = (XYPlot) findViewById(R.id.xyRegionExamplePlot);
+ timCB = (CheckBox) findViewById(R.id.s1CheckBox);
+ timCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onS1CheckBoxClicked();
+ }
+ });
+
+ nickCB = (CheckBox) findViewById(R.id.s2CheckBox);
+ nickCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onS2CheckBoxClicked();
+ }
+ });
+
+ joeCB = (CheckBox) findViewById(R.id.s3CheckBox);
+ joeCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onS3CheckBoxClicked();
+ }
+ });
+
+ jamesCB = (CheckBox) findViewById(R.id.s4CheckBox);
+ jamesCB.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onS4CheckBoxClicked();
+ }
+ });
+
+
+
+ r2CheckBox = (CheckBox) findViewById(R.id.r2CheckBox);
+ r2CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onCheckBoxClicked(r2CheckBox, timFormatter, shortRegionFormatter, shortRegion);
+ }
+ });
+
+ r3CheckBox = (CheckBox) findViewById(R.id.r3CheckBox);
+ r3CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onCheckBoxClicked(r3CheckBox, nickFormatter, warmupRegionFormatter, warmupRegion);
+ }
+ });
+
+ r4CheckBox = (CheckBox) findViewById(R.id.r4CheckBox);
+ r4CheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
+ onCheckBoxClicked(r4CheckBox, nickFormatter, homeRunRegionFormatter, homeRunRegion);
+ }
+ });
+
+ seriesSetup();
+ markerSetup();
+ axisLabelSetup();
+ regionSetup();
+ makePlotPretty();
+ }
+
+ private void onS1CheckBoxClicked() {
+ if(timCB.isChecked()) {
+ plot.addSeries(timSeries, timFormatter);
+ r2CheckBox.setEnabled(true);
+ } else {
+ plot.removeSeries(timSeries);
+ r2CheckBox.setEnabled(false);
+ }
+ plot.redraw();
+ }
+
+ private void onS2CheckBoxClicked() {
+ if(nickCB.isChecked()) {
+ plot.addSeries(nickSeries, nickFormatter);
+ r3CheckBox.setEnabled(true);
+ r4CheckBox.setEnabled(true);
+ } else {
+ plot.removeSeries(nickSeries);
+ r3CheckBox.setEnabled(false);
+ r4CheckBox.setEnabled(false);
+ }
+ plot.redraw();
+ }
+
+ private void onS3CheckBoxClicked() {
+ if(joeCB.isChecked()) {
+ plot.addSeries(joeSeries, joeFormatter);
+ } else {
+ plot.removeSeries(joeSeries);
+ }
+ plot.redraw();
+ }
+
+ private void onS4CheckBoxClicked() {
+ if(jamesCB.isChecked()) {
+ plot.addSeries(jamesSeries, jamesFormatter);
+ } else {
+ plot.removeSeries(jamesSeries);
+ }
+ plot.redraw();
+ }
+
+ /**
+ * Processes a check box event
+ * @param cb The checkbox event origin
+ * @param lpf LineAndPointFormatter with which rr and rf are to be added/removed
+ * @param rf The XYRegionFormatter with which rr should be rendered
+ * @param rr The RectRegion to add/remove
+ */
+ private void onCheckBoxClicked(CheckBox cb, LineAndPointFormatter lpf,
+ XYRegionFormatter rf, RectRegion rr) {
+ if(cb.isChecked()) {
+ lpf.removeRegion(rr);
+ } else {
+ lpf.addRegion(rr, rf);
+ }
+ }
+
+ /**
+ * Cleans up the plot's general layout and color scheme
+ */
+ private void makePlotPretty() {
+ // use a 2x5 grid with room for 10 items:
+ plot.getLegendWidget().setTableModel(new DynamicTableModel(4, 2));
+
+ // add a semi-transparent black background to the legend
+ // so it's easier to see overlaid on top of our plot:
+ Paint bgPaint = new Paint();
+ bgPaint.setColor(Color.BLACK);
+ bgPaint.setStyle(Paint.Style.FILL);
+ bgPaint.setAlpha(40);
+
+ plot.getLegendWidget().setBackgroundPaint(bgPaint);
+
+ // adjust the padding of the legend widget to look a little nicer:
+ plot.getLegendWidget().setPadding(5, 5, 5, 5);
+
+ plot.setRangeValueFormat(new NumberFormat() {
+ @Override
+ public StringBuffer format(double value, StringBuffer buffer, FieldPosition field) {
+ return new StringBuffer(value + "'");
+ }
+
+ @Override
+ public StringBuffer format(long value, StringBuffer buffer, FieldPosition field) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public Number parse(String string, ParsePosition position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+ });
+
+ plot.setDomainValueFormat(new DecimalFormat("#"));
+
+ plot.getLegendWidget().setWidth(PixelUtils.dpToPix(100), SizeLayoutType.FILL);
+
+
+ // adjust the legend size so there is enough room
+ // to draw the new legend grid:
+ //plot.getLegendWidget().getHeightMetric().setLayoutType(SizeLayoutType.ABSOLUTE);
+ //plot.getLegendWidget().getWidthMetric().setLayoutType(SizeLayoutType.ABSOLUTE);
+ //plot.getLegendWidget().setSize(
+ // new SizeMetrics(70, SizeLayoutType.ABSOLUTE, 80, SizeLayoutType.ABSOLUTE));
+
+ // reposition the grid so that it rests above the bottom-left
+ // edge of the graph widget:
+
+ plot.getLegendWidget().position(
+ 125,
+ XLayoutStyle.ABSOLUTE_FROM_LEFT,
+ 65,
+ YLayoutStyle.ABSOLUTE_FROM_TOP,
+ AnchorPosition.LEFT_TOP);
+
+ plot.getGraphWidget().setRangeLabelHorizontalOffset(-1);
+
+ // add enough space to ensure range value labels arent cut off on the left/right:
+ plot.getGraphWidget().setRangeLabelWidth(25);
+
+ // add enough space to make sure domain value labels arent cut off on the bottom:
+ plot.getGraphWidget().setDomainLabelWidth(15);
+
+ plot.getGraphWidget().setDomainLabelVerticalOffset(-6);
+
+ plot.setRangeBoundaries(0, BoundaryMode.FIXED, 500, BoundaryMode.FIXED);
+ }
+
+ /**
+ * Create 4 XYSeries from the values defined above add add them to the plot.
+ * Also add some arbitrary regions.
+ */
+ private void seriesSetup() {
+
+
+ // TIM
+ timFormatter = new LineAndPointFormatter(
+ Color.rgb(100, 25, 20),
+ Color.rgb(100, 25, 20),
+ null, null);
+ timFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
+ timFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
+
+ timSeries = new SimpleXYSeries(Arrays.asList(timHits),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Tim");
+
+ plot.addSeries(timSeries, timFormatter);
+
+ // SERIES #2:
+ nickFormatter = new LineAndPointFormatter(
+ Color.rgb(100, 25, 200),
+ Color.rgb(100, 25, 200),
+ null, null);
+ nickFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
+ nickFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
+
+
+
+ nickSeries = new SimpleXYSeries(Arrays.asList(nickHits),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Nick");
+
+ plot.addSeries(nickSeries, nickFormatter);
+
+ // SERIES #3:
+ joeFormatter = new LineAndPointFormatter(
+ Color.rgb(200, 25, 200),
+ Color.rgb(200, 25, 200),
+ null, null);
+ joeFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
+ joeFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
+
+ joeSeries = new SimpleXYSeries(Arrays.asList(joeHits),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Joe");
+
+ plot.addSeries(joeSeries, joeFormatter);
+
+ // SERIES #4:
+ jamesFormatter = new LineAndPointFormatter(
+ Color.rgb(220, 25, 20),
+ Color.rgb(220, 25, 20),
+ null, null);
+
+ jamesFormatter.getLinePaint().setStrokeWidth(PixelUtils.dpToPix(LINE_THICKNESS_DP));
+ jamesFormatter.getVertexPaint().setStrokeWidth(PixelUtils.dpToPix(POINT_SIZE_DP));
+
+ jamesSeries = new SimpleXYSeries(Arrays.asList(jamesHits),
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY,"James");
+ plot.addSeries(jamesSeries, jamesFormatter);
+
+ plot.setRangeStep(XYStepMode.INCREMENT_BY_VAL, 100);
+ //plot.setTicksPerRangeLabel(1);
+ plot.setDomainStep(XYStepMode.INCREMENT_BY_VAL, 1);
+ }
+
+ /**
+ * Add some color coded regions to our axis labels.
+ */
+ private void axisLabelSetup() {
+ // DOMAIN
+ plot.getGraphWidget().addDomainAxisValueLabelRegion(
+ Double.NEGATIVE_INFINITY, 2, new AxisValueLabelFormatter(Color.GRAY));
+ plot.getGraphWidget().addDomainAxisValueLabelRegion(
+ 2, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.WHITE));
+ // RANGE
+ plot.getGraphWidget().addRangeAxisValueLabelRegion(
+ Double.NEGATIVE_INFINITY, HOME_RUN_DIST, new AxisValueLabelFormatter(Color.RED));
+ plot.getGraphWidget().addRangeAxisValueLabelRegion(
+ HOME_RUN_DIST, Double.POSITIVE_INFINITY, new AxisValueLabelFormatter(Color.GREEN));
+ }
+
+ /**
+ * Add some markers to our plot.
+ */
+ private void markerSetup() {
+
+ YValueMarker fenwayLfMarker = new YValueMarker(
+ 380, // y-val to mark
+ "Fenway Park LF Wall", // marker label
+ new XPositionMetric( // object instance to set text positioning on the marker
+ PixelUtils.dpToPix(5), // 5dp offset
+ XLayoutStyle.ABSOLUTE_FROM_RIGHT), // offset origin
+ Color.BLUE, // line paint color
+ Color.BLUE); // text paint color
+
+ YValueMarker attRfMarker = new YValueMarker(
+ 309, // y-val to mark
+ "ATT Park RF Wall", // marker label
+ new XPositionMetric( // object instance to set text positioning on the marker
+ PixelUtils.dpToPix(5), // 5dp offset
+ XLayoutStyle.ABSOLUTE_FROM_RIGHT), // offset origin
+ Color.CYAN, // line paint color
+ Color.CYAN); // text paint color
+
+
+ fenwayLfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
+ attRfMarker.getTextPaint().setTextSize(PixelUtils.dpToPix(14));
+
+ DashPathEffect dpe = new DashPathEffect(
+ new float[]{PixelUtils.dpToPix(2), PixelUtils.dpToPix(2)}, 0);
+
+ fenwayLfMarker.getLinePaint().setPathEffect(dpe);
+ attRfMarker.getLinePaint().setPathEffect(dpe);
+
+ plot.addMarker(fenwayLfMarker);
+ plot.addMarker(attRfMarker);
+ }
+
+ /**
+ * Add some fill regions to our series data
+ */
+ private void regionSetup() {
+
+
+ // and another region:
+ shortRegionFormatter = new XYRegionFormatter(Color.RED);
+ shortRegionFormatter.getPaint().setAlpha(75);
+ shortRegion = new RectRegion(2, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, HOME_RUN_DIST, "Short");
+ timFormatter.addRegion(shortRegion, shortRegionFormatter);
+ nickFormatter.addRegion(shortRegion, shortRegionFormatter);
+ joeFormatter.addRegion(shortRegion, shortRegionFormatter);
+ jamesFormatter.addRegion(shortRegion, shortRegionFormatter);
+
+ // the next three regions are horizontal regions with minY/maxY
+ // set to negative and positive infinity respectively.
+ warmupRegionFormatter = new XYRegionFormatter(Color.WHITE);
+ warmupRegionFormatter.getPaint().setAlpha(75);
+
+ warmupRegion = new RectRegion(0, 2, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, "Warmup");
+ timFormatter.addRegion(warmupRegion, warmupRegionFormatter);
+ nickFormatter.addRegion(warmupRegion, warmupRegionFormatter);
+ joeFormatter.addRegion(warmupRegion, warmupRegionFormatter);
+ jamesFormatter.addRegion(warmupRegion, warmupRegionFormatter);
+
+ homeRunRegionFormatter = new XYRegionFormatter(Color.GREEN);
+ homeRunRegionFormatter.getPaint().setAlpha(75);
+
+ homeRunRegion = new RectRegion(2, Double.POSITIVE_INFINITY, HOME_RUN_DIST, Double.POSITIVE_INFINITY, "H. Run");
+ timFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
+ nickFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
+ joeFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
+ jamesFormatter.addRegion(homeRunRegion, homeRunRegionFormatter);
+
+ nickFormatter.setFillDirection(FillDirection.RANGE_ORIGIN);
+ }
+}
\ No newline at end of file
diff --git a/Examples/DemoApp/src/com/androidplot/demos/widget/DemoAppWidgetProvider.java b/Examples/DemoApp/src/com/androidplot/demos/widget/DemoAppWidgetProvider.java
new file mode 100644
index 0000000..f44a277
--- /dev/null
+++ b/Examples/DemoApp/src/com/androidplot/demos/widget/DemoAppWidgetProvider.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 AndroidPlot.com
+ *
+ * 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 com.androidplot.demos.widget;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.widget.RemoteViews;
+import com.androidplot.demos.R;
+import com.androidplot.xy.XYSeries;
+import com.androidplot.xy.LineAndPointFormatter;
+import com.androidplot.xy.SimpleXYSeries;
+import com.androidplot.xy.XYPlot;
+
+import java.util.Arrays;
+
+public class DemoAppWidgetProvider extends AppWidgetProvider {
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ for (int widgetId : appWidgetIds) {
+ XYPlot plot = new XYPlot(context, "Widget Example");
+ //plot.getLayoutParams().height = 100;
+ //plot.getLayoutParams().width = 100;
+ plot.measure(150,150);
+ plot.layout(0,0,150,150);
+ plot.setDrawingCacheEnabled(true);
+
+ // Create a couple arrays of y-values to plot:
+ Number[] series1Numbers = {1, 8, 5, 2, 7, 4};
+ Number[] series2Numbers = {4, 6, 3, 8, 2, 10};
+
+ // Turn the above arrays into XYSeries':
+ XYSeries series1 = new SimpleXYSeries(
+ Arrays.asList(series1Numbers), // SimpleXYSeries takes a List so turn our array into a List
+ SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
+ "Series1"); // Set the display title of the series
+
+ // same as above
+ XYSeries series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Series2");
+
+ // Create a formatter to use for drawing a series using LineAndPointRenderer:
+ LineAndPointFormatter series1Format = new LineAndPointFormatter(
+ Color.rgb(0, 200, 0), // line color
+ Color.rgb(0, 100, 0), // point color
+ null, null); // fill color (none)
+
+ // add a new series' to the xyplot:
+ plot.addSeries(series1, series1Format);
+
+ // same as above:
+ plot.addSeries(series2,
+ new LineAndPointFormatter(
+ Color.rgb(0, 0, 200), Color.rgb(0, 0, 100), null, null));
+
+
+ // reduce the number of range labels
+ plot.setTicksPerRangeLabel(3);
+
+ // by default, AndroidPlot displays developer guides to aid in laying out your plot.
+ // To get rid of them call disableAllMarkup():
+ //plot.disableAllMarkup();
+
+ Bitmap bmp = plot.getDrawingCache();
+
+ RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.demo_app_widget);
+ rv.setBitmap(R.id.imgView, "setImageBitmap", bmp);
+ appWidgetManager.updateAppWidget(widgetId, rv);
+ }
+ }
+}