summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/widget
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/widget')
-rw-r--r--src/com/android/settings/widget/ChartDataUsageView.java93
-rw-r--r--src/com/android/settings/widget/ChartGridView.java94
-rw-r--r--src/com/android/settings/widget/ChartNetworkSeriesView.java42
-rw-r--r--src/com/android/settings/widget/ChartSweepView.java9
-rw-r--r--src/com/android/settings/widget/ChartView.java9
-rw-r--r--src/com/android/settings/widget/PieChartView.java244
6 files changed, 102 insertions, 389 deletions
diff --git a/src/com/android/settings/widget/ChartDataUsageView.java b/src/com/android/settings/widget/ChartDataUsageView.java
index 4e16bfc..c20a8db 100644
--- a/src/com/android/settings/widget/ChartDataUsageView.java
+++ b/src/com/android/settings/widget/ChartDataUsageView.java
@@ -50,26 +50,24 @@ public class ChartDataUsageView extends ChartView {
private static final int MSG_UPDATE_AXIS = 100;
private static final long DELAY_MILLIS = 250;
- private static final boolean LIMIT_SWEEPS_TO_VALID_DATA = false;
-
private ChartGridView mGrid;
private ChartNetworkSeriesView mSeries;
private ChartNetworkSeriesView mDetailSeries;
private NetworkStatsHistory mHistory;
- private ChartSweepView mSweepLeft;
- private ChartSweepView mSweepRight;
private ChartSweepView mSweepWarning;
private ChartSweepView mSweepLimit;
+ private long mInspectStart;
+ private long mInspectEnd;
+
private Handler mHandler;
/** Current maximum value of {@link #mVert}. */
private long mVertMax;
public interface DataUsageChartListener {
- public void onInspectRangeChanged();
public void onWarningChanged();
public void onLimitChanged();
public void requestWarningEdit();
@@ -112,43 +110,27 @@ public class ChartDataUsageView extends ChartView {
mDetailSeries = (ChartNetworkSeriesView) findViewById(R.id.detail_series);
mDetailSeries.setVisibility(View.GONE);
- mSweepLeft = (ChartSweepView) findViewById(R.id.sweep_left);
- mSweepRight = (ChartSweepView) findViewById(R.id.sweep_right);
mSweepLimit = (ChartSweepView) findViewById(R.id.sweep_limit);
mSweepWarning = (ChartSweepView) findViewById(R.id.sweep_warning);
// prevent sweeps from crossing each other
- mSweepLeft.setValidRangeDynamic(null, mSweepRight);
- mSweepRight.setValidRangeDynamic(mSweepLeft, null);
mSweepWarning.setValidRangeDynamic(null, mSweepLimit);
mSweepLimit.setValidRangeDynamic(mSweepWarning, null);
// mark neighbors for checking touch events against
- mSweepLeft.setNeighbors(mSweepRight);
- mSweepRight.setNeighbors(mSweepLeft);
- mSweepLimit.setNeighbors(mSweepWarning, mSweepLeft, mSweepRight);
- mSweepWarning.setNeighbors(mSweepLimit, mSweepLeft, mSweepRight);
+ mSweepLimit.setNeighbors(mSweepWarning);
+ mSweepWarning.setNeighbors(mSweepLimit);
- mSweepLeft.addOnSweepListener(mHorizListener);
- mSweepRight.addOnSweepListener(mHorizListener);
mSweepWarning.addOnSweepListener(mVertListener);
mSweepLimit.addOnSweepListener(mVertListener);
mSweepWarning.setDragInterval(5 * MB_IN_BYTES);
mSweepLimit.setDragInterval(5 * MB_IN_BYTES);
- // TODO: make time sweeps adjustable through dpad
- mSweepLeft.setClickable(false);
- mSweepLeft.setFocusable(false);
- mSweepRight.setClickable(false);
- mSweepRight.setFocusable(false);
-
// tell everyone about our axis
mGrid.init(mHoriz, mVert);
mSeries.init(mHoriz, mVert);
mDetailSeries.init(mHoriz, mVert);
- mSweepLeft.init(mHoriz);
- mSweepRight.init(mHoriz);
mSweepWarning.init(mVert);
mSweepLimit.init(mVert);
@@ -194,7 +176,7 @@ public class ChartDataUsageView extends ChartView {
mSweepLimit.setEnabled(true);
mSweepLimit.setValue(policy.limitBytes);
} else {
- mSweepLimit.setVisibility(View.VISIBLE);
+ mSweepLimit.setVisibility(View.INVISIBLE);
mSweepLimit.setEnabled(false);
mSweepLimit.setValue(-1);
}
@@ -295,23 +277,6 @@ public class ChartDataUsageView extends ChartView {
mSeries.setEstimateVisible(estimateVisible);
}
- private OnSweepListener mHorizListener = new OnSweepListener() {
- @Override
- public void onSweep(ChartSweepView sweep, boolean sweepDone) {
- updatePrimaryRange();
-
- // update detail list only when done sweeping
- if (sweepDone && mListener != null) {
- mListener.onInspectRangeChanged();
- }
- }
-
- @Override
- public void requestEdit(ChartSweepView sweep) {
- // ignored
- }
- };
-
private void sendUpdateAxisDelayed(ChartSweepView sweep, boolean force) {
if (force || !mHandler.hasMessages(MSG_UPDATE_AXIS, sweep)) {
mHandler.sendMessageDelayed(
@@ -369,11 +334,11 @@ public class ChartDataUsageView extends ChartView {
}
public long getInspectStart() {
- return mSweepLeft.getValue();
+ return mInspectStart;
}
public long getInspectEnd() {
- return mSweepRight.getValue();
+ return mInspectEnd;
}
public long getWarningBytes() {
@@ -384,14 +349,6 @@ public class ChartDataUsageView extends ChartView {
return mSweepLimit.getLabelValue();
}
- private long getHistoryStart() {
- return mHistory != null ? mHistory.getStart() : Long.MAX_VALUE;
- }
-
- private long getHistoryEnd() {
- return mHistory != null ? mHistory.getEnd() : Long.MIN_VALUE;
- }
-
/**
* Set the exact time range that should be displayed, updating how
* {@link ChartNetworkSeriesView} paints. Moves inspection ranges to be the
@@ -403,30 +360,8 @@ public class ChartDataUsageView extends ChartView {
mSeries.setBounds(visibleStart, visibleEnd);
mDetailSeries.setBounds(visibleStart, visibleEnd);
- final long historyStart = getHistoryStart();
- final long historyEnd = getHistoryEnd();
-
- final long validStart = historyStart == Long.MAX_VALUE ? visibleStart
- : Math.max(visibleStart, historyStart);
- final long validEnd = historyEnd == Long.MIN_VALUE ? visibleEnd
- : Math.min(visibleEnd, historyEnd);
-
- if (LIMIT_SWEEPS_TO_VALID_DATA) {
- // prevent time sweeps from leaving valid data
- mSweepLeft.setValidRange(validStart, validEnd);
- mSweepRight.setValidRange(validStart, validEnd);
- } else {
- mSweepLeft.setValidRange(visibleStart, visibleEnd);
- mSweepRight.setValidRange(visibleStart, visibleEnd);
- }
-
- // default sweeps to last week of data
- final long halfRange = (visibleEnd + visibleStart) / 2;
- final long sweepMax = validEnd;
- final long sweepMin = Math.max(visibleStart, (sweepMax - DateUtils.WEEK_IN_MILLIS));
-
- mSweepLeft.setValue(sweepMin);
- mSweepRight.setValue(sweepMax);
+ mInspectStart = visibleStart;
+ mInspectEnd = visibleEnd;
requestLayout();
if (changed) {
@@ -440,15 +375,11 @@ public class ChartDataUsageView extends ChartView {
}
private void updatePrimaryRange() {
- final long left = mSweepLeft.getValue();
- final long right = mSweepRight.getValue();
-
// prefer showing primary range on detail series, when available
if (mDetailSeries.getVisibility() == View.VISIBLE) {
- mDetailSeries.setPrimaryRange(left, right);
- mSeries.setPrimaryRange(0, 0);
+ mSeries.setSecondary(true);
} else {
- mSeries.setPrimaryRange(left, right);
+ mSeries.setSecondary(false);
}
}
diff --git a/src/com/android/settings/widget/ChartGridView.java b/src/com/android/settings/widget/ChartGridView.java
index ec5882c..4cd6f5f 100644
--- a/src/com/android/settings/widget/ChartGridView.java
+++ b/src/com/android/settings/widget/ChartGridView.java
@@ -19,22 +19,25 @@ package com.android.settings.widget;
import static com.android.settings.DataUsageSummary.formatDateRange;
import android.content.Context;
+import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import com.android.internal.util.Preconditions;
import com.android.settings.R;
+import java.util.Locale;
+
/**
* Background of {@link ChartView} that renders grid lines as requested by
* {@link ChartAxis#getTickPoints()}.
@@ -47,10 +50,13 @@ public class ChartGridView extends View {
private Drawable mPrimary;
private Drawable mSecondary;
private Drawable mBorder;
+
+ private int mLabelSize;
private int mLabelColor;
- private Layout mLayoutStart;
- private Layout mLayoutEnd;
+ private Layout mLabelStart;
+ private Layout mLabelMid;
+ private Layout mLabelEnd;
public ChartGridView(Context context) {
this(context, null, 0);
@@ -71,7 +77,17 @@ public class ChartGridView extends View {
mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
- mLabelColor = a.getColor(R.styleable.ChartGridView_labelColor, Color.RED);
+
+ final int taId = a.getResourceId(R.styleable.ChartGridView_android_textAppearance, -1);
+ final TypedArray ta = context.obtainStyledAttributes(taId,
+ com.android.internal.R.styleable.TextAppearance);
+ mLabelSize = ta.getDimensionPixelSize(
+ com.android.internal.R.styleable.TextAppearance_textSize, 0);
+ ta.recycle();
+
+ final ColorStateList labelColor = a.getColorStateList(
+ R.styleable.ChartGridView_android_textColor);
+ mLabelColor = labelColor.getDefaultColor();
a.recycle();
}
@@ -83,71 +99,83 @@ public class ChartGridView extends View {
void setBounds(long start, long end) {
final Context context = getContext();
- mLayoutStart = makeLayout(formatDateRange(context, start, start));
- mLayoutEnd = makeLayout(formatDateRange(context, end, end));
+ final long mid = (start + end) / 2;
+ mLabelStart = makeLabel(formatDateRange(context, start, start));
+ mLabelMid = makeLabel(formatDateRange(context, mid, mid));
+ mLabelEnd = makeLabel(formatDateRange(context, end, end));
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
final int width = getWidth();
- final int height = getHeight();
+ final int height = getHeight() - getPaddingBottom();
final Drawable secondary = mSecondary;
- final int secondaryHeight = mSecondary.getIntrinsicHeight();
-
- final float[] vertTicks = mVert.getTickPoints();
- for (float y : vertTicks) {
- final int bottom = (int) Math.min(y + secondaryHeight, height);
- secondary.setBounds(0, (int) y, width, bottom);
- secondary.draw(canvas);
+ if (secondary != null) {
+ final int secondaryHeight = secondary.getIntrinsicHeight();
+
+ final float[] vertTicks = mVert.getTickPoints();
+ for (float y : vertTicks) {
+ final int bottom = (int) Math.min(y + secondaryHeight, height);
+ secondary.setBounds(0, (int) y, width, bottom);
+ secondary.draw(canvas);
+ }
}
final Drawable primary = mPrimary;
- final int primaryWidth = mPrimary.getIntrinsicWidth();
- final int primaryHeight = mPrimary.getIntrinsicHeight();
-
- final float[] horizTicks = mHoriz.getTickPoints();
- for (float x : horizTicks) {
- final int right = (int) Math.min(x + primaryWidth, width);
- primary.setBounds((int) x, 0, right, height);
- primary.draw(canvas);
+ if (primary != null) {
+ final int primaryWidth = primary.getIntrinsicWidth();
+ final int primaryHeight = primary.getIntrinsicHeight();
+
+ final float[] horizTicks = mHoriz.getTickPoints();
+ for (float x : horizTicks) {
+ final int right = (int) Math.min(x + primaryWidth, width);
+ primary.setBounds((int) x, 0, right, height);
+ primary.draw(canvas);
+ }
}
mBorder.setBounds(0, 0, width, height);
mBorder.draw(canvas);
- final int padding = mLayoutStart != null ? mLayoutStart.getHeight() / 8 : 0;
+ final int padding = mLabelStart != null ? mLabelStart.getHeight() / 8 : 0;
- final Layout start = mLayoutStart;
+ final Layout start = mLabelStart;
if (start != null) {
- canvas.save();
+ final int saveCount = canvas.save();
canvas.translate(0, height + padding);
start.draw(canvas);
- canvas.restore();
+ canvas.restoreToCount(saveCount);
+ }
+
+ final Layout mid = mLabelMid;
+ if (mid != null) {
+ final int saveCount = canvas.save();
+ canvas.translate((width - mid.getWidth()) / 2, height + padding);
+ mid.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
- final Layout end = mLayoutEnd;
+ final Layout end = mLabelEnd;
if (end != null) {
- canvas.save();
+ final int saveCount = canvas.save();
canvas.translate(width - end.getWidth(), height + padding);
end.draw(canvas);
- canvas.restore();
+ canvas.restoreToCount(saveCount);
}
}
- private Layout makeLayout(CharSequence text) {
+ private Layout makeLabel(CharSequence text) {
final Resources res = getResources();
final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
paint.density = res.getDisplayMetrics().density;
paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
paint.setColor(mLabelColor);
- paint.setTextSize(
- TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, res.getDisplayMetrics()));
+ paint.setTextSize(mLabelSize);
return new StaticLayout(text, paint,
(int) Math.ceil(Layout.getDesiredWidth(text, paint)),
Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
}
-
}
diff --git a/src/com/android/settings/widget/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java
index 6250a25..7aaba66 100644
--- a/src/com/android/settings/widget/ChartNetworkSeriesView.java
+++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java
@@ -60,17 +60,17 @@ public class ChartNetworkSeriesView extends View {
private Path mPathFill;
private Path mPathEstimate;
+ private int mSafeRegion;
+
private long mStart;
private long mEnd;
- private long mPrimaryLeft;
- private long mPrimaryRight;
-
/** Series will be extended to reach this end time. */
private long mEndTime = Long.MIN_VALUE;
private boolean mPathValid = false;
private boolean mEstimateVisible = false;
+ private boolean mSecondary = false;
private long mMax;
private long mMaxEstimate;
@@ -93,8 +93,11 @@ public class ChartNetworkSeriesView extends View {
final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
final int fillSecondary = a.getColor(
R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
+ final int safeRegion = a.getDimensionPixelSize(
+ R.styleable.ChartNetworkSeriesView_safeRegion, 0);
setChartColor(stroke, fill, fillSecondary);
+ setSafeRegion(safeRegion);
setWillNotDraw(false);
a.recycle();
@@ -134,6 +137,10 @@ public class ChartNetworkSeriesView extends View {
mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
}
+ public void setSafeRegion(int safeRegion) {
+ mSafeRegion = safeRegion;
+ }
+
public void bindNetworkStats(NetworkStatsHistory stats) {
mStats = stats;
invalidatePath();
@@ -145,14 +152,8 @@ public class ChartNetworkSeriesView extends View {
mEnd = end;
}
- /**
- * Set the range to paint with {@link #mPaintFill}, leaving the remaining
- * area to be painted with {@link #mPaintFillSecondary}.
- */
- public void setPrimaryRange(long left, long right) {
- mPrimaryLeft = left;
- mPrimaryRight = right;
- invalidate();
+ public void setSecondary(boolean secondary) {
+ mSecondary = secondary;
}
public void invalidatePath() {
@@ -322,9 +323,6 @@ public class ChartNetworkSeriesView extends View {
generatePath();
}
- final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
- final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);
-
if (mEstimateVisible) {
save = canvas.save();
canvas.clipRect(0, 0, getWidth(), getHeight());
@@ -332,21 +330,11 @@ public class ChartNetworkSeriesView extends View {
canvas.restoreToCount(save);
}
- save = canvas.save();
- canvas.clipRect(0, 0, primaryLeftPoint, getHeight());
- canvas.drawPath(mPathFill, mPaintFillSecondary);
- canvas.restoreToCount(save);
+ final Paint paintFill = mSecondary ? mPaintFillSecondary : mPaintFill;
save = canvas.save();
- canvas.clipRect(primaryRightPoint, 0, getWidth(), getHeight());
- canvas.drawPath(mPathFill, mPaintFillSecondary);
+ canvas.clipRect(mSafeRegion, 0, getWidth(), getHeight() - mSafeRegion);
+ canvas.drawPath(mPathFill, paintFill);
canvas.restoreToCount(save);
-
- save = canvas.save();
- canvas.clipRect(primaryLeftPoint, 0, primaryRightPoint, getHeight());
- canvas.drawPath(mPathFill, mPaintFill);
- canvas.drawPath(mPathStroke, mPaintStroke);
- canvas.restoreToCount(save);
-
}
}
diff --git a/src/com/android/settings/widget/ChartSweepView.java b/src/com/android/settings/widget/ChartSweepView.java
index 774e5d8..04fc862 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -58,6 +58,7 @@ public class ChartSweepView extends View {
private Rect mMargins = new Rect();
private float mNeighborMargin;
+ private int mSafeRegion;
private int mFollowAxis;
@@ -125,6 +126,7 @@ public class ChartSweepView extends View {
setSweepDrawable(a.getDrawable(R.styleable.ChartSweepView_sweepDrawable));
setFollowAxis(a.getInt(R.styleable.ChartSweepView_followAxis, -1));
setNeighborMargin(a.getDimensionPixelSize(R.styleable.ChartSweepView_neighborMargin, 0));
+ setSafeRegion(a.getDimensionPixelSize(R.styleable.ChartSweepView_safeRegion, 0));
setLabelMinSize(a.getDimensionPixelSize(R.styleable.ChartSweepView_labelSize, 0));
setLabelTemplate(a.getResourceId(R.styleable.ChartSweepView_labelTemplate, 0));
@@ -259,7 +261,6 @@ public class ChartSweepView extends View {
paint.density = getResources().getDisplayMetrics().density;
paint.setCompatibilityScaling(getResources().getCompatibilityInfo().applicationScale);
paint.setColor(mLabelColor);
- paint.setShadowLayer(4 * paint.density, 0, 0, Color.BLACK);
mLabelTemplate = new SpannableStringBuilder(template);
mLabelLayout = new DynamicLayout(
@@ -383,6 +384,10 @@ public class ChartSweepView extends View {
mNeighborMargin = neighborMargin;
}
+ public void setSafeRegion(int safeRegion) {
+ mSafeRegion = safeRegion;
+ }
+
/**
* Set valid range this sweep can move within, defined by the given
* {@link ChartSweepView}. The most restrictive combination of all valid
@@ -709,7 +714,7 @@ public class ChartSweepView extends View {
mLabelLayout.draw(canvas);
}
canvas.restoreToCount(count);
- labelSize = (int) mLabelSize;
+ labelSize = (int) mLabelSize + mSafeRegion;
} else {
labelSize = 0;
}
diff --git a/src/com/android/settings/widget/ChartView.java b/src/com/android/settings/widget/ChartView.java
index 69e6e94..30284bc 100644
--- a/src/com/android/settings/widget/ChartView.java
+++ b/src/com/android/settings/widget/ChartView.java
@@ -112,12 +112,18 @@ public class ChartView extends FrameLayout {
parentRect.set(mContent);
- if (child instanceof ChartNetworkSeriesView || child instanceof ChartGridView) {
+ if (child instanceof ChartNetworkSeriesView) {
// series are always laid out to fill entire graph area
// TODO: handle scrolling for series larger than content area
Gravity.apply(params.gravity, width, height, parentRect, childRect);
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
+ } else if (child instanceof ChartGridView) {
+ // Grid uses some extra room for labels
+ Gravity.apply(params.gravity, width, height, parentRect, childRect);
+ child.layout(childRect.left, childRect.top, childRect.right,
+ childRect.bottom + child.getPaddingBottom());
+
} else if (child instanceof ChartSweepView) {
layoutSweep((ChartSweepView) child, parentRect, childRect);
child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
@@ -154,5 +160,4 @@ public class ChartView extends FrameLayout {
parentRect, childRect);
}
}
-
}
diff --git a/src/com/android/settings/widget/PieChartView.java b/src/com/android/settings/widget/PieChartView.java
deleted file mode 100644
index 6070190..0000000
--- a/src/com/android/settings/widget/PieChartView.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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.Matrix;
-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.android.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 = false;
-
- private static final boolean FILL_GRADIENT = false;
-
- private ArrayList<Slice> mSlices = Lists.newArrayList();
-
- private int mOriginAngle;
- private Matrix mMatrix = new Matrix();
-
- private Paint mPaintOutline = new Paint();
-
- private Path mPathSide = new Path();
- private Path mPathSideOutline = new Path();
-
- private Path mPathOutline = new Path();
-
- private int mSideWidth;
-
- public class Slice {
- public long value;
-
- public Path path = new Path();
- public Path pathSide = new Path();
- public Path pathOutline = new Path();
-
- public Paint paint;
-
- public Slice(long value, int color) {
- this.value = value;
- this.paint = 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);
-
- mPaintOutline.setColor(Color.BLACK);
- mPaintOutline.setStyle(Style.STROKE);
- mPaintOutline.setStrokeWidth(3f * getResources().getDisplayMetrics().density);
- mPaintOutline.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);
-
- if (FILL_GRADIENT) {
- 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) {
- final float centerX = getWidth() / 2;
- final float centerY = getHeight() / 2;
-
- mMatrix.reset();
- mMatrix.postScale(0.665f, 0.95f, centerX, centerY);
- mMatrix.postRotate(-40, centerX, centerY);
-
- generatePath();
- }
-
- public void generatePath() {
- if (LOGD) Log.d(TAG, "generatePath()");
-
- long total = 0;
- for (Slice slice : mSlices) {
- slice.path.reset();
- slice.pathSide.reset();
- slice.pathOutline.reset();
- total += slice.value;
- }
-
- mPathSide.reset();
- mPathSideOutline.reset();
- mPathOutline.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);
- final RectF rectSide = new RectF();
- rectSide.set(rect);
- rectSide.offset(-mSideWidth, 0);
-
- mPathSide.addOval(rectSide, Direction.CW);
- mPathSideOutline.addOval(rectSide, Direction.CW);
- mPathOutline.addOval(rect, Direction.CW);
-
- int startAngle = mOriginAngle;
- for (Slice slice : mSlices) {
- final int sweepAngle = (int) (slice.value * 360 / total);
- final int endAngle = startAngle + sweepAngle;
-
- final float startAngleMod = startAngle % 360;
- final float endAngleMod = endAngle % 360;
- final boolean startSideVisible = startAngleMod > 90 && startAngleMod < 270;
- final boolean endSideVisible = endAngleMod > 90 && endAngleMod < 270;
-
- // draw slice
- slice.path.moveTo(rect.centerX(), rect.centerY());
- slice.path.arcTo(rect, startAngle, sweepAngle);
- slice.path.lineTo(rect.centerX(), rect.centerY());
-
- if (startSideVisible || endSideVisible) {
-
- // when start is beyond horizon, push until visible
- final float startAngleSide = startSideVisible ? startAngle : 450;
- final float endAngleSide = endSideVisible ? endAngle : 270;
- final float sweepAngleSide = endAngleSide - startAngleSide;
-
- // draw slice side
- slice.pathSide.moveTo(rect.centerX(), rect.centerY());
- slice.pathSide.arcTo(rect, startAngleSide, 0);
- slice.pathSide.rLineTo(-mSideWidth, 0);
- slice.pathSide.arcTo(rectSide, startAngleSide, sweepAngleSide);
- slice.pathSide.rLineTo(mSideWidth, 0);
- slice.pathSide.arcTo(rect, endAngleSide, -sweepAngleSide);
- }
-
- // draw slice outline
- slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
- slice.pathOutline.arcTo(rect, startAngle, 0);
- if (startSideVisible) {
- slice.pathOutline.rLineTo(-mSideWidth, 0);
- }
- slice.pathOutline.moveTo(rect.centerX(), rect.centerY());
- slice.pathOutline.arcTo(rect, startAngle + sweepAngle, 0);
- if (endSideVisible) {
- slice.pathOutline.rLineTo(-mSideWidth, 0);
- }
-
- startAngle += sweepAngle;
- }
-
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
-
- canvas.concat(mMatrix);
-
- for (Slice slice : mSlices) {
- canvas.drawPath(slice.pathSide, slice.paint);
- }
- canvas.drawPath(mPathSideOutline, mPaintOutline);
-
- for (Slice slice : mSlices) {
- canvas.drawPath(slice.path, slice.paint);
- canvas.drawPath(slice.pathOutline, mPaintOutline);
- }
- canvas.drawPath(mPathOutline, mPaintOutline);
- }
-
- 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);
- }
-
-}