Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1465)

Unified Diff: third_party/android_data_chart/java/src/org/chromium/third_party/android/datausagechart/ChartNetworkSeriesView.java

Issue 866813004: Add third_party/android_data_chart for data chart widget. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: renamed to third_party/android_data_chart Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/android_data_chart/java/src/org/chromium/third_party/android/datausagechart/ChartNetworkSeriesView.java
diff --git a/third_party/android_data_chart/java/src/org/chromium/third_party/android/datausagechart/ChartNetworkSeriesView.java b/third_party/android_data_chart/java/src/org/chromium/third_party/android/datausagechart/ChartNetworkSeriesView.java
new file mode 100644
index 0000000000000000000000000000000000000000..33a9e6b13005f9cf0a3d130215fda8cb76f54a23
--- /dev/null
+++ b/third_party/android_data_chart/java/src/org/chromium/third_party/android/datausagechart/ChartNetworkSeriesView.java
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2013 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 org.chromium.third_party.android.datausagechart;
+
+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.Path;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+
+import org.chromium.third_party.android.R;
+
+/**
+ * {@link NetworkStatsHistory} series to render inside a {@link ChartView},
+ * using {@link ChartAxis} to map into screen coordinates.
+ * This is derived from com.android.settings.widget.ChartNetworkSeriesView.
+ */
+public class ChartNetworkSeriesView extends View {
+ private static final String TAG = "ChartNetworkSeriesView";
+ private static final boolean LOGD = false;
+
+ private ChartAxis mHoriz;
+ private ChartAxis mVert;
+
+ private Paint mPaintStroke;
+ private Paint mPaintFill;
+ private Paint mPaintFillSecondary;
+ private Paint mPaintEstimate;
+
+ private NetworkStatsHistory mStats;
+
+ private Path mPathStroke;
+ private Path mPathFill;
+ private Path mPathEstimate;
+
+ 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 long mMax;
+ private long mMaxEstimate;
+
+ public ChartNetworkSeriesView(Context context) {
+ this(context, null, 0);
+ }
+
+ 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);
+ setWillNotDraw(false);
+
+ a.recycle();
+
+ mPathStroke = new Path();
+ mPathFill = new Path();
+ mPathEstimate = new Path();
+ }
+
+ void init(ChartAxis horiz, ChartAxis vert) {
+ if (horiz == null) throw new NullPointerException("missing horiz");
+ if (vert == null) throw new NullPointerException("missing vert");
+ mHoriz = horiz;
+ mVert = vert;
+ }
+
+ public void setChartColor(int stroke, int fill, int fillSecondary) {
+ mPaintStroke = new Paint();
+ mPaintStroke.setStrokeWidth(4.0f * getResources().getDisplayMetrics().density);
+ mPaintStroke.setColor(stroke);
+ mPaintStroke.setStyle(Style.STROKE);
+ mPaintStroke.setAntiAlias(true);
+
+ mPaintFill = new Paint();
+ mPaintFill.setColor(fill);
+ mPaintFill.setStyle(Style.FILL);
+ mPaintFill.setAntiAlias(true);
+
+ mPaintFillSecondary = new Paint();
+ mPaintFillSecondary.setColor(fillSecondary);
+ mPaintFillSecondary.setStyle(Style.FILL);
+ mPaintFillSecondary.setAntiAlias(true);
+
+ mPaintEstimate = new Paint();
+ mPaintEstimate.setStrokeWidth(3.0f);
+ mPaintEstimate.setColor(fillSecondary);
+ mPaintEstimate.setStyle(Style.STROKE);
+ mPaintEstimate.setAntiAlias(true);
+ mPaintEstimate.setPathEffect(new DashPathEffect(new float[] { 10, 10 }, 1));
+ }
+
+ public void bindNetworkStats(NetworkStatsHistory stats) {
+ mStats = stats;
+ invalidatePath();
+ invalidate();
+ }
+
+ public void setBounds(long start, long end) {
+ mStart = start;
+ 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 invalidatePath() {
+ mPathValid = false;
+ mMax = 0;
+ invalidate();
+ }
+
+ /**
+ * Erase any existing {@link Path} and generate series outline based on
+ * currently bound {@link NetworkStatsHistory} data.
+ */
+ private void generatePath() {
+ if (LOGD) Log.d(TAG, "generatePath()");
+
+ mMax = 0;
+ mPathStroke.reset();
+ mPathFill.reset();
+ mPathEstimate.reset();
+ mPathValid = true;
+
+ // bail when not enough stats to render
+ if (mStats == null || mStats.size() < 2) {
+ return;
+ }
+
+ final int height = getHeight();
+
+ boolean started = false;
+ float lastX = 0;
+ float lastY = height;
+ long lastTime = mHoriz.convertToValue(lastX);
+
+ // move into starting position
+ mPathStroke.moveTo(lastX, lastY);
+ mPathFill.moveTo(lastX, lastY);
+
+ // TODO(bengr): count fractional data from first bucket crossing start;
+ // currently it only accepts first full bucket.
+
+ long totalData = 0;
+
+ NetworkStatsHistory.Entry entry = null;
+
+ final int start = mStats.getIndexBefore(mStart);
+ final int end = mStats.getIndexAfter(mEnd);
+ for (int i = start; i <= end; i++) {
+ entry = mStats.getValues(i, entry);
+
+ final long startTime = entry.bucketStart;
+ final long endTime = startTime + entry.bucketDuration;
+
+ final float startX = mHoriz.convertToPoint(startTime);
+ final float endX = mHoriz.convertToPoint(endTime);
+
+ // skip until we find first stats on screen
+ if (endX < 0) continue;
+
+ // increment by current bucket total
+ totalData += entry.rxBytes + entry.txBytes;
+
+ final float startY = lastY;
+ final float endY = mVert.convertToPoint(totalData);
+
+ if (lastTime != startTime) {
+ // gap in buckets; line to start of current bucket
+ mPathStroke.lineTo(startX, startY);
+ mPathFill.lineTo(startX, startY);
+ }
+
+ // always draw to end of current bucket
+ mPathStroke.lineTo(endX, endY);
+ mPathFill.lineTo(endX, endY);
+
+ lastX = endX;
+ lastY = endY;
+ lastTime = endTime;
+ }
+
+ // when data falls short, extend to requested end time
+ if (lastTime < mEndTime) {
+ lastX = mHoriz.convertToPoint(mEndTime);
+
+ mPathStroke.lineTo(lastX, lastY);
+ mPathFill.lineTo(lastX, lastY);
+ }
+
+ if (LOGD) {
+ final RectF bounds = new RectF();
+ mPathFill.computeBounds(bounds, true);
+ Log.d(TAG, "onLayout() rendered with bounds=" + bounds.toString() + " and totalData="
+ + totalData);
+ }
+
+ // drop to bottom of graph from current location
+ mPathFill.lineTo(lastX, height);
+ mPathFill.lineTo(0, height);
+
+ mMax = totalData;
+
+ invalidate();
+ }
+
+ public void setEndTime(long endTime) {
+ mEndTime = endTime;
+ }
+
+ public void setEstimateVisible(boolean estimateVisible) {
+ mEstimateVisible = false;
+ invalidate();
+ }
+
+ public long getMaxEstimate() {
+ return mMaxEstimate;
+ }
+
+ public long getMaxVisible() {
+ final long maxVisible = mEstimateVisible ? mMaxEstimate : mMax;
+ if (maxVisible <= 0 && mStats != null) {
+ // haven't generated path yet; fall back to raw data
+ final NetworkStatsHistory.Entry entry = mStats.getValues(mStart, mEnd, null);
+ return entry.rxBytes + entry.txBytes;
+ } else {
+ return maxVisible;
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int save;
+
+ if (!mPathValid) {
+ generatePath();
+ }
+
+ final float primaryLeftPoint = mHoriz.convertToPoint(mPrimaryLeft);
+ final float primaryRightPoint = mHoriz.convertToPoint(mPrimaryRight);
+
+ if (mEstimateVisible) {
+ save = canvas.save();
+ canvas.clipRect(0, 0, getWidth(), getHeight());
+ canvas.drawPath(mPathEstimate, mPaintEstimate);
+ canvas.restoreToCount(save);
+ }
+
+ save = canvas.save();
+ canvas.clipRect(0, 0, primaryLeftPoint, getHeight());
+ canvas.drawPath(mPathFill, mPaintFillSecondary);
+ canvas.restoreToCount(save);
+
+ save = canvas.save();
+ canvas.clipRect(primaryRightPoint, 0, getWidth(), getHeight());
+ canvas.drawPath(mPathFill, mPaintFillSecondary);
+ canvas.restoreToCount(save);
+
+ save = canvas.save();
+ canvas.clipRect(primaryLeftPoint, 0, primaryRightPoint, getHeight());
+ canvas.drawPath(mPathFill, mPaintFill);
+ canvas.drawPath(mPathStroke, mPaintStroke);
+ canvas.restoreToCount(save);
+
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698