summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/widget
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-06-23 00:39:38 -0700
committerJeff Sharkey <jsharkey@android.com>2011-06-23 00:39:47 -0700
commit52c3f4461b806e4f1ce48455ee2ba0ac05dfdab4 (patch)
tree413297650a61f914f6e212b73af8fb76cacbc3d9 /src/com/android/settings/widget
parentaef3981e86909a6a5b4f6ecab972e43fd77582c1 (diff)
downloadpackages_apps_Settings-52c3f4461b806e4f1ce48455ee2ba0ac05dfdab4.zip
packages_apps_Settings-52c3f4461b806e4f1ce48455ee2ba0ac05dfdab4.tar.gz
packages_apps_Settings-52c3f4461b806e4f1ce48455ee2ba0ac05dfdab4.tar.bz2
Iterate on data usage chart UI.
Switched to inflating chart views from XML, using attributes for configuration. Start using drawable assets for chart components instead of manually painting. Include hand-cut assets, and animate between states when touched to invoke. Clamp sweeps to valid chart ranges and prepare for sweep labels. Bug: 4768483, 4598460 Change-Id: Ic660c35bec826eb5e3f6a1dde3cc04d8c437ef2b
Diffstat (limited to 'src/com/android/settings/widget')
-rw-r--r--src/com/android/settings/widget/ChartAxis.java1
-rw-r--r--src/com/android/settings/widget/ChartGridView.java75
-rw-r--r--src/com/android/settings/widget/ChartNetworkSeriesView.java81
-rw-r--r--src/com/android/settings/widget/ChartSweepView.java181
-rw-r--r--src/com/android/settings/widget/ChartView.java54
-rw-r--r--src/com/android/settings/widget/DataUsageChartView.java165
-rw-r--r--src/com/android/settings/widget/InvertedChartAxis.java5
7 files changed, 360 insertions, 202 deletions
diff --git a/src/com/android/settings/widget/ChartAxis.java b/src/com/android/settings/widget/ChartAxis.java
index 2b21d28..e761202 100644
--- a/src/com/android/settings/widget/ChartAxis.java
+++ b/src/com/android/settings/widget/ChartAxis.java
@@ -29,6 +29,7 @@ public interface ChartAxis {
public long convertToValue(float point);
public CharSequence getLabel(long value);
+ public CharSequence getShortLabel(long value);
public float[] getTickPoints();
diff --git a/src/com/android/settings/widget/ChartGridView.java b/src/com/android/settings/widget/ChartGridView.java
index be71890..7a83fbf 100644
--- a/src/com/android/settings/widget/ChartGridView.java
+++ b/src/com/android/settings/widget/ChartGridView.java
@@ -17,12 +17,13 @@
package com.android.settings.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
import android.view.View;
+import com.android.settings.R;
import com.google.common.base.Preconditions;
/**
@@ -31,32 +32,42 @@ import com.google.common.base.Preconditions;
*/
public class ChartGridView extends View {
- private final ChartAxis mHoriz;
- private final ChartAxis mVert;
+ // TODO: eventually teach about drawing chart labels
- private final Paint mPaintHoriz;
- private final Paint mPaintVert;
+ private ChartAxis mHoriz;
+ private ChartAxis mVert;
- public ChartGridView(Context context, ChartAxis horiz, ChartAxis vert) {
- super(context);
+ private Drawable mPrimary;
+ private Drawable mSecondary;
+ private Drawable mBorder;
- mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
- mVert = Preconditions.checkNotNull(vert, "missing vert");
+ public ChartGridView(Context context) {
+ this(context, null, 0);
+ }
+
+ public ChartGridView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ChartGridView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
setWillNotDraw(false);
- // TODO: convert these colors to resources
- mPaintHoriz = new Paint();
- mPaintHoriz.setColor(Color.parseColor("#667bb5"));
- mPaintHoriz.setStrokeWidth(2.0f);
- mPaintHoriz.setStyle(Style.STROKE);
- mPaintHoriz.setAntiAlias(true);
-
- mPaintVert = new Paint();
- mPaintVert.setColor(Color.parseColor("#28262c"));
- mPaintVert.setStrokeWidth(1.0f);
- mPaintVert.setStyle(Style.STROKE);
- mPaintVert.setAntiAlias(true);
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ChartGridView, defStyle, 0);
+
+ mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
+ mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
+ mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
+ // TODO: eventually read labelColor
+
+ a.recycle();
+ }
+
+ void init(ChartAxis horiz, ChartAxis vert) {
+ mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
+ mVert = Preconditions.checkNotNull(vert, "missing vert");
}
@Override
@@ -64,16 +75,28 @@ public class ChartGridView extends View {
final int width = getWidth();
final int height = getHeight();
+ final Drawable secondary = mSecondary;
+ final int secondaryHeight = mSecondary.getIntrinsicHeight();
+
final float[] vertTicks = mVert.getTickPoints();
for (float y : vertTicks) {
- canvas.drawLine(0, y, width, y, mPaintVert);
+ 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) {
- canvas.drawLine(x, 0, x, height, mPaintHoriz);
+ final int right = (int) Math.min(x + primaryWidth, width);
+ primary.setBounds((int) x, 0, right, height);
+ primary.draw(canvas);
}
- canvas.drawRect(0, 0, width, height, mPaintHoriz);
+ mBorder.setBounds(0, 0, width, height);
+ mBorder.draw(canvas);
}
}
diff --git a/src/com/android/settings/widget/ChartNetworkSeriesView.java b/src/com/android/settings/widget/ChartNetworkSeriesView.java
index 780ca46..0a34565 100644
--- a/src/com/android/settings/widget/ChartNetworkSeriesView.java
+++ b/src/com/android/settings/widget/ChartNetworkSeriesView.java
@@ -17,6 +17,7 @@
package com.android.settings.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -24,9 +25,11 @@ import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.net.NetworkStatsHistory;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
+import com.android.settings.R;
import com.google.common.base.Preconditions;
/**
@@ -37,35 +40,54 @@ public class ChartNetworkSeriesView extends View {
private static final String TAG = "ChartNetworkSeriesView";
private static final boolean LOGD = true;
- private final ChartAxis mHoriz;
- private final ChartAxis mVert;
+ private ChartAxis mHoriz;
+ private ChartAxis mVert;
private Paint mPaintStroke;
private Paint mPaintFill;
- private Paint mPaintFillDisabled;
+ private Paint mPaintFillSecondary;
private NetworkStatsHistory mStats;
private Path mPathStroke;
private Path mPathFill;
- private ChartSweepView mSweep1;
- private ChartSweepView mSweep2;
+ private long mPrimaryLeft;
+ private long mPrimaryRight;
- public ChartNetworkSeriesView(Context context, ChartAxis horiz, ChartAxis vert) {
- super(context);
+ public ChartNetworkSeriesView(Context context) {
+ this(context, null, 0);
+ }
- mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
- mVert = Preconditions.checkNotNull(vert, "missing vert");
+ public ChartNetworkSeriesView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ChartNetworkSeriesView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ChartNetworkSeriesView, defStyle, 0);
+
+ final int stroke = a.getColor(R.styleable.ChartNetworkSeriesView_strokeColor, Color.RED);
+ final int fill = a.getColor(R.styleable.ChartNetworkSeriesView_fillColor, Color.RED);
+ final int fillSecondary = a.getColor(
+ R.styleable.ChartNetworkSeriesView_fillColorSecondary, Color.RED);
+
+ setChartColor(stroke, fill, fillSecondary);
- setChartColor(Color.parseColor("#24aae1"), Color.parseColor("#c050ade5"),
- Color.parseColor("#88566abc"));
+ a.recycle();
mPathStroke = new Path();
mPathFill = new Path();
}
- public void setChartColor(int stroke, int fill, int disabled) {
+ void init(ChartAxis horiz, ChartAxis vert) {
+ mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
+ mVert = Preconditions.checkNotNull(vert, "missing vert");
+ }
+
+ public void setChartColor(int stroke, int fill, int fillSecondary) {
mPaintStroke = new Paint();
mPaintStroke.setStrokeWidth(6.0f);
mPaintStroke.setColor(stroke);
@@ -77,10 +99,10 @@ public class ChartNetworkSeriesView extends View {
mPaintFill.setStyle(Style.FILL);
mPaintFill.setAntiAlias(true);
- mPaintFillDisabled = new Paint();
- mPaintFillDisabled.setColor(disabled);
- mPaintFillDisabled.setStyle(Style.FILL);
- mPaintFillDisabled.setAntiAlias(true);
+ mPaintFillSecondary = new Paint();
+ mPaintFillSecondary.setColor(fillSecondary);
+ mPaintFillSecondary.setStyle(Style.FILL);
+ mPaintFillSecondary.setAntiAlias(true);
}
public void bindNetworkStats(NetworkStatsHistory stats) {
@@ -90,12 +112,10 @@ public class ChartNetworkSeriesView extends View {
mPathFill.reset();
}
- public void bindSweepRange(ChartSweepView sweep1, ChartSweepView sweep2) {
- // TODO: generalize to support vertical sweeps
- // TODO: enforce that both sweeps are along same dimension
-
- mSweep1 = Preconditions.checkNotNull(sweep1, "missing sweep1");
- mSweep2 = Preconditions.checkNotNull(sweep2, "missing sweep2");
+ public void setPrimaryRange(long left, long right) {
+ mPrimaryLeft = left;
+ mPrimaryRight = right;
+ invalidate();
}
@Override
@@ -168,27 +188,20 @@ public class ChartNetworkSeriesView extends View {
@Override
protected void onDraw(Canvas canvas) {
-
- // clip to sweep area
- final float sweep1 = mSweep1.getPoint();
- final float sweep2 = mSweep2.getPoint();
- final float sweepLeft = Math.min(sweep1, sweep2);
- final float sweepRight = Math.max(sweep1, sweep2);
-
int save;
save = canvas.save();
- canvas.clipRect(0, 0, sweepLeft, getHeight());
- canvas.drawPath(mPathFill, mPaintFillDisabled);
+ canvas.clipRect(0, 0, mPrimaryLeft, getHeight());
+ canvas.drawPath(mPathFill, mPaintFillSecondary);
canvas.restoreToCount(save);
save = canvas.save();
- canvas.clipRect(sweepRight, 0, getWidth(), getHeight());
- canvas.drawPath(mPathFill, mPaintFillDisabled);
+ canvas.clipRect(mPrimaryRight, 0, getWidth(), getHeight());
+ canvas.drawPath(mPathFill, mPaintFillSecondary);
canvas.restoreToCount(save);
save = canvas.save();
- canvas.clipRect(sweepLeft, 0, sweepRight, getHeight());
+ canvas.clipRect(mPrimaryLeft, 0, mPrimaryRight, 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 788caad..881fde4 100644
--- a/src/com/android/settings/widget/ChartSweepView.java
+++ b/src/com/android/settings/widget/ChartSweepView.java
@@ -17,63 +17,79 @@
package com.android.settings.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.DashPathEffect;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
+import android.widget.FrameLayout;
+import com.android.settings.R;
import com.google.common.base.Preconditions;
/**
* Sweep across a {@link ChartView} at a specific {@link ChartAxis} value, which
* a user can drag.
*/
-public class ChartSweepView extends View {
+public class ChartSweepView extends FrameLayout {
- private final Paint mPaintSweep;
- private final Paint mPaintSweepDisabled;
- private final Paint mPaintShadow;
+ // TODO: paint label when requested
- private final ChartAxis mAxis;
+ private Drawable mSweep;
+ private int mFollowAxis;
+ private boolean mShowLabel;
+
+ private ChartAxis mAxis;
private long mValue;
+ public static final int HORIZONTAL = 0;
+ public static final int VERTICAL = 1;
+
public interface OnSweepListener {
public void onSweep(ChartSweepView sweep, boolean sweepDone);
}
private OnSweepListener mListener;
-
- private boolean mHorizontal;
private MotionEvent mTracking;
- public ChartSweepView(Context context, ChartAxis axis, long value, int color) {
- super(context);
+ public ChartSweepView(Context context) {
+ this(context, null, 0);
+ }
- mAxis = Preconditions.checkNotNull(axis, "missing axis");
- mValue = value;
+ public ChartSweepView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
- mPaintSweep = new Paint();
- mPaintSweep.setColor(color);
- mPaintSweep.setStrokeWidth(3.0f);
- mPaintSweep.setStyle(Style.FILL_AND_STROKE);
- mPaintSweep.setAntiAlias(true);
+ public ChartSweepView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
- mPaintSweepDisabled = new Paint();
- mPaintSweepDisabled.setColor(color);
- mPaintSweepDisabled.setStrokeWidth(1.5f);
- mPaintSweepDisabled.setStyle(Style.FILL_AND_STROKE);
- mPaintSweepDisabled.setPathEffect(new DashPathEffect(new float[] { 5, 5 }, 0));
- mPaintSweepDisabled.setAntiAlias(true);
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, R.styleable.ChartSweepView, defStyle, 0);
- mPaintShadow = new Paint();
- mPaintShadow.setColor(Color.BLACK);
- mPaintShadow.setStrokeWidth(6.0f);
- mPaintShadow.setStyle(Style.FILL_AND_STROKE);
- mPaintShadow.setAntiAlias(true);
+ setSweepDrawable(a.getDrawable(R.styleable.ChartSweepView_sweepDrawable));
+ setFollowAxis(a.getInt(R.styleable.ChartSweepView_followAxis, -1));
+ setShowLabel(a.getBoolean(R.styleable.ChartSweepView_showLabel, false));
+
+ a.recycle();
+
+ setClipToPadding(false);
+ setClipChildren(false);
+ setWillNotDraw(false);
+ }
+
+ void init(ChartAxis axis) {
+ mAxis = Preconditions.checkNotNull(axis, "missing axis");
+ }
+ public int getFollowAxis() {
+ return mFollowAxis;
+ }
+
+ public void getExtraMargins(Rect rect) {
+ mSweep.getPadding(rect);
}
public void addOnSweepListener(OnSweepListener listener) {
@@ -86,6 +102,56 @@ public class ChartSweepView extends View {
}
}
+ public void setSweepDrawable(Drawable sweep) {
+ if (mSweep != null) {
+ mSweep.setCallback(null);
+ unscheduleDrawable(mSweep);
+ }
+
+ if (sweep != null) {
+ sweep.setCallback(this);
+ if (sweep.isStateful()) {
+ sweep.setState(getDrawableState());
+ }
+ sweep.setVisible(getVisibility() == VISIBLE, false);
+ mSweep = sweep;
+ } else {
+ mSweep = null;
+ }
+
+ invalidate();
+ }
+
+ public void setFollowAxis(int followAxis) {
+ mFollowAxis = followAxis;
+ }
+
+ public void setShowLabel(boolean showLabel) {
+ mShowLabel = showLabel;
+ invalidate();
+ }
+
+ @Override
+ public void jumpDrawablesToCurrentState() {
+ super.jumpDrawablesToCurrentState();
+ if (mSweep != null) {
+ mSweep.jumpToCurrentState();
+ }
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ if (mSweep != null) {
+ mSweep.setVisible(visibility == VISIBLE, false);
+ }
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return who == mSweep || super.verifyDrawable(who);
+ }
+
public ChartAxis getAxis() {
return mAxis;
}
@@ -115,14 +181,24 @@ public class ChartSweepView extends View {
case MotionEvent.ACTION_MOVE: {
getParent().requestDisallowInterceptTouchEvent(true);
- if (mHorizontal) {
- setTranslationY(event.getRawY() - mTracking.getRawY());
+ if (mFollowAxis == VERTICAL) {
+ final float chartHeight = parent.getHeight() - parent.getPaddingTop()
+ - parent.getPaddingBottom();
+ final float translationY = MathUtils.constrain(
+ event.getRawY() - mTracking.getRawY(), -getTop(),
+ chartHeight - getTop());
+ setTranslationY(translationY);
final float point = (getTop() + getTranslationY() + (getHeight() / 2))
- parent.getPaddingTop();
mValue = mAxis.convertToValue(point);
dispatchOnSweep(false);
} else {
- setTranslationX(event.getRawX() - mTracking.getRawX());
+ final float chartWidth = parent.getWidth() - parent.getPaddingLeft()
+ - parent.getPaddingRight();
+ final float translationX = MathUtils.constrain(
+ event.getRawX() - mTracking.getRawX(), -getLeft(),
+ chartWidth - getLeft());
+ setTranslationX(translationX);
final float point = (getLeft() + getTranslationX() + (getWidth() / 2))
- parent.getPaddingLeft();
mValue = mAxis.convertToValue(point);
@@ -145,40 +221,25 @@ public class ChartSweepView extends View {
}
@Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+ if (mSweep.isStateful()) {
+ mSweep.setState(getDrawableState());
+ }
+ }
+
+ @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // need at least 50px in each direction for grippies
- // TODO: provide this value through params
- setMeasuredDimension(50, 50);
+ setMeasuredDimension(mSweep.getIntrinsicWidth(), mSweep.getIntrinsicHeight());
}
@Override
protected void onDraw(Canvas canvas) {
-
- // draw line across larger dimension
final int width = getWidth();
final int height = getHeight();
- mHorizontal = width > height;
-
- final Paint linePaint = isEnabled() ? mPaintSweep : mPaintSweepDisabled;
-
- if (mHorizontal) {
- final int centerY = height / 2;
- final int endX = width - height;
-
- canvas.drawLine(0, centerY, endX, centerY, mPaintShadow);
- canvas.drawLine(0, centerY, endX, centerY, linePaint);
- canvas.drawCircle(endX, centerY, 4.0f, mPaintShadow);
- canvas.drawCircle(endX, centerY, 4.0f, mPaintSweep);
- } else {
- final int centerX = width / 2;
- final int endY = height - width;
-
- canvas.drawLine(centerX, 0, centerX, endY, mPaintShadow);
- canvas.drawLine(centerX, 0, centerX, endY, linePaint);
- canvas.drawCircle(centerX, endY, 4.0f, mPaintShadow);
- canvas.drawCircle(centerX, endY, 4.0f, mPaintSweep);
- }
+ mSweep.setBounds(0, 0, width, height);
+ mSweep.draw(canvas);
}
}
diff --git a/src/com/android/settings/widget/ChartView.java b/src/com/android/settings/widget/ChartView.java
index 3e5fc50..d762631 100644
--- a/src/com/android/settings/widget/ChartView.java
+++ b/src/com/android/settings/widget/ChartView.java
@@ -16,13 +16,11 @@
package com.android.settings.widget;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static com.google.common.base.Preconditions.checkNotNull;
import android.content.Context;
import android.graphics.Rect;
-import android.util.Log;
+import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
@@ -38,21 +36,31 @@ public class ChartView extends FrameLayout {
// TODO: extend something that supports two-dimensional scrolling
- final ChartAxis mHoriz;
- final ChartAxis mVert;
+ ChartAxis mHoriz;
+ ChartAxis mVert;
private Rect mContent = new Rect();
- public ChartView(Context context, ChartAxis horiz, ChartAxis vert) {
- super(context);
+ public ChartView(Context context) {
+ this(context, null, 0);
+ }
- mHoriz = checkNotNull(horiz, "missing horiz");
- mVert = checkNotNull(vert, "missing vert");
+ public ChartView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ChartView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
setClipToPadding(false);
setClipChildren(false);
}
+ void init(ChartAxis horiz, ChartAxis vert) {
+ mHoriz = checkNotNull(horiz, "missing horiz");
+ mVert = checkNotNull(vert, "missing vert");
+ }
+
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mContent.set(getPaddingLeft(), getPaddingTop(), r - l - getPaddingRight(),
@@ -66,6 +74,7 @@ public class ChartView extends FrameLayout {
final Rect parentRect = new Rect();
final Rect childRect = new Rect();
+ final Rect extraMargins = new Rect();
for (int i = 0; i < getChildCount(); i++) {
final View child = getChildAt(i);
@@ -82,23 +91,22 @@ public class ChartView extends FrameLayout {
} else if (child instanceof ChartSweepView) {
// sweep is always placed along specific dimension
final ChartSweepView sweep = (ChartSweepView) child;
- final ChartAxis axis = sweep.getAxis();
final float point = sweep.getPoint();
+ sweep.getExtraMargins(extraMargins);
- if (axis == mHoriz) {
+ if (sweep.getFollowAxis() == ChartSweepView.HORIZONTAL) {
parentRect.left = parentRect.right = (int) point + getPaddingLeft();
- parentRect.bottom += child.getMeasuredWidth();
+ parentRect.top -= extraMargins.top;
+ parentRect.bottom += extraMargins.bottom;
Gravity.apply(params.gravity, child.getMeasuredWidth(), parentRect.height(),
parentRect, childRect);
- } else if (axis == mVert) {
+ } else {
parentRect.top = parentRect.bottom = (int) point + getPaddingTop();
- parentRect.right += child.getMeasuredHeight();
+ parentRect.left -= extraMargins.left;
+ parentRect.right += extraMargins.right;
Gravity.apply(params.gravity, parentRect.width(), child.getMeasuredHeight(),
parentRect, childRect);
-
- } else {
- throw new IllegalStateException("unexpected axis");
}
}
@@ -106,16 +114,4 @@ public class ChartView extends FrameLayout {
}
}
- public static LayoutParams buildChartParams() {
- final LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT);
- params.gravity = Gravity.LEFT | Gravity.BOTTOM;
- return params;
- }
-
- public static LayoutParams buildSweepParams() {
- final LayoutParams params = new LayoutParams(WRAP_CONTENT, WRAP_CONTENT);
- params.gravity = Gravity.CENTER;
- return params;
- }
-
}
diff --git a/src/com/android/settings/widget/DataUsageChartView.java b/src/com/android/settings/widget/DataUsageChartView.java
index 6c62fa8..1c76291 100644
--- a/src/com/android/settings/widget/DataUsageChartView.java
+++ b/src/com/android/settings/widget/DataUsageChartView.java
@@ -17,12 +17,14 @@
package com.android.settings.widget;
import android.content.Context;
-import android.graphics.Color;
import android.net.NetworkPolicy;
import android.net.NetworkStatsHistory;
import android.text.format.DateUtils;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
import android.view.View;
+import com.android.settings.R;
import com.android.settings.widget.ChartSweepView.OnSweepListener;
/**
@@ -35,13 +37,16 @@ public class DataUsageChartView extends ChartView {
private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
+ // TODO: enforce that sweeps cant cross each other
+ // TODO: limit sweeps at graph boundaries
+
+ private ChartGridView mGrid;
private ChartNetworkSeriesView mSeries;
- // TODO: limit sweeps at graph boundaries
- private ChartSweepView mSweepTime1;
- private ChartSweepView mSweepTime2;
- private ChartSweepView mSweepDataWarn;
- private ChartSweepView mSweepDataLimit;
+ private ChartSweepView mSweepLeft;
+ private ChartSweepView mSweepRight;
+ private ChartSweepView mSweepWarning;
+ private ChartSweepView mSweepLimit;
public interface DataUsageChartListener {
public void onInspectRangeChanged();
@@ -51,46 +56,58 @@ public class DataUsageChartView extends ChartView {
private DataUsageChartListener mListener;
- private static ChartAxis buildTimeAxis() {
- return new TimeAxis();
+ public DataUsageChartView(Context context) {
+ this(context, null, 0);
}
- private static ChartAxis buildDataAxis() {
- return new InvertedChartAxis(new DataAxis());
+ public DataUsageChartView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
}
- public DataUsageChartView(Context context) {
- super(context, buildTimeAxis(), buildDataAxis());
- setPadding(20, 20, 20, 20);
-
- addView(new ChartGridView(context, mHoriz, mVert), buildChartParams());
+ public DataUsageChartView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(new TimeAxis(), new InvertedChartAxis(new DataAxis()));
+ }
- mSeries = new ChartNetworkSeriesView(context, mHoriz, mVert);
- addView(mSeries, buildChartParams());
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
- mSweepTime1 = new ChartSweepView(context, mHoriz, 0L, Color.parseColor("#ffffff"));
- mSweepTime2 = new ChartSweepView(context, mHoriz, 0L, Color.parseColor("#ffffff"));
- mSweepDataWarn = new ChartSweepView(context, mVert, 0L, Color.parseColor("#f7931d"));
- mSweepDataLimit = new ChartSweepView(context, mVert, 0L, Color.parseColor("#be1d2c"));
+ mGrid = (ChartGridView) findViewById(R.id.grid);
+ mSeries = (ChartNetworkSeriesView) findViewById(R.id.series);
- addView(mSweepTime1, buildSweepParams());
- addView(mSweepTime2, buildSweepParams());
- addView(mSweepDataWarn, buildSweepParams());
- addView(mSweepDataLimit, buildSweepParams());
+ 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);
- mSeries.bindSweepRange(mSweepTime1, mSweepTime2);
+ mSweepLeft.addOnSweepListener(mSweepListener);
+ mSweepRight.addOnSweepListener(mSweepListener);
+ mSweepWarning.addOnSweepListener(mWarningListener);
+ mSweepLimit.addOnSweepListener(mLimitListener);
- mSweepDataWarn.addOnSweepListener(mWarningListener);
- mSweepDataLimit.addOnSweepListener(mLimitListener);
+ // tell everyone about our axis
+ mGrid.init(mHoriz, mVert);
+ mSeries.init(mHoriz, mVert);
+ mSweepLeft.init(mHoriz);
+ mSweepRight.init(mHoriz);
+ mSweepWarning.init(mVert);
+ mSweepLimit.init(mVert);
- mSweepTime1.addOnSweepListener(mSweepListener);
- mSweepTime2.addOnSweepListener(mSweepListener);
+ setActivated(false);
+ }
- mSweepDataWarn.setVisibility(View.INVISIBLE);
- mSweepDataLimit.setVisibility(View.INVISIBLE);
+ @Override
+ public void setActivated(boolean activated) {
+ super.setActivated(activated);
+ mSweepLeft.setEnabled(activated);
+ mSweepRight.setEnabled(activated);
+ mSweepWarning.setEnabled(activated);
+ mSweepLimit.setEnabled(activated);
}
+ @Deprecated
public void setChartColor(int stroke, int fill, int disabled) {
mSeries.setChartColor(stroke, fill, disabled);
}
@@ -105,36 +122,46 @@ public class DataUsageChartView extends ChartView {
public void bindNetworkPolicy(NetworkPolicy policy) {
if (policy == null) {
- mSweepDataLimit.setVisibility(View.INVISIBLE);
- mSweepDataWarn.setVisibility(View.INVISIBLE);
+ mSweepLimit.setVisibility(View.INVISIBLE);
+ mSweepWarning.setVisibility(View.INVISIBLE);
return;
}
if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) {
- mSweepDataLimit.setVisibility(View.VISIBLE);
- mSweepDataLimit.setValue(policy.limitBytes);
- mSweepDataLimit.setEnabled(true);
+ mSweepLimit.setVisibility(View.VISIBLE);
+ mSweepLimit.setValue(policy.limitBytes);
+ mSweepLimit.setEnabled(true);
} else {
// TODO: set limit default based on axis maximum
- mSweepDataLimit.setVisibility(View.VISIBLE);
- mSweepDataLimit.setValue(5 * GB_IN_BYTES);
- mSweepDataLimit.setEnabled(false);
+ mSweepLimit.setVisibility(View.VISIBLE);
+ mSweepLimit.setValue(5 * GB_IN_BYTES);
+ mSweepLimit.setEnabled(false);
}
if (policy.warningBytes != NetworkPolicy.WARNING_DISABLED) {
- mSweepDataWarn.setVisibility(View.VISIBLE);
- mSweepDataWarn.setValue(policy.warningBytes);
+ mSweepWarning.setVisibility(View.VISIBLE);
+ mSweepWarning.setValue(policy.warningBytes);
} else {
- mSweepDataWarn.setVisibility(View.INVISIBLE);
+ mSweepWarning.setVisibility(View.INVISIBLE);
}
requestLayout();
+
+ // TODO: eventually remove this; was to work around lack of sweep clamping
+ if (policy.limitBytes < -1 || policy.limitBytes > 5 * GB_IN_BYTES) {
+ policy.limitBytes = 5 * GB_IN_BYTES;
+ mLimitListener.onSweep(mSweepLimit, true);
+ }
+ if (policy.warningBytes < -1 || policy.warningBytes > 5 * GB_IN_BYTES) {
+ policy.warningBytes = 4 * GB_IN_BYTES;
+ mWarningListener.onSweep(mSweepWarning, true);
+ }
+
}
private OnSweepListener mSweepListener = new OnSweepListener() {
public void onSweep(ChartSweepView sweep, boolean sweepDone) {
- // always update graph clip region
- mSeries.invalidate();
+ mSeries.setPrimaryRange(mSweepLeft.getValue(), mSweepRight.getValue());
// update detail list only when done sweeping
if (sweepDone && mListener != null) {
@@ -159,24 +186,39 @@ public class DataUsageChartView extends ChartView {
}
};
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (isActivated()) return false;
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN: {
+ return true;
+ }
+ case MotionEvent.ACTION_UP: {
+ setActivated(true);
+ return true;
+ }
+ default: {
+ return false;
+ }
+ }
+ }
+
/**
* Return current inspection range (start and end time) based on internal
* {@link ChartSweepView} positions.
*/
public long[] getInspectRange() {
- final long sweep1 = mSweepTime1.getValue();
- final long sweep2 = mSweepTime2.getValue();
- final long start = Math.min(sweep1, sweep2);
- final long end = Math.max(sweep1, sweep2);
+ final long start = mSweepLeft.getValue();
+ final long end = mSweepRight.getValue();
return new long[] { start, end };
}
public long getWarningBytes() {
- return mSweepDataWarn.getValue();
+ return mSweepWarning.getValue();
}
public long getLimitBytes() {
- return mSweepDataLimit.getValue();
+ return mSweepLimit.getValue();
}
/**
@@ -192,8 +234,9 @@ public class DataUsageChartView extends ChartView {
final long sweepMax = Math.min(end, dataBoundary);
final long sweepMin = Math.max(start, (sweepMax - DateUtils.WEEK_IN_MILLIS));
- mSweepTime1.setValue(sweepMin);
- mSweepTime2.setValue(sweepMax);
+ mSweepLeft.setValue(sweepMin);
+ mSweepRight.setValue(sweepMax);
+ mSeries.setPrimaryRange(sweepMin, sweepMax);
requestLayout();
mSeries.generatePath();
@@ -240,6 +283,12 @@ public class DataUsageChartView extends ChartView {
}
/** {@inheritDoc} */
+ public CharSequence getShortLabel(long value) {
+ // TODO: convert to string
+ return Long.toString(value);
+ }
+
+ /** {@inheritDoc} */
public float[] getTickPoints() {
// tick mark for every week
final int tickCount = (int) ((mMax - mMin) / TICK_INTERVAL);
@@ -299,6 +348,16 @@ public class DataUsageChartView extends ChartView {
/** {@inheritDoc} */
public CharSequence getLabel(long value) {
+
+ // TODO: use exploded string here
+
+
+ // TODO: convert to string
+ return Long.toString(value);
+ }
+
+ /** {@inheritDoc} */
+ public CharSequence getShortLabel(long value) {
// TODO: convert to string
return Long.toString(value);
}
diff --git a/src/com/android/settings/widget/InvertedChartAxis.java b/src/com/android/settings/widget/InvertedChartAxis.java
index e7e7893..a30d24c 100644
--- a/src/com/android/settings/widget/InvertedChartAxis.java
+++ b/src/com/android/settings/widget/InvertedChartAxis.java
@@ -54,6 +54,11 @@ public class InvertedChartAxis implements ChartAxis {
}
/** {@inheritDoc} */
+ public CharSequence getShortLabel(long value) {
+ return mWrapped.getShortLabel(value);
+ }
+
+ /** {@inheritDoc} */
public float[] getTickPoints() {
final float[] points = mWrapped.getTickPoints();
for (int i = 0; i < points.length; i++) {