Browse Source

fixed bugs in statistics fragment

Julien Clauter 10 years ago
parent
commit
0f2289a320

BIN
libs/chart-library2.2.jar


+ 35 - 33
res/layout/fragment_statistics.xml

@@ -7,51 +7,53 @@
     >
 
 
-    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-        android:orientation="vertical"
-        android:layout_height="40dp"
-        android:layout_width="match_parent"
-        android:id="@+id/title_layout"
-        android:padding="5dp"
-        android:layout_alignParentTop="true"
-        android:layout_alignParentLeft="true"
-        android:layout_alignParentStart="true">
+        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_height="40dp"
+            android:layout_width="match_parent"
+            android:id="@+id/title_layout"
+            android:padding="5dp"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:text="Title"
+                android:textAlignment="center"
+                android:id="@+id/title_textView" />
+        </LinearLayout>
+
 
-        <TextView
+
+        <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:text="Title"
-            android:textAlignment="center"
-            android:id="@+id/title_textView" />
-    </LinearLayout>
-
-    <LinearLayout
-        android:orientation="vertical"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:layout_above="@+id/linearLayout"
-        android:layout_below="@+id/title_layout"
-        android:weightSum="2">
+            android:layout_above="@+id/toolbar_layout"
+            android:layout_below="@+id/title_layout"
+            android:weightSum="2">
 
         <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
             android:orientation="vertical"
-            android:layout_height="fill_parent"
-            android:layout_width="fill_parent"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
             android:id="@+id/plot_layout"
             android:padding="2dp"
             android:layout_weight="0.9">
 
         </LinearLayout>
 
-        <ListView
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent"
-            android:id="@+id/listView"
-            android:layout_weight="1.1"
-            />
+            <ListView
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:id="@+id/legend_list_view"
+                android:layout_weight="1.1"
+                />
 
-        </LinearLayout>
+            </LinearLayout>
 
 
     <RelativeLayout
@@ -60,7 +62,7 @@
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:alpha="0.8"
-        android:id="@+id/linearLayout"
+        android:id="@+id/toolbar_layout"
         android:layout_alignParentBottom="true"
         android:layout_alignParentLeft="true"
         android:layout_alignParentStart="true">

+ 45 - 0
res/layout/plot_list_item.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="horizontal"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:weightSum="10">
+
+    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:orientation="horizontal"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:weightSum="10"
+        android:padding="4dp">
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="match_parent"
+        android:textAppearance="?android:attr/textAppearanceSmall"
+        android:text=" "
+        android:id="@+id/color_view"
+        android:layout_weight="4"
+        />
+
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="match_parent"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="title"
+        android:id="@+id/title_text_view"
+        android:layout_weight="2"
+        android:paddingLeft="5dp"
+        android:paddingRight="5dp"
+        android:textColor="#000000" />
+
+    <TextView
+        android:layout_width="fill_parent"
+        android:layout_height="match_parent"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="value"
+        android:id="@+id/value_text_view"
+        android:textAlignment="textEnd"
+        android:layout_weight="4"
+        android:textColor="#000000" />
+    </LinearLayout>
+</LinearLayout>

+ 85 - 0
src/com/echo/holographlibrary/Bar.java

@@ -0,0 +1,85 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.echo.holographlibrary;
+
+import android.graphics.Path;
+import android.graphics.Region;
+
+public class Bar {
+	private int mColor;
+	private String mName = null;
+	private float mValue;
+	private String mValueString = null;
+	private Path mPath = null;
+	private Region mRegion = null;
+	
+	public int getColor() {
+		return mColor;
+	}
+	public void setColor(int color) {
+		this.mColor = color;
+	}
+	public String getName() {
+		return mName;
+	}
+	public void setName(String name) {
+		this.mName = name;
+	}
+	public float getValue() {
+		return mValue;
+	}
+	public void setValue(float value) {
+		this.mValue = value;
+	}
+
+	public String getValueString()
+	{
+		if (mValueString != null) {
+			return mValueString;
+		} else {
+			return String.valueOf(mValue);
+		}
+	}
+	
+	public void setValueString(final String valueString)
+	{
+		mValueString = valueString;
+	}
+	
+	public Path getPath() {
+		return mPath;
+	}
+	public void setPath(Path path) {
+		this.mPath = path;
+	}
+	public Region getRegion() {
+		return mRegion;
+	}
+	public void setRegion(Region region) {
+		this.mRegion = region;
+	}
+
+
+	
+}

+ 247 - 0
src/com/echo/holographlibrary/BarGraph.java

@@ -0,0 +1,247 @@
+/*
+ *     Created by Daniel Nadeau
+ *     daniel.nadeau01@gmail.com
+ *     danielnadeau.blogspot.com
+ * 
+ *     Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.echo.holographlibrary;
+
+import android.content.Context;
+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.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.View;
+
+import java.util.ArrayList;
+
+public class BarGraph extends View {
+
+	private final static int VALUE_FONT_SIZE = 30, AXIS_LABEL_FONT_SIZE = 15;
+	
+    private ArrayList<Bar> mBars = new ArrayList<Bar>();
+    private Paint mPaint = new Paint();
+    private Rect mRectangle = null;
+    private boolean mShowBarText = true;
+    private boolean mShowAxis = true;
+    private int mIndexSelected = -1;
+    private OnBarClickedListener mListener;
+    private Bitmap mFullImage;
+    private boolean mShouldUpdate = false;
+
+    private int popupImageID;
+
+    private Context mContext = null;
+    
+    public BarGraph(Context context) {
+        super(context);
+        mContext = context;
+        this.setWillNotDraw(false);
+    }
+    
+    public BarGraph(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        this.setWillNotDraw(false);
+    }
+    
+    public void setShowBarText(boolean show){
+        mShowBarText = show;
+    }
+    
+    public void setShowAxis(boolean show){
+        mShowAxis = show;
+    }
+    
+    public void setBars(ArrayList<Bar> points){
+        this.mBars = points;
+        mShouldUpdate = true;
+        postInvalidate();
+    }
+    
+    public ArrayList<Bar> getBars(){
+        return this.mBars;
+    }
+
+    public void onDraw(Canvas ca) {
+    	super.onDraw(ca);
+        if (mFullImage == null || mShouldUpdate) {
+            mFullImage = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
+            Canvas canvas = new Canvas(mFullImage);
+            canvas.drawColor(Color.TRANSPARENT);
+            NinePatchDrawable popup = (NinePatchDrawable)this.getResources().getDrawable(popupImageID);
+            
+            float maxValue = 0;
+            float padding = 7 * mContext.getResources().getDisplayMetrics().density;
+            int selectPadding = (int) (4 * mContext.getResources().getDisplayMetrics().density);
+            float bottomPadding = 30 * mContext.getResources().getDisplayMetrics().density;
+            
+            float usableHeight;
+            if (mShowBarText) {
+                this.mPaint.setTextSize(VALUE_FONT_SIZE * mContext.getResources().getDisplayMetrics().scaledDensity);
+                Rect r3 = new Rect();
+                this.mPaint.getTextBounds("$", 0, 1, r3);
+                usableHeight = getHeight()-bottomPadding-Math.abs(r3.top-r3.bottom)-24 * mContext.getResources().getDisplayMetrics().density;
+            } else {
+                usableHeight = getHeight()-bottomPadding;
+            }
+             
+            // Draw x-axis line
+            if (mShowAxis){
+                mPaint.setColor(Color.BLACK);
+                mPaint.setStrokeWidth(2 * mContext.getResources().getDisplayMetrics().density);
+                mPaint.setAlpha(50);
+                mPaint.setAntiAlias(true);
+                canvas.drawLine(0, getHeight()-bottomPadding+10* mContext.getResources().getDisplayMetrics().density, getWidth(), getHeight()-bottomPadding+10* mContext.getResources().getDisplayMetrics().density, mPaint);
+            }
+            float barWidth = (getWidth() - (padding*2)*mBars.size())/mBars.size();
+
+            // Maximum y value = sum of all values.
+            for (final Bar bar : mBars) {
+                if (bar.getValue() > maxValue) {
+                    maxValue = bar.getValue();
+                }
+            }
+            
+            mRectangle = new Rect();
+            
+            int count = 0;
+            for (final Bar bar : mBars) {
+                // Set bar bounds
+                int left = (int)((padding*2)*count + padding + barWidth*count);
+                int top = (int)(getHeight()-bottomPadding-(usableHeight*(bar.getValue()/maxValue)));
+                int right = (int)((padding*2)*count + padding + barWidth*(count+1));
+                int bottom = (int)(getHeight()-bottomPadding);
+                mRectangle.set(left, top, right, bottom);
+
+                // Draw bar
+                this.mPaint.setColor(bar.getColor());
+                this.mPaint.setAlpha(255);
+                canvas.drawRect(mRectangle, this.mPaint);
+
+                // Create selection region
+                Path path = new Path();
+                path.addRect(new RectF(mRectangle.left-selectPadding, mRectangle.top-selectPadding, mRectangle.right+selectPadding, mRectangle.bottom+selectPadding), Path.Direction.CW);
+                bar.setPath(path);
+                bar.setRegion(new Region(mRectangle.left-selectPadding, mRectangle.top-selectPadding, mRectangle.right+selectPadding, mRectangle.bottom+selectPadding));
+
+                // Draw x-axis label text
+                if (mShowAxis){
+                    this.mPaint.setTextSize(AXIS_LABEL_FONT_SIZE * mContext.getResources().getDisplayMetrics().scaledDensity);
+                    int x = (int)(((mRectangle.left+mRectangle.right)/2)-(this.mPaint.measureText(bar.getName())/2));
+                    int y = (int) (getHeight()-3 * mContext.getResources().getDisplayMetrics().scaledDensity);
+                    canvas.drawText(bar.getName(), x, y, this.mPaint);
+                }
+
+                // Draw value text
+                if (mShowBarText){
+                    this.mPaint.setTextSize(VALUE_FONT_SIZE * mContext.getResources().getDisplayMetrics().scaledDensity);
+                    this.mPaint.setColor(Color.WHITE);
+                    Rect r2 = new Rect();
+                    this.mPaint.getTextBounds(bar.getValueString(), 0, 1, r2);
+                    
+                    int boundLeft = (int) (((mRectangle.left+mRectangle.right)/2)-(this.mPaint.measureText(bar.getValueString())/2)-10 * mContext.getResources().getDisplayMetrics().density);
+                    int boundTop = (int) (mRectangle.top+(r2.top-r2.bottom)-18 * mContext.getResources().getDisplayMetrics().density);
+                    int boundRight = (int)(((mRectangle.left+mRectangle.right)/2)+(this.mPaint.measureText(bar.getValueString())/2)+10 * mContext.getResources().getDisplayMetrics().density);
+                    popup.setBounds(boundLeft, boundTop, boundRight, mRectangle.top);
+                    popup.draw(canvas);
+                    
+                    canvas.drawText(bar.getValueString(), (int)(((mRectangle.left+mRectangle.right)/2)-(this.mPaint.measureText(bar.getValueString()))/2), mRectangle.top-(mRectangle.top - boundTop)/2f+(float)Math.abs(r2.top-r2.bottom)/2f*0.7f, this.mPaint);
+                }
+                if (mIndexSelected == count && mListener != null) {
+                    this.mPaint.setColor(Color.parseColor("#33B5E5"));
+                    this.mPaint.setAlpha(100);
+                    canvas.drawPath(bar.getPath(), this.mPaint);
+                    this.mPaint.setAlpha(255);
+                }
+                count++;
+            }
+            mShouldUpdate = false;
+        }
+        
+        ca.drawBitmap(mFullImage, 0, 0, null);
+        
+    }
+
+    public void setPopupImageID(int id){
+        this.popupImageID = id;
+    }
+
+    @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 : mBars){
+            Region r = new Region();
+            r.setPath(bar.getPath(), bar.getRegion());
+            if (r.contains((int)point.x,(int) point.y) && event.getAction() == MotionEvent.ACTION_DOWN){
+                mIndexSelected = count;
+            } else if (event.getAction() == MotionEvent.ACTION_UP){
+                if (r.contains((int)point.x,(int) point.y) && mListener != null){
+                    if (mIndexSelected > -1) mListener.onClick(mIndexSelected);
+                    mIndexSelected = -1;
+                }
+            }
+            else if(event.getAction() == MotionEvent.ACTION_CANCEL)
+            	mIndexSelected = -1;
+            
+            count++;
+        }
+        
+        if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
+            mShouldUpdate = true;
+            postInvalidate();
+        }
+        
+        
+
+        return true;
+    }
+    
+    @Override
+    protected void onDetachedFromWindow()
+    {
+    	if(mFullImage != null)
+    		mFullImage.recycle();
+    	
+    	super.onDetachedFromWindow();
+    }
+    
+    public void setOnBarClickedListener(OnBarClickedListener listener) {
+        this.mListener = listener;
+    }
+    
+    public interface OnBarClickedListener {
+        abstract void onClick(int index);
+    }
+}

+ 103 - 0
src/com/echo/holographlibrary/Line.java

@@ -0,0 +1,103 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.echo.holographlibrary;
+
+import java.util.ArrayList;
+
+public class Line {
+	private ArrayList<LinePoint> points = new ArrayList<LinePoint>();
+	private int color;
+	private boolean showPoints = true;
+	// 6 has been the default prior to the addition of custom stroke widths
+	private int strokeWidth = 6;
+	// since this is a new addition, it has to default to false to be backwards compatible
+	private boolean isUsingDips = false;
+
+
+	public boolean isUsingDips() {
+		return isUsingDips;
+	}
+	public void setUsingDips(boolean treatSizesAsDips) {
+		this.isUsingDips = treatSizesAsDips;
+	}
+	public int getStrokeWidth() {
+		return strokeWidth;
+	}
+	public void setStrokeWidth(int strokeWidth) {
+		if (strokeWidth < 0) {
+			throw new IllegalArgumentException("strokeWidth must not be less than zero");
+		}
+		this.strokeWidth = strokeWidth;
+	}
+	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){
+		LinePoint p;
+		for(int i = 0; i < points.size(); i++){
+			p = points.get(i);
+			if(point.getX() < p.getX()){
+				points.add(i, point);
+				return;
+			}
+		}
+		points.add(point);
+	}
+	
+	public void removePoint(LinePoint point){
+		points.remove(point);
+	}
+	public LinePoint getPoint(int index){
+		return points.get(index);
+	}
+	
+	public LinePoint getPoint(float x, float y){
+		LinePoint p;
+		for(int i = 0; i < points.size(); i++){
+			p = points.get(i);
+			if(p.getX() == x && p.getY() == y)
+				return p;
+		}
+		return null;
+	}
+	public int getSize(){
+		return points.size();
+	}
+	public boolean isShowingPoints() {
+		return showPoints;
+	}
+	public void setShowingPoints(boolean showPoints) {
+		this.showPoints = showPoints;
+	}
+	
+}

+ 533 - 0
src/com/echo/holographlibrary/LineGraph.java

@@ -0,0 +1,533 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.echo.holographlibrary;
+
+import android.content.Context;
+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.Path.Direction;
+import android.graphics.Point;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Region;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+public class LineGraph extends View {
+	
+	private ArrayList<Line> lines = new ArrayList<Line>();
+	Paint paint = new Paint();
+	private float minY = 0, minX = 0;
+	private float maxY = 0, maxX = 0;
+	private double rangeYRatio = 0;
+	private double rangeXRatio = 0;
+	private boolean isMaxYUserSet = false;
+	private boolean isMaxXUserSet = false;
+	private int lineToFill = -1;
+	private int indexSelected = -1;
+	private OnPointClickedListener listener;
+	private Bitmap fullImage;
+	private boolean shouldUpdate = false;
+	
+	public LineGraph(Context context){
+		super(context);
+        this.setWillNotDraw(false);
+    }
+	
+	public LineGraph(Context context, AttributeSet attrs) {
+		super(context, attrs);
+        this.setWillNotDraw(false);
+    }
+	public void setMinY(float minY){
+		
+	}
+	
+	public void removeAllLines(){
+		while (lines.size() > 0){
+			lines.remove(0);
+		}
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	
+	public void addLine(Line line) {
+		lines.add(line);
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	public void addPointToLine(int lineIndex, double x, double y){
+		addPointToLine(lineIndex, (float) x, (float) y);
+	}
+	public void addPointToLine(int lineIndex, float x, float y){
+		LinePoint p = new LinePoint(x, y);
+
+		addPointToLine(lineIndex, p);
+	}
+	
+	public double getRangeYRatio(){
+		return rangeYRatio;
+	}
+	
+	public void setRangeYRatio(double rr){
+		this.rangeYRatio = rr;
+	}
+	public double getRangeXRatio(){
+		return rangeXRatio;
+	}
+	
+	public void setRangeXRatio(double rr){
+		this.rangeXRatio = rr;
+	}
+	public void addPointToLine(int lineIndex, LinePoint point){
+		Line line = getLine(lineIndex);
+		line.addPoint(point);
+		lines.set(lineIndex, line);
+		resetLimits();
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	
+	public void addPointsToLine(int lineIndex, LinePoint[] points){
+		Line line = getLine(lineIndex);
+		for(LinePoint point : points){
+			line.addPoint(point);
+		}
+		lines.set(lineIndex, line);
+		resetLimits();
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	
+	public void removeAllPointsAfter(int lineIndex, double x){
+		removeAllPointsBetween(lineIndex, x, getMaxX());
+	}
+	public void removeAllPointsBefore(int lineIndex, double x){
+		removeAllPointsBetween(lineIndex, getMinX(), x);
+	}
+	
+	public void removeAllPointsBetween(int lineIndex, double startX, double finishX){
+		Line line = getLine(lineIndex);
+		LinePoint[] pts = new LinePoint[line.getPoints().size()];
+		pts = line.getPoints().toArray(pts);
+		for(LinePoint point : pts){
+			if(point.getX() >= startX && point.getX() <= finishX)
+				line.removePoint(point);
+		}
+		lines.set(lineIndex, line);
+		resetLimits();
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	public void removePointsFromLine(int lineIndex, LinePoint[] points){
+		Line line = getLine(lineIndex);
+		for(LinePoint point : points){
+			line.removePoint(point);
+		}
+		lines.set(lineIndex, line);
+		resetLimits();
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	public void removePointFromLine(int lineIndex, float x, float y){
+		LinePoint p = null;
+		Line line = getLine(lineIndex);
+		p = line.getPoint(x, y);
+		removePointFromLine(lineIndex, p);
+	}
+	public void removePointFromLine(int lineIndex, LinePoint point){
+		Line line = getLine(lineIndex);
+		line.removePoint(point);
+		lines.set(lineIndex, line);
+		resetLimits();
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	
+	public void resetYLimits(){
+		float range = getMaxY() - getMinY();
+		setRangeY(getMinY()-range*getRangeYRatio(), getMaxY()+range*getRangeYRatio());
+	}
+	public void resetXLimits(){
+		float range = getMaxX() - getMinX();
+		setRangeX(getMinX()-range*getRangeXRatio(), getMaxX()+range*getRangeXRatio());
+	}
+	public void resetLimits() {
+		resetYLimits();
+		resetXLimits();
+	}
+	public ArrayList<Line> getLines() {
+		return lines;
+	}
+	public void setLineToFill(int indexOfLine) {
+		this.lineToFill = indexOfLine;
+		shouldUpdate = true;
+		postInvalidate();
+	}
+	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;
+	}
+	private void setRangeY(double min, double max){
+		minY = (float)min;
+		maxY = (float)max;
+		isMaxXUserSet = true;
+	}
+	public void setRangeX(float min, float max) {
+		minX = min;
+		maxX = max;
+	}
+	private void setRangeX(double min, double max){
+		minX = (float)min;
+		maxX = (float)max;
+	}
+	public float getMaxY(){
+		float max = lines.get(0).getPoint(0).getY();
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				max = point.getY() > max ? point.getY() : max;
+			}
+		}
+		maxY = max;
+		return maxY;	
+	}
+
+	public float getMinY(){
+		float min = lines.get(0).getPoint(0).getY();
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				min = point.getY() < min ? point.getY() : min;
+			}
+		}
+		minY = min;
+		return minY;
+	}
+	public float getMinLimY(){
+		return minY;
+	}
+	public float getMaxLimY(){
+		return maxY;
+	}
+	public float getMinLimX(){
+		return minX;
+	}
+	public float getMaxLimX(){
+		if (isMaxXUserSet) {
+			return maxX;
+		}
+		else {
+			return getMaxX();
+		}
+	}
+	public float getMaxX(){
+		float max = lines.size() > 0 ? lines.get(0).getPoint(0).getX() : 0;
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				max = point.getX() > max ? point.getX() : max;
+			}
+		}
+		maxX = max;
+		return maxX;
+		
+	}
+	public float getMinX(){
+		float min = lines.size() > 0 ? lines.get(0).getPoint(0).getX() : 0;
+		for (Line line : lines){
+			for (LinePoint point : line.getPoints()){
+				min = point.getX() < min ? point.getX() : min;
+			}
+		}
+		minX = min;
+		return minX;
+	}
+	
+
+
+	 
+	public void onDraw(Canvas ca) {
+        super.onDraw(ca);
+
+        if (fullImage == null || shouldUpdate) {
+			fullImage = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
+			Canvas canvas = new Canvas(fullImage);
+			
+			paint.reset();
+			Path path = new Path();
+
+			float bottomPadding = 10, topPadding = 10;
+			float sidePadding = 10;
+			float usableHeight = getHeight() - bottomPadding - topPadding;
+			float usableWidth = getWidth() - 2*sidePadding;
+
+			float maxY = getMaxLimY();
+			float minY = getMinLimY();
+			float maxX = getMaxLimX();
+			float minX = getMinLimX();
+
+	        
+			int lineCount = 0;
+			for (Line line : lines){
+				int count = 0;
+				float firstXPixels = 0, lastXPixels = 0, newYPixels = 0;
+				float lastYPixels = 0, newXPixels = 0;
+				
+				if (lineCount == lineToFill){
+					paint.setColor(Color.BLACK);
+					paint.setAlpha(30);
+					paint.setStrokeWidth(2);
+					for (int i = 10; i-getWidth() < getHeight(); i = i+20){
+						canvas.drawLine(i, getHeight()-bottomPadding, 0, getHeight()-bottomPadding-i, paint);
+					}
+					
+					paint.reset();
+					
+					paint.setXfermode(new PorterDuffXfermode(android.graphics.PorterDuff.Mode.CLEAR));
+					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);
+							Path pa = new Path();
+							pa.moveTo(lastXPixels, lastYPixels);
+							pa.lineTo(newXPixels, newYPixels);
+							pa.lineTo(newXPixels, 0);
+							pa.lineTo(lastXPixels, 0);
+							pa.close();
+							canvas.drawPath(pa, paint);
+							lastXPixels = newXPixels;
+							lastYPixels = newYPixels;
+						}
+						count++;
+					}
+					
+					path.reset();
+					
+					path.moveTo(0, getHeight()-bottomPadding);
+					path.lineTo(sidePadding, getHeight()-bottomPadding);
+					path.lineTo(sidePadding, 0);
+					path.lineTo(0, 0);
+					path.close();
+					canvas.drawPath(path, paint);
+					
+					path.reset();
+					
+					path.moveTo(getWidth(), getHeight()-bottomPadding);
+					path.lineTo(getWidth()-sidePadding, getHeight()-bottomPadding);
+					path.lineTo(getWidth()-sidePadding, 0);
+					path.lineTo(getWidth(), 0);
+					path.close();
+					
+					canvas.drawPath(path, paint);
+					
+				}
+				
+				lineCount++;
+			}
+			
+			paint.reset();
+			
+			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;
+				
+				paint.setColor(line.getColor());
+				paint.setStrokeWidth(getStrokeWidth(line));
+				
+				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){
+
+				paint.setColor(line.getColor());
+				paint.setStrokeWidth(getStrokeWidth(line));
+				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);
+
+						int outerRadius;
+						if (line.isUsingDips()) {
+							outerRadius = getPixelForDip(line.getStrokeWidth() + 4);
+						}
+						else {
+							outerRadius = line.getStrokeWidth() + 4;
+						}
+						int innerRadius = outerRadius / 2;
+
+						paint.setColor(Color.parseColor(p.getColor()));
+						canvas.drawCircle(xPixels, yPixels, outerRadius, paint);
+						paint.setColor(Color.WHITE);
+						canvas.drawCircle(xPixels, yPixels, innerRadius, 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 && listener != null){
+                            paint.setColor(Color.parseColor(p.getColor()));
+							paint.setAlpha(100);
+							canvas.drawPath(p.getPath(), paint);
+							paint.setAlpha(255);
+						}
+						
+						pointCount++;
+					}
+				}
+			}
+			
+			shouldUpdate = false;
+		}
+		
+		ca.drawBitmap(fullImage, 0, 0, null);
+		
+		
+	}
+
+	private int getStrokeWidth(Line line) {
+		int strokeWidth;
+		if (line.isUsingDips()) {
+			strokeWidth = getPixelForDip(line.getStrokeWidth());
+		}
+		else {
+			strokeWidth = line.getStrokeWidth();
+		}
+		return strokeWidth;
+	}
+
+	private int getPixelForDip(int dipValue) {
+		return (int) TypedValue.applyDimension(
+				TypedValue.COMPLEX_UNIT_DIP,
+				dipValue,
+				getResources().getDisplayMetrics());
+	}
+
+	@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()){
+	    		
+	    		if (p.getPath() != null && p.getRegion() != null){
+	    			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){
+	    	shouldUpdate = true;
+	    	postInvalidate();
+	    }
+	    
+	    
+
+	    return true;
+	}
+	
+	public void setOnPointClickedListener(OnPointClickedListener listener) {
+		this.listener = listener;
+	}
+	
+	public interface OnPointClickedListener {
+		abstract void onClick(int lineIndex, int pointIndex);
+	}
+}

+ 92 - 0
src/com/echo/holographlibrary/LinePoint.java

@@ -0,0 +1,92 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.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;
+    private String color;
+
+    public LinePoint(){
+    }
+
+	public LinePoint(double x, double y){
+		this.x = (float)x;
+		this.y = (float)y;
+	}
+	public LinePoint(float x, float y){
+		this.x = x;
+		this.y = y;
+	}
+	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 void setX(double x){
+		this.x = (float) x;
+	}
+	
+	public void setY(double y){
+		this.y = (float) 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;
+	}
+	
+	@Override
+	public String toString(){
+		return "x= " + x + ", y= " + y;
+	}
+
+    public String getColor() {
+        return color != null ? color : "#33B5E5";
+    }
+
+    public void setColor(String color) {
+        this.color = color;
+    }
+}

+ 209 - 0
src/com/echo/holographlibrary/PieGraph.java

@@ -0,0 +1,209 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.echo.holographlibrary;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+public class PieGraph extends View {
+
+	private ArrayList<PieSlice> slices = new ArrayList<PieSlice>();
+	private Paint paint = new Paint();
+	private Path path = new Path();
+	
+	private int indexSelected = -1;
+	private int thickness;
+	private OnSliceClickedListener listener;
+	
+	private boolean drawCompleted = false;
+	
+	
+	public PieGraph(Context context) {
+		super(context);
+		thickness = (int) (25f * context.getResources().getDisplayMetrics().density);
+        this.setWillNotDraw(false);
+	}
+	
+	public PieGraph(Context context, AttributeSet attrs) {
+		super(context, attrs);
+		thickness = (int) (25f * context.getResources().getDisplayMetrics().density);
+        this.setWillNotDraw(false);
+    }
+
+
+    public void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        canvas.drawColor(Color.TRANSPARENT);
+		paint.reset();
+		paint.setAntiAlias(true);
+		float midX, midY, radius, innerRadius;
+		path.reset();
+		
+		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){
+			Path 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.reset();
+				paint.setColor(slice.getColor());
+				paint.setColor(Color.parseColor("#33B5E5"));
+				paint.setAlpha(100);
+				
+				if (slices.size() > 1) {
+					path.arcTo(new RectF(midX-radius-(padding*2), midY-radius-(padding*2), midX+radius+(padding*2), midY+radius+(padding*2)), currentAngle, currentSweep+padding);
+					path.arcTo(new RectF(midX-innerRadius+(padding*2), midY-innerRadius+(padding*2), midX+innerRadius-(padding*2), midY+innerRadius-(padding*2)), currentAngle + currentSweep + padding, -(currentSweep + padding));
+					path.close();
+				} else {
+					path.addCircle(midX, midY, radius+padding, Direction.CW);
+				}
+				
+				canvas.drawPath(path, paint);
+				paint.setAlpha(255);
+			}
+			
+			currentAngle = currentAngle+currentSweep;
+			
+			count++;
+		}
+		
+		drawCompleted = true;
+		
+	}
+	
+	@Override
+	public boolean onTouchEvent(MotionEvent event) {
+
+		if (drawCompleted) {
+		
+			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){
+						if (indexSelected > -1){
+							listener.onClick(indexSelected);
+						}
+						indexSelected = -1;
+					}
+					
+				}
+				else if(event.getAction() == MotionEvent.ACTION_CANCEL)
+					indexSelected = -1;
+				count++;
+			}
+			
+			if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
+				postInvalidate();
+			}
+	    }
+	    
+
+	    return true;
+	}
+	
+	public ArrayList<PieSlice> getSlices() {
+		return slices;
+	}
+	public void setSlices(ArrayList<PieSlice> slices) {
+		this.slices = slices;
+		postInvalidate();
+	}
+	public PieSlice getSlice(int index) {
+		return slices.get(index);
+	}
+	public void addSlice(PieSlice slice) {
+		this.slices.add(slice);
+		postInvalidate();
+	}
+	public void setOnSliceClickedListener(OnSliceClickedListener listener) {
+		this.listener = listener;
+	}
+	
+	public int getThickness() {
+		return thickness;
+	}
+	public void setThickness(int thickness) {
+		this.thickness = thickness;
+		postInvalidate();
+	}
+	
+	public void removeSlices(){
+		for (int i = slices.size()-1; i >= 0; i--){
+			slices.remove(i);
+		}
+		postInvalidate();
+	}
+
+	public static interface OnSliceClickedListener {
+		public abstract void onClick(int index);
+	}
+
+}

+ 68 - 0
src/com/echo/holographlibrary/PieSlice.java

@@ -0,0 +1,68 @@
+/*
+ * 	   Created by Daniel Nadeau
+ * 	   daniel.nadeau01@gmail.com
+ * 	   danielnadeau.blogspot.com
+ * 
+ * 	   Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you 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.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;
+	}
+	
+}

+ 76 - 0
src/de/tudarmstadt/informatik/hostage/ui2/adapter/StatisticListAdapter.java

@@ -0,0 +1,76 @@
+package de.tudarmstadt.informatik.hostage.ui2.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.tudarmstadt.informatik.hostage.R;
+import de.tudarmstadt.informatik.hostage.ui2.model.PlotComparisonItem;
+
+/**
+ * Created by Julien on 22.02.14.
+ */
+public class StatisticListAdapter extends ArrayAdapter<PlotComparisonItem> {
+    private class ViewHolder {
+        public TextView titleView;
+        public TextView valueView;
+        public TextView colorView;
+    }
+
+    private final Context context;
+    private List<PlotComparisonItem> values;
+
+    public StatisticListAdapter(Context context, List<PlotComparisonItem> objects) {
+        super(context, getLayoutID(), objects);
+        List<PlotComparisonItem> list = objects == null ? new ArrayList<PlotComparisonItem>() : objects;
+        this.context = context;
+        this.values = list;
+    }
+
+    public void setValues(List<PlotComparisonItem> list){
+        this.values = list;
+    }
+
+    @Override
+    public View getView(final int position, View convertView, ViewGroup parent) {
+        LayoutInflater inflater = (LayoutInflater) context
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+        View rowView = convertView;
+        ViewHolder holder = null;
+
+        final PlotComparisonItem item = values.get(position);
+
+        if(rowView == null){
+            rowView = inflater.inflate(getLayoutID() , parent, false);
+            holder = new ViewHolder();
+            holder.titleView = (TextView) rowView.findViewById(R.id.title_text_view);
+            holder.valueView = (TextView) rowView.findViewById(R.id.value_text_view);
+            holder.colorView = (TextView) rowView.findViewById(R.id.color_view);
+            rowView.setTag(holder);
+        } else {
+            holder = (ViewHolder) rowView.getTag();
+        }
+
+
+        this.configureView(holder, item);
+
+        return rowView;
+    }
+
+    static public int getLayoutID(){
+        return R.layout.plot_list_item;
+    }
+
+    private void configureView(ViewHolder holder, PlotComparisonItem item){
+        holder.colorView.setBackgroundColor(item.getColor());
+        holder.titleView.setText(item.getTitle());
+        holder.valueView.setText("" + item.getValue2());
+    }
+}

+ 35 - 20
src/de/tudarmstadt/informatik/hostage/ui2/fragment/StatisticsFragment.java

@@ -10,6 +10,7 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.LinearLayout;
+import android.widget.ListView;
 
 import com.echo.holographlibrary.Bar;
 import com.echo.holographlibrary.BarGraph;
@@ -32,6 +33,7 @@ import de.tudarmstadt.informatik.hostage.R;
 import de.tudarmstadt.informatik.hostage.logging.Record;
 import de.tudarmstadt.informatik.hostage.logging.UglyDbHelper;
 import de.tudarmstadt.informatik.hostage.ui.LogFilter;
+import de.tudarmstadt.informatik.hostage.ui2.adapter.StatisticListAdapter;
 import de.tudarmstadt.informatik.hostage.ui2.model.PlotComparisonItem;
 
 /**
@@ -78,6 +80,8 @@ public class StatisticsFragment extends Fragment {
 
     private UglyDbHelper dbh;
 
+    private ListView legendListView;
+
     public enum ChartType {
         PIE_CHART(0),
         BAR_CHART(1),
@@ -134,9 +138,11 @@ public class StatisticsFragment extends Fragment {
         }
 
         View rootView = inflater.inflate(this.getLayoutID(), container, false);
+
+        this.legendListView = (ListView) rootView.findViewById(R.id.legend_list_view);
         this.rootView = rootView;
-        this.configureRootView(rootView);
 
+        this.configureRootView(rootView);
 
         return rootView;
     }
@@ -150,7 +156,7 @@ public class StatisticsFragment extends Fragment {
     }
 
     public void configureRootView(View rootView){
-        this.setChartType(ChartType.PIE_CHART);
+        this.actualiseCurrentPlot();
     }
 
     public void setChartType(ChartType type){
@@ -168,8 +174,10 @@ public class StatisticsFragment extends Fragment {
         }
         if (shouldChange){
             LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout);
+            plotLayout.removeView(this.currentPlotView);
             this.currentPlotView = this.getPlotViewForType(type);
             plotLayout.addView(this.currentPlotView);
+
             this.actualiseCurrentPlot();
         }
     }
@@ -185,6 +193,11 @@ public class StatisticsFragment extends Fragment {
         }
     }
 
+    public void actualiseLegendList(){
+        StatisticListAdapter adapter = new StatisticListAdapter(this.getApplicationContext(), this.currentData);
+        this.legendListView.setAdapter(adapter);
+    }
+
     /**
     *
     * PLOT TOUCH HANDLING
@@ -203,7 +216,8 @@ public class StatisticsFragment extends Fragment {
     * **/
     public PieGraph getPieGraphView(){
         if (this.pieGraph == null) {
-            this.pieGraph = new PieGraph(this.getApplicationContext());
+            this.pieGraph = new PieGraph(this.getActivity());
+            this.pieGraph.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
             this.pieGraph.setOnSliceClickedListener(new PieGraph.OnSliceClickedListener() {
                 @Override
                 public void onClick(int index) {
@@ -211,24 +225,19 @@ public class StatisticsFragment extends Fragment {
                 }
             });
         }
-        /*
-        * ACTUALISE INPUT DATA
-        * */
-         this.setPieGraphData(this.pieGraph);
          return this.pieGraph;
     }
 
     public LineGraph getLineGraphView(){
         if (this.lineGraph == null) {
-            this.lineGraph = new LineGraph(this.getApplicationContext());
+            this.lineGraph = new LineGraph(this.getActivity());
         }
-        this.setLineGraphData(this.lineGraph);
         return this.lineGraph;
     }
 
     public BarGraph getBarGraphView(){
         if (this.barGraph == null) {
-            this.barGraph = new BarGraph(this.getApplicationContext());
+            this.barGraph = new BarGraph(this.getActivity());
             this.barGraph.setPopupImageID(R.drawable.popup_black);
             this.barGraph.setOnBarClickedListener(new BarGraph.OnBarClickedListener() {
                 @Override
@@ -237,7 +246,6 @@ public class StatisticsFragment extends Fragment {
                 }
             });
         }
-        this.setBarGraphData(this.barGraph);
         return this.barGraph;
     }
 
@@ -261,6 +269,7 @@ public class StatisticsFragment extends Fragment {
             this.pieGraph.addSlice(slice);
         }
         this.pieGraph.invalidate();
+
     }
 
     public void setLineGraphData(LineGraph linegraph){
@@ -322,22 +331,27 @@ public class StatisticsFragment extends Fragment {
          if (plot == null){
              if (this.pieGraph == null){
                  this.currentPlotView = this.getPieGraphView();
-                 // AVOID RELOADING THE DATA ON INITIAL LOAD
-                 return;
              }
              this.currentPlotView = this.getPieGraphView();
-             return;
+             LinearLayout plotLayout = (LinearLayout) this.rootView.findViewById(R.id.plot_layout);
+             plotLayout.addView(this.currentPlotView);
+             plot = this.currentPlotView;
          }
         if (plot instanceof PieGraph){
-            this.setPieGraphData((PieGraph)plot);
+            PieGraph pie = (PieGraph) plot;
+            this.setPieGraphData(pie);
         }
         if (plot instanceof BarGraph){
-            this.setBarGraphData((BarGraph) plot);
+            BarGraph bar = (BarGraph) plot;
+            this.setBarGraphData(bar);
         }
         if (plot instanceof LineGraph){
-            this.setLineGraphData((LineGraph) plot);
+           LineGraph line = (LineGraph)plot;
+           this.setLineGraphData(line);
         }
-    }
+
+         this.actualiseLegendList();
+     }
 
     public ArrayList<PlotComparisonItem> getPieData(){
         // DEFAULT
@@ -532,6 +546,7 @@ public class StatisticsFragment extends Fragment {
                     }
                 }
                 PlotComparisonItem otherItem = new PlotComparisonItem(OTHER_CHART_TITLE, this.getOtherColor(), 0., valueOfOthers);
+                otherItem.setOtherData(others);
                 copy.add(otherItem);
 
                 return copy;
@@ -586,7 +601,7 @@ public class StatisticsFragment extends Fragment {
 
 
     public int getOtherColor(){
-        return Color.rgb(0,0,0);
+        return Color.argb(255,0,0,0);
     }
 
      public ArrayList<Integer> getColorList(){
@@ -624,7 +639,7 @@ public class StatisticsFragment extends Fragment {
         int G = Math.max( (g[n] * 255) - ((Math.max(0,(a ))) * 16), 0);
         int B = Math.max( (b[n] * 255) - ((Math.max(0,(a ))) * 16), 0);
 
-        return Color.rgb(R,G,B);
+        return Color.argb(255,R,G,B);
     }
 
     /*

+ 4 - 4
src/de/tudarmstadt/informatik/hostage/ui2/model/PlotComparisonItem.java

@@ -5,7 +5,7 @@ import java.util.ArrayList;
 /**
  * Created by Julien on 16.02.14.
  */
-public class PlotComparisonItem {
+public class PlotComparisonItem{
 
     private Double value1;
     private Double value2;
@@ -14,7 +14,7 @@ public class PlotComparisonItem {
 
     private int color;
 
-    private ArrayList<Object> otherData;
+    private ArrayList<PlotComparisonItem> otherData;
 
     public PlotComparisonItem(String title, int color , Double value1, Double value2){
         super();
@@ -24,10 +24,10 @@ public class PlotComparisonItem {
         this.value2 = value2;
     }
 
-    public ArrayList<Object> getOtherData(){
+    public ArrayList<PlotComparisonItem> getOtherData(){
         return this.otherData;
     }
-    public void setOtherData(ArrayList<Object> other){
+    public void setOtherData(ArrayList<PlotComparisonItem> other){
         this.otherData = other;
     }
     public String getTitle(){