Commits

Daniel Nadeau committed 737561f

Initial commit

  • Participants

Comments (0)

Files changed (48)

File HoloGraphLibrary/.classpath

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>

File HoloGraphLibrary/.project

+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>HoloGraphLibrary</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>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

File HoloGraphLibrary/.settings/org.eclipse.jdt.core.prefs

+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6

File HoloGraphLibrary/AndroidManifest.xml

+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.echo.holographlibrary"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="16" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+    </application>
+
+</manifest>

File HoloGraphLibrary/bin/AndroidManifest.xml

+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.echo.holographlibrary"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="8"
+        android:targetSdkVersion="16" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+    </application>
+
+</manifest>

File HoloGraphLibrary/bin/R.txt

+int drawable ic_launcher 0x7f020000
+int drawable popup_nocolor 0x7f020001
+int string app_name 0x7f030000
+int style AppBaseTheme 0x7f040000
+int style AppTheme 0x7f040001

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/Bar.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/BarGraph$OnBarClickedListener.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/BarGraph.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/BuildConfig.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/Line.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/LineGraph$OnPointClickedListener.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/LineGraph.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/LinePoint.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/PieGraph$OnSliceClickedListener.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/PieGraph.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/PieSlice.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/R$attr.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/R$drawable.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/R$string.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/R$style.class

Binary file added.

File HoloGraphLibrary/bin/classes/com/echo/holographlibrary/R.class

Binary file added.

File HoloGraphLibrary/bin/holographlibrary.jar

Binary file added.

File HoloGraphLibrary/bin/jarlist.cache

+# cache for current jar dependecy. DO NOT EDIT.
+# format is <lastModified> <length> <SHA-1> <path>
+# Encoding is UTF-8

File HoloGraphLibrary/bin/res/drawable-hdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/bin/res/drawable-mdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/bin/res/drawable-xhdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/bin/res/drawable-xhdpi/popup_nocolor.9.png

Added
New image

File HoloGraphLibrary/gen/com/echo/holographlibrary/BuildConfig.java

+/** Automatically generated file. DO NOT MODIFY */
+package com.echo.holographlibrary;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}

File HoloGraphLibrary/gen/com/echo/holographlibrary/R.java

+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package com.echo.holographlibrary;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static int ic_launcher=0x7f020000;
+        public static int popup_nocolor=0x7f020001;
+    }
+    public static final class string {
+        public static int app_name=0x7f030000;
+    }
+    public static final class style {
+        /** 
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+         */
+        public static int AppBaseTheme=0x7f040000;
+        /**  Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+         */
+        public static int AppTheme=0x7f040001;
+    }
+}

File HoloGraphLibrary/libs/android-support-v4.jar

Binary file added.

File HoloGraphLibrary/proguard-project.txt

+# 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 *;
+#}

File HoloGraphLibrary/project.properties

+# 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
+
+# Project target.
+target=android-17
+android.library=true

File HoloGraphLibrary/res/drawable-hdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/res/drawable-mdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/res/drawable-xhdpi/ic_launcher.png

Added
New image

File HoloGraphLibrary/res/drawable-xhdpi/popup_nocolor.9.png

Added
New image

File HoloGraphLibrary/res/values-v11/styles.xml

+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>

File HoloGraphLibrary/res/values-v14/styles.xml

+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>

File HoloGraphLibrary/res/values/strings.xml

+<resources>
+
+    <string name="app_name">HoloGraphLibrary</string>
+
+</resources>

File HoloGraphLibrary/res/values/styles.xml

+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>

File HoloGraphLibrary/src/com/echo/holographlibrary/Bar.java

+package com.echo.holographlibrary;
+
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.Region;
+
+public class Bar {
+	private int color;
+	private String name;
+	private float value;
+	private Path path;
+	private Region region;
+	
+	public int getColor() {
+		return color;
+	}
+	public void setColor(int color) {
+		this.color = color;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public float getValue() {
+		return value;
+	}
+	public void setValue(float value) {
+		this.value = value;
+	}
+	public Path getPath() {
+		return path;
+	}
+	public void setPath(Path path) {
+		this.path = path;
+	}
+	public Region getRegion() {
+		return region;
+	}
+	public void setRegion(Region region) {
+		this.region = region;
+	}
+	
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/BarGraph.java

+package com.echo.holographlibrary;
+
+import java.util.ArrayList;
+
+import com.echo.holographlibrary.PieGraph.OnSliceClickedListener;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.drawable.NinePatchDrawable;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class BarGraph extends SurfaceView implements SurfaceHolder.Callback {
+
+	private ArrayList<Bar> points = new ArrayList<Bar>();
+	private Paint p;
+	private Rect r;
+	private boolean showBarText = true;
+	private int indexSelected = -1;
+	private OnBarClickedListener listener;
+	
+	public BarGraph(Context context) {
+		super(context);
+	    this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	
+	public BarGraph(Context context, AttributeSet attrs) {
+		super(context, attrs);
+	    this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	
+	public void setShowBarText(boolean show){
+		showBarText = show;
+	}
+	
+	public void setBars(ArrayList<Bar> points){
+		this.points = points;
+		postInvalidate();
+	}
+	
+	public ArrayList<Bar> getBars(){
+		return this.points;
+	}
+
+	public void onDraw(Canvas canvas) {
+		
+		canvas.drawColor(Color.TRANSPARENT);
+		NinePatchDrawable popup = (NinePatchDrawable)this.getResources().getDrawable(R.drawable.popup_nocolor);
+		
+		float maxValue = 0;
+		float padding = 7;
+		int selectPadding = 4;
+		float bottomPadding = 40;
+		
+		if (p == null) p = new Paint();
+		
+		float usableHeight;
+		if (showBarText) {
+			this.p.setTextSize(40);
+			Rect r3 = new Rect();
+			this.p.getTextBounds("$", 0, 1, r3);
+			usableHeight = getHeight()-bottomPadding-Math.abs(r3.top-r3.bottom)-26;
+		} else {
+			usableHeight = getHeight()-bottomPadding;
+		}
+		 
+		
+		p.setColor(Color.BLACK);
+		p.setStrokeWidth(2);
+		p.setAlpha(50);
+		p.setAntiAlias(true);
+		
+		canvas.drawLine(0, getHeight()-bottomPadding+10, getWidth(), getHeight()-bottomPadding+10, p);
+		
+		float barWidth = (getWidth() - (padding*2)*points.size())/points.size();
+		
+		for (Bar p : points) {
+        	maxValue += p.getValue();
+        }
+		
+		r = new Rect();
+		
+		int count = 0;
+		for (Bar p : points) {
+			r.set((int)((padding*2)*count + padding + barWidth*count), (int)(getHeight()-bottomPadding-(usableHeight*(p.getValue()/maxValue))), (int)((padding*2)*count + padding + barWidth*(count+1)), (int)(getHeight()-bottomPadding));
+        	
+			Path path = new Path();
+        	path.addRect(new RectF(r.left-selectPadding, r.top-selectPadding, r.right+selectPadding, r.bottom+selectPadding), Path.Direction.CW);
+        	p.setPath(path);
+        	p.setRegion(new Region(r.left-selectPadding, r.top-selectPadding, r.right+selectPadding, r.bottom+selectPadding));
+			
+        	this.p.setColor(p.getColor());
+        	this.p.setAlpha(255);
+			canvas.drawRect(r, this.p);
+			this.p.setTextSize(20);
+			canvas.drawText(p.getName(), (int)(((r.left+r.right)/2)-(this.p.measureText(p.getName())/2)), getHeight()-5, this.p);
+			if (showBarText){
+				this.p.setTextSize(40);
+				this.p.setColor(Color.WHITE);
+				Rect r2 = new Rect();
+				this.p.getTextBounds("$"+p.getValue(), 0, 1, r2);
+				popup.setBounds((int)(((r.left+r.right)/2)-(this.p.measureText("$"+p.getValue())/2))-14, r.top+(r2.top-r2.bottom)-26, (int)(((r.left+r.right)/2)+(this.p.measureText("$"+p.getValue())/2))+14, r.top);
+				popup.draw(canvas);
+				canvas.drawText("$"+p.getValue(), (int)(((r.left+r.right)/2)-(this.p.measureText("$"+p.getValue())/2)), r.top-20, this.p);
+			}
+			if (indexSelected == count && listener != null) {
+				this.p.setColor(Color.parseColor("#33B5E5"));
+				this.p.setAlpha(100);
+				canvas.drawPath(p.getPath(), this.p);
+				this.p.setAlpha(255);
+			}
+        	count++;
+        }
+	}
+
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+
+	    Point point = new Point();
+	    point.x = (int) event.getX();
+	    point.y = (int) event.getY();
+	    
+	    int count = 0;
+	    for (Bar bar : points){
+	    	Region r = new Region();
+	    	r.setPath(bar.getPath(), bar.getRegion());
+	    	if (r.contains((int)point.x,(int) point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
+	    		indexSelected = count;
+	    	} else if (event.getAction() == MotionEvent.ACTION_UP){
+	    		if (r.contains((int)point.x,(int) point.y) && listener != null){
+	    			listener.onClick(indexSelected);
+	    		}
+	    		indexSelected = -1;
+	    	}
+		    count++;
+	    }
+	    
+	    if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP){
+	    	postInvalidate();
+	    }
+	    
+	    
+
+	    return true;
+	}
+	
+	@Override
+	public void surfaceChanged(SurfaceHolder holder, int format, int width,
+			int height) {}
+
+	@Override
+	public void surfaceCreated(SurfaceHolder holder) {
+		setWillNotDraw(false); 					//Allows us to use invalidate() to call onDraw()
+		postInvalidate();
+	}
+
+	@Override
+	public void surfaceDestroyed(SurfaceHolder holder) {}
+	
+	public void setOnBarClickedListener(OnBarClickedListener listener) {
+		this.listener = listener;
+	}
+	
+	public abstract class OnBarClickedListener {
+		abstract void onClick(int index);
+	}
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/Line.java

+package com.echo.holographlibrary;
+
+import java.util.ArrayList;
+
+public class Line {
+	private ArrayList<LinePoint> points = new ArrayList<LinePoint>();
+	private int color;
+	private boolean showPoints = true;
+	
+	
+	public int getColor() {
+		return color;
+	}
+	public void setColor(int color) {
+		this.color = color;
+	}
+	public ArrayList<LinePoint> getPoints() {
+		return points;
+	}
+	public void setPoints(ArrayList<LinePoint> points) {
+		this.points = points;
+	}
+	public void addPoint(LinePoint point){
+		points.add(point);
+	}
+	public LinePoint getPoint(int index){
+		return points.get(index);
+	}
+	public int getSize(){
+		return points.size();
+	}
+	public boolean isShowingPoints() {
+		return showPoints;
+	}
+	public void setShowingPoints(boolean showPoints) {
+		this.showPoints = showPoints;
+	}
+	
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/LineGraph.java

+package com.echo.holographlibrary;
+
+import java.util.ArrayList;
+
+import com.echo.holographlibrary.BarGraph.OnBarClickedListener;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.AvoidXfermode;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.Path.Direction;
+import android.graphics.PixelFormat;
+import android.graphics.Region;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class LineGraph extends SurfaceView implements SurfaceHolder.Callback {
+	
+	private ArrayList<Line> lines = new ArrayList<Line>();
+	private float minY = 0, minX = 0;
+	private float maxY = 0, maxX = 0;
+	private boolean isMaxYUserSet = false;
+	private int lineToFill = -1;
+	private int indexSelected = -1;
+	private OnPointClickedListener listener;
+	
+	public LineGraph(Context context){
+		super(context);
+		this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	
+	public LineGraph(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	
+	public void addLine(Line line) {
+		lines.add(line);
+	}
+	public ArrayList<Line> getLines() {
+		return lines;
+	}
+	public void setLineToFill(int indexOfLine) {
+		this.lineToFill = indexOfLine;
+	}
+	public int getLineToFill(){
+		return lineToFill;
+	}
+	public void setLines(ArrayList<Line> lines) {
+		this.lines = lines;
+	}
+	public Line getLine(int index) {
+		return lines.get(index);
+	}
+	public int getSize(){
+		return lines.size();
+	}
+	
+	public void setRangeY(float min, float max) {
+		minY = min;
+		maxY = max;
+		isMaxYUserSet = true;
+	}
+	public float getMaxY(){
+		if (isMaxYUserSet){
+			return maxY;
+		} else {
+			maxY = lines.get(0).getPoint(0).getY();
+			for (Line line : lines){
+				for (LinePoint point : line.getPoints()){
+					if (point.getY() > maxY){
+						maxY = point.getY();
+					}
+				}
+			}
+			return maxY;
+		}
+		
+	}
+	public float getMinY(){
+		if (isMaxYUserSet){
+			return minY;
+		} else {
+			float min = lines.get(0).getPoint(0).getY();
+			for (Line line : lines){
+				for (LinePoint point : line.getPoints()){
+					if (point.getY() < min) min = point.getY();
+				}
+			}
+			minY = min;
+			return minY;
+		}
+	}
+	public float getMaxX(){
+		float max = lines.get(0).getPoint(0).getX();
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				if (point.getX() > max) max = point.getX();
+			}
+		}
+		maxX = max;
+		return maxX;
+		
+	}
+	public float getMinX(){
+		float max = lines.get(0).getPoint(0).getX();
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				if (point.getX() < max) max = point.getX();
+			}
+		}
+		maxX = max;
+		return maxX;
+	}
+
+	@Override
+	public void surfaceChanged(SurfaceHolder holder, int format, int width,
+			int height) {}
+
+	@Override
+	public void surfaceCreated(SurfaceHolder holder) {
+		setWillNotDraw(false); 					//Allows us to use invalidate() to call onDraw()
+		postInvalidate();
+	}
+
+	@Override
+	public void surfaceDestroyed(SurfaceHolder holder) {}
+	
+	public void onDraw(Canvas canvas) {
+		Paint paint = new Paint();
+		Path path = new Path();
+		float bottomPadding = 2, topPadding = 10;
+		float sidePadding = 10;
+		float usableHeight = getHeight() - bottomPadding - topPadding;
+		float usableWidth = getWidth() - 2*sidePadding;
+		
+		int lineCount = 0;
+		for (Line line : lines){
+			int count = 0;
+			float firstXPixels = 0, lastXPixels = 0, newYPixels = 0;
+			float lastYPixels = 0, newXPixels = 0;
+			float maxY = getMaxY();
+			float minY = getMinY();
+			float maxX = getMaxX();
+			float minX = getMinX();
+			
+			if (lineCount == lineToFill){
+				
+				Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
+				Canvas c = new Canvas(b);
+				
+				for (LinePoint p : line.getPoints()){
+					float yPercent = (p.getY()-minY)/(maxY - minY);
+					float xPercent = (p.getX()-minX)/(maxX - minX);
+					if (count == 0){
+						lastXPixels = sidePadding + (xPercent*usableWidth);
+						lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
+						firstXPixels = lastXPixels;
+						path.moveTo(lastXPixels, lastYPixels);
+					} else {
+						newXPixels = sidePadding + (xPercent*usableWidth);
+						newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
+						path.lineTo(newXPixels, newYPixels);
+						lastXPixels = newXPixels;
+						lastYPixels = newYPixels;
+					}
+					count++;
+				}
+				path.lineTo(newXPixels, getHeight()-bottomPadding);
+				path.lineTo(getWidth(), getHeight()-bottomPadding);
+				path.lineTo(getWidth(), 0);
+				path.lineTo(0, 0);
+				path.lineTo(0, getHeight()-bottomPadding);
+				path.lineTo(firstXPixels, getHeight()-bottomPadding);
+				path.close();
+					
+				paint.setColor(Color.BLACK);
+				paint.setAlpha(30);
+				paint.setStrokeWidth(2);
+				for (int i = 10; i-getWidth() < getHeight(); i = i+20){
+					c.drawLine(i, getHeight()-bottomPadding, 0, getHeight()-bottomPadding-i, paint);
+				}
+				paint.setColor(Color.RED);
+				paint.setAlpha(255);
+				c.drawPath(path, paint);
+
+				Paint pa = new Paint();
+				pa.setColor(Color.RED); // ARGB for the color, in this case red
+				int removeColor = pa.getColor(); // store this color's int for later use
+				pa.setAlpha(0);
+				pa.setXfermode(new AvoidXfermode(removeColor, 0, AvoidXfermode.Mode.TARGET));
+				// draw transparent on the "brown" pixels
+				c.drawPaint(pa);
+				
+				canvas.drawBitmap(b, 0, 0, null);
+			}
+			
+			lineCount++;
+		}
+		
+		paint.setColor(Color.BLACK);
+		paint.setAlpha(50);
+		paint.setAntiAlias(true);
+		canvas.drawLine(sidePadding, getHeight() - bottomPadding, getWidth()-sidePadding, getHeight()-bottomPadding, paint);
+		paint.setAlpha(255);
+		
+		
+		for (Line line : lines){
+			int count = 0;
+			float lastXPixels = 0, newYPixels = 0;
+			float lastYPixels = 0, newXPixels = 0;
+			float maxY = getMaxY();
+			float minY = getMinY();
+			float maxX = getMaxX();
+			float minX = getMinX();
+			
+			paint.setColor(line.getColor());
+			paint.setStrokeWidth(6);
+			
+			for (LinePoint p : line.getPoints()){
+				float yPercent = (p.getY()-minY)/(maxY - minY);
+				float xPercent = (p.getX()-minX)/(maxX - minX);
+				if (count == 0){
+					lastXPixels = sidePadding + (xPercent*usableWidth);
+					lastYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
+				} else {
+					newXPixels = sidePadding + (xPercent*usableWidth);
+					newYPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
+					canvas.drawLine(lastXPixels, lastYPixels, newXPixels, newYPixels, paint);
+					lastXPixels = newXPixels;
+					lastYPixels = newYPixels;
+				}
+				count++;
+			}
+		}
+		
+		
+		int pointCount = 0;
+		
+		for (Line line : lines){
+			float maxY = getMaxY();
+			float minY = getMinY();
+			float maxX = getMaxX();
+			float minX = getMinX();
+			
+			paint.setColor(line.getColor());
+			paint.setStrokeWidth(6);
+			paint.setStrokeCap(Paint.Cap.ROUND);
+			
+			if (line.isShowingPoints()){
+				for (LinePoint p : line.getPoints()){
+					float yPercent = (p.getY()-minY)/(maxY - minY);
+					float xPercent = (p.getX()-minX)/(maxX - minX);
+					float xPixels = sidePadding + (xPercent*usableWidth);
+					float yPixels = getHeight() - bottomPadding - (usableHeight*yPercent);
+					
+					paint.setColor(Color.GRAY);
+					canvas.drawCircle(xPixels, yPixels, 10, paint);
+					paint.setColor(Color.WHITE);
+					canvas.drawCircle(xPixels, yPixels, 5, paint);
+					
+					Path path2 = new Path();
+					path2.addCircle(xPixels, yPixels, 30, Direction.CW);
+					p.setPath(path2);
+					p.setRegion(new Region((int)(xPixels-30), (int)(yPixels-30), (int)(xPixels+30), (int)(yPixels+30)));
+					
+					if (indexSelected == pointCount){
+						paint.setColor(Color.parseColor("#33B5E5"));
+						paint.setAlpha(100);
+						canvas.drawPath(p.getPath(), paint);
+						paint.setAlpha(255);
+					}
+					
+					pointCount++;
+				}
+			}
+		}
+		
+		
+	}
+	
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+
+	    Point point = new Point();
+	    point.x = (int) event.getX();
+	    point.y = (int) event.getY();
+	    
+	    int count = 0;
+	    int lineCount = 0;
+	    int pointCount = 0;
+	    
+	    Region r = new Region();
+	    for (Line line : lines){
+	    	pointCount = 0;
+	    	for (LinePoint p : line.getPoints()){
+		    	r.setPath(p.getPath(), p.getRegion());
+		    	if (r.contains((int)point.x,(int) point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
+		    		indexSelected = count;
+		    	} else if (event.getAction() == MotionEvent.ACTION_UP){
+		    		if (r.contains((int)point.x,(int) point.y) && listener != null){
+		    			listener.onClick(lineCount, pointCount);
+		    		}
+		    		indexSelected = -1;
+		    	}
+		    	pointCount++;
+			    count++;
+	    	}
+	    	lineCount++;
+	    	
+	    }
+	    
+	    if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP){
+	    	postInvalidate();
+	    }
+	    
+	    
+
+	    return true;
+	}
+	
+	public void setOnPointClickedListener(OnPointClickedListener listener) {
+		this.listener = listener;
+	}
+	
+	public abstract class OnPointClickedListener {
+		abstract void onClick(int lineIndex, int pointIndex);
+	}
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/LinePoint.java

+package com.echo.holographlibrary;
+
+import android.graphics.Path;
+import android.graphics.Region;
+
+public class LinePoint {
+	private float x = 0;
+	private float y = 0;
+	private Path path;
+	private Region region;
+
+	
+	public float getX() {
+		return x;
+	}
+	public void setX(float x) {
+		this.x = x;
+	}
+	public float getY() {
+		return y;
+	}
+	public void setY(float y) {
+		this.y = y;
+	}
+	public Region getRegion() {
+		return region;
+	}
+	public void setRegion(Region region) {
+		this.region = region;
+	}
+	public Path getPath() {
+		return path;
+	}
+	public void setPath(Path path) {
+		this.path = path;
+	}
+	
+	
+	
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/PieGraph.java

+package com.echo.holographlibrary;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class PieGraph extends SurfaceView implements SurfaceHolder.Callback {
+
+	private ArrayList<PieSlice> slices = new ArrayList<PieSlice>();
+	private int indexSelected = -1;
+	private int thickness = 50;
+	private OnSliceClickedListener listener;
+	
+	
+	public PieGraph(Context context) {
+		super(context);
+		this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	public PieGraph(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		this.setZOrderOnTop(true); //necessary                
+	    getHolder().setFormat(PixelFormat.TRANSPARENT); 
+	    getHolder().addCallback(this); 
+	}
+	
+	public void onDraw(Canvas canvas) {
+		canvas.drawColor(Color.TRANSPARENT);
+		Paint paint = new Paint();
+		paint.setAntiAlias(true);
+		float midX, midY, radius, innerRadius;
+		Path p = new Path();
+		
+		float currentAngle = 270;
+		float currentSweep = 0;
+		int totalValue = 0;
+		float padding = 2;
+		
+		midX = getWidth()/2;
+		midY = getHeight()/2;
+		if (midX < midY){
+			radius = midX;
+		} else {
+			radius = midY;
+		}
+		radius -= padding;
+		innerRadius = radius - thickness;
+		
+		for (PieSlice slice : slices){
+			totalValue += slice.getValue();
+		}
+		
+		int count = 0;
+		for (PieSlice slice : slices){
+			p = new Path();
+			paint.setColor(slice.getColor());
+			currentSweep = (slice.getValue()/totalValue)*(360);
+			p.arcTo(new RectF(midX-radius, midY-radius, midX+radius, midY+radius), currentAngle+padding, currentSweep - padding);
+			p.arcTo(new RectF(midX-innerRadius, midY-innerRadius, midX+innerRadius, midY+innerRadius), (currentAngle+padding) + (currentSweep - padding), -(currentSweep-padding));
+			p.close();
+			
+			slice.setPath(p);
+			slice.setRegion(new Region((int)(midX-radius), (int)(midY-radius), (int)(midX+radius), (int)(midY+radius)));
+			canvas.drawPath(p, paint);
+			
+			if (indexSelected == count && listener != null){
+				Path p2 = new Path();
+				paint.setColor(slice.getColor());
+				paint.setColor(Color.parseColor("#33B5E5"));
+				paint.setAlpha(100);
+				p2.arcTo(new RectF(midX-radius-(padding*2), midY-radius-(padding*2), midX+radius+(padding*2), midY+radius+(padding*2)), currentAngle, currentSweep+padding);
+				p2.arcTo(new RectF(midX-innerRadius+(padding*2), midY-innerRadius+(padding*2), midX+innerRadius-(padding*2), midY+innerRadius-(padding*2)), currentAngle + currentSweep + padding, -(currentSweep + padding));
+				p2.close();
+				canvas.drawPath(p2, paint);
+				paint.setAlpha(255);
+			}
+			
+			currentAngle = currentAngle+currentSweep;
+			
+			count++;
+		}
+		
+		
+	}
+	
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+
+	    Point point = new Point();
+	    point.x = (int) event.getX();
+	    point.y = (int) event.getY();
+	    
+	    int count = 0;
+	    for (PieSlice slice : slices){
+	    	Region r = new Region();
+	    	r.setPath(slice.getPath(), slice.getRegion());
+	    	if (r.contains((int)point.x,(int) point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
+	    		indexSelected = count;
+	    	} else if (event.getAction() == MotionEvent.ACTION_UP){
+	    		if (r.contains((int)point.x,(int) point.y) && listener != null){
+	    			listener.onClick(indexSelected);
+	    		}
+	    		indexSelected = -1;
+	    	}
+		    count++;
+	    }
+	    
+	    if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP){
+	    	postInvalidate();
+	    }
+	    
+	    
+
+	    return true;
+	}
+	
+	@Override
+	public void surfaceChanged(SurfaceHolder holder, int format, int width,
+			int height) {}
+
+	@Override
+	public void surfaceCreated(SurfaceHolder holder) {
+		setWillNotDraw(false); 					//Allows us to use invalidate() to call onDraw()
+		postInvalidate();
+	}
+
+	@Override
+	public void surfaceDestroyed(SurfaceHolder holder) {}
+	
+	public ArrayList<PieSlice> getSlices() {
+		return slices;
+	}
+	public void setSlices(ArrayList<PieSlice> slices) {
+		this.slices = slices;
+	}
+	public PieSlice getSlice(int index) {
+		return slices.get(index);
+	}
+	public void addSlice(PieSlice slice) {
+		this.slices.add(slice);
+	}
+	public void setOnSliceClickedListener(OnSliceClickedListener listener) {
+		this.listener = listener;
+	}
+	
+	public int getThickness() {
+		return thickness;
+	}
+	public void setThickness(int thickness) {
+		this.thickness = thickness;
+	}
+
+	public abstract class OnSliceClickedListener {
+		abstract void onClick(int index);
+	}
+
+}

File HoloGraphLibrary/src/com/echo/holographlibrary/PieSlice.java

+package com.echo.holographlibrary;
+
+import android.graphics.Color;
+import android.graphics.Path;
+import android.graphics.Region;
+
+public class PieSlice {
+	private int color = Color.BLACK;
+	private float value;
+	private String title;
+	private Path path;
+	private Region region;
+
+	public String getTitle() {
+		return title;
+	}
+	public void setTitle(String title) {
+		this.title = title;
+	}
+	public int getColor() {
+		return color;
+	}
+	public void setColor(int color) {
+		this.color = color;
+	}
+	public float getValue() {
+		return value;
+	}
+	public void setValue(float value) {
+		this.value = value;
+	}
+	public Path getPath() {
+		return path;
+	}
+	public void setPath(Path path) {
+		this.path = path;
+	}
+	public Region getRegion() {
+		return region;
+	}
+	public void setRegion(Region region) {
+		this.region = region;
+	}
+	
+}