summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/widget/PieChartView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/widget/PieChartView.java')
-rw-r--r--src/com/android/settings/widget/PieChartView.java202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/com/android/settings/widget/PieChartView.java b/src/com/android/settings/widget/PieChartView.java
new file mode 100644
index 0000000..85d45a2
--- /dev/null
+++ b/src/com/android/settings/widget/PieChartView.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * 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.android.settings.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Path;
+import android.graphics.Path.Direction;
+import android.graphics.RadialGradient;
+import android.graphics.RectF;
+import android.graphics.Shader.TileMode;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+
+/**
+ * Pie chart with multiple items.
+ */
+public class PieChartView extends View {
+ public static final String TAG = "PieChartView";
+ public static final boolean LOGD = true;
+
+ private ArrayList<Slice> mSlices = Lists.newArrayList();
+
+ private int mOriginAngle;
+
+ private Paint mPaintPrimary = new Paint();
+ private Paint mPaintShadow = new Paint();
+
+ private Path mPathSide = new Path();
+ private Path mPathSideShadow = new Path();
+
+ private Path mPathShadow = new Path();
+
+ private int mSideWidth;
+
+ public class Slice {
+ public long value;
+
+ public Path pathPrimary = new Path();
+ public Path pathShadow = new Path();
+
+ public Paint paintPrimary;
+
+ public Slice(long value, int color) {
+ this.value = value;
+ this.paintPrimary = buildFillPaint(color, getResources());
+ }
+ }
+
+ public PieChartView(Context context) {
+ this(context, null);
+ }
+
+ public PieChartView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PieChartView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ mPaintPrimary = buildFillPaint(Color.parseColor("#666666"), getResources());
+
+ mPaintShadow.setColor(Color.BLACK);
+ mPaintShadow.setStyle(Style.STROKE);
+ mPaintShadow.setStrokeWidth(3f * getResources().getDisplayMetrics().density);
+ mPaintShadow.setAntiAlias(true);
+
+ mSideWidth = (int) (20 * getResources().getDisplayMetrics().density);
+
+ setWillNotDraw(false);
+ }
+
+ private static Paint buildFillPaint(int color, Resources res) {
+ final Paint paint = new Paint();
+
+ paint.setColor(color);
+ paint.setStyle(Style.FILL_AND_STROKE);
+ paint.setAntiAlias(true);
+
+ final int width = (int) (280 * res.getDisplayMetrics().density);
+ paint.setShader(new RadialGradient(0, 0, width, color, darken(color), TileMode.MIRROR));
+
+ return paint;
+ }
+
+ public void setOriginAngle(int originAngle) {
+ mOriginAngle = originAngle;
+ }
+
+ public void addSlice(long value, int color) {
+ mSlices.add(new Slice(value, color));
+ }
+
+ public void removeAllSlices() {
+ mSlices.clear();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ generatePath();
+ }
+
+ public void generatePath() {
+ if (LOGD) Log.d(TAG, "generatePath()");
+
+ long total = 0;
+ for (Slice slice : mSlices) {
+ slice.pathPrimary.reset();
+ slice.pathShadow.reset();
+ total += slice.value;
+ }
+
+ mPathSide.reset();
+ mPathSideShadow.reset();
+ mPathShadow.reset();
+
+ // bail when not enough stats to render
+ if (total == 0) {
+ invalidate();
+ return;
+ }
+
+ final int width = getWidth();
+ final int height = getHeight();
+
+ final RectF rect = new RectF(0, 0, width, height);
+
+ mPathSide.addOval(rect, Direction.CW);
+ mPathSideShadow.addOval(rect, Direction.CW);
+ mPathShadow.addOval(rect, Direction.CW);
+
+ int startAngle = mOriginAngle;
+ for (Slice slice : mSlices) {
+ final int sweepAngle = (int) (slice.value * 360 / total);
+
+ slice.pathPrimary.moveTo(rect.centerX(), rect.centerY());
+ slice.pathPrimary.arcTo(rect, startAngle, sweepAngle);
+ slice.pathPrimary.lineTo(rect.centerX(), rect.centerY());
+
+ slice.pathShadow.moveTo(rect.centerX(), rect.centerY());
+ slice.pathShadow.arcTo(rect, startAngle, 0);
+ slice.pathShadow.moveTo(rect.centerX(), rect.centerY());
+ slice.pathShadow.arcTo(rect, startAngle + sweepAngle, 0);
+
+ startAngle += sweepAngle;
+ }
+
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+
+ canvas.translate(getWidth() * 0.25f, getHeight() * -0.05f);
+ canvas.rotate(-40, getWidth() * 0.5f, getHeight());
+ canvas.scale(0.7f, 1.0f, getWidth(), getHeight());
+
+ canvas.save();
+ canvas.translate(-mSideWidth, 0);
+ canvas.drawPath(mPathSide, mPaintPrimary);
+ canvas.drawPath(mPathSideShadow, mPaintShadow);
+ canvas.restore();
+
+ for (Slice slice : mSlices) {
+ canvas.drawPath(slice.pathPrimary, slice.paintPrimary);
+ canvas.drawPath(slice.pathShadow, mPaintShadow);
+ }
+ canvas.drawPath(mPathShadow, mPaintShadow);
+ }
+
+ public static int darken(int color) {
+ float[] hsv = new float[3];
+ Color.colorToHSV(color, hsv);
+ hsv[2] /= 2;
+ hsv[1] /= 2;
+ return Color.HSVToColor(hsv);
+ }
+
+}