Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bf9cb113 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement general projection curve support for UsageGraph." into oc-dr1-dev

parents 7134ca43 c57ceaaa
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ public class ChartDataUsagePreference extends Preference {

        int top = getTop();
        chart.clearPaths();
        chart.configureGraph(toInt(mEnd - mStart), top, false, false);
        chart.configureGraph(toInt(mEnd - mStart), top);
        calcPoints(chart);
        chart.setBottomLabels(new CharSequence[] {
                Utils.formatDateRange(getContext(), mStart, mStart),
+16 −6
Original line number Diff line number Diff line
@@ -55,18 +55,23 @@ public class BatteryInfo {
    public void bindHistory(final UsageView view, BatteryDataParser... parsers) {
        BatteryDataParser parser = new BatteryDataParser() {
            SparseIntArray points = new SparseIntArray();
            int lastTime = -1;
            byte lastLevel;
            int maxTime;

            @Override
            public void onParsingStarted(long startTime, long endTime) {
                timePeriod = endTime - startTime - remainingTimeUs / 1000;
                this.maxTime = (int) (endTime - startTime);
                timePeriod = maxTime - (remainingTimeUs / 1000);
                view.clearPaths();
                view.configureGraph((int) (endTime - startTime), 100, remainingTimeUs != 0,
                        mCharging);
                view.configureGraph(maxTime, 100);
            }

            @Override
            public void onDataPoint(long time, HistoryItem record) {
                points.put((int) time, record.batteryLevel);
                lastTime = (int) time;
                lastLevel = record.batteryLevel;
                points.put(lastTime, lastLevel);
            }

            @Override
@@ -79,8 +84,13 @@ public class BatteryInfo {

            @Override
            public void onParsingDone() {
                if (points.size() > 1) {
                    view.addPath(points);
                onDataGap();

                // Add linear projection
                if (lastTime >= 0 && remainingTimeUs != 0) {
                    points.put(lastTime, lastLevel);
                    points.put(maxTime, mCharging ? 100 : 0);
                    view.addProjectedPath(points);
                }
            }
        };
+71 −64
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.util.AttributeSet;
import android.util.SparseIntArray;
import android.util.TypedValue;
import android.view.View;

import com.android.settingslib.R;

public class UsageGraph extends View {
@@ -52,11 +53,14 @@ public class UsageGraph extends View {
    private final SparseIntArray mPaths = new SparseIntArray();
    // Paths in local coordinates for drawing.
    private final SparseIntArray mLocalPaths = new SparseIntArray();
    private final int mCornerRadius;

    // Paths for projection in coordinates they are passed in.
    private final SparseIntArray mProjectedPaths = new SparseIntArray();
    // Paths for projection in local coordinates for drawing.
    private final SparseIntArray mLocalProjectedPaths = new SparseIntArray();

    private final int mCornerRadius;
    private int mAccentColor;
    private boolean mShowProjection;
    private boolean mProjectUp;

    private float mMaxX = 100;
    private float mMaxY = 100;
@@ -98,6 +102,9 @@ public class UsageGraph extends View {

    void clearPaths() {
        mPaths.clear();
        mLocalPaths.clear();
        mProjectedPaths.clear();
        mLocalProjectedPaths.clear();
    }

    void setMax(int maxX, int maxY) {
@@ -115,11 +122,21 @@ public class UsageGraph extends View {
    }

    public void addPath(SparseIntArray points) {
        for (int i = 0; i < points.size(); i++) {
            mPaths.put(points.keyAt(i), points.valueAt(i));
        addPathAndUpdate(points, mPaths, mLocalPaths);
    }
        mPaths.put(points.keyAt(points.size() - 1) + 1, PATH_DELIM);
        calculateLocalPaths();

    public void addProjectedPath(SparseIntArray points) {
        addPathAndUpdate(points, mProjectedPaths, mLocalProjectedPaths);
    }

    private void addPathAndUpdate(SparseIntArray points, SparseIntArray paths,
            SparseIntArray localPaths) {
        for (int i = 0, size = points.size(); i < size; i++) {
            paths.put(points.keyAt(i), points.valueAt(i));
        }
        // Add a delimiting value immediately after the last point.
        paths.put(points.keyAt(points.size() - 1) + 1, PATH_DELIM);
        calculateLocalPaths(paths, localPaths);
        postInvalidate();
    }

@@ -130,48 +147,45 @@ public class UsageGraph extends View {
        postInvalidate();
    }

    void setShowProjection(boolean showProjection, boolean projectUp) {
        mShowProjection = showProjection;
        mProjectUp = projectUp;
        postInvalidate();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        updateGradient();
        calculateLocalPaths();
        calculateLocalPaths(mPaths, mLocalPaths);
        calculateLocalPaths(mProjectedPaths, mLocalProjectedPaths);
    }

    private void calculateLocalPaths() {
        if (getWidth() == 0) return;
        mLocalPaths.clear();
    private void calculateLocalPaths(SparseIntArray paths, SparseIntArray localPaths) {
        if (getWidth() == 0) {
            return;
        }
        localPaths.clear();
        int pendingXLoc = 0;
        int pendingYLoc = PATH_DELIM;
        for (int i = 0; i < mPaths.size(); i++) {
            int x = mPaths.keyAt(i);
            int y = mPaths.valueAt(i);
        for (int i = 0; i < paths.size(); i++) {
            int x = paths.keyAt(i);
            int y = paths.valueAt(i);
            if (y == PATH_DELIM) {
                if (i == mPaths.size() - 1 && pendingYLoc != PATH_DELIM) {
                if (i == paths.size() - 1 && pendingYLoc != PATH_DELIM) {
                    // Connect to the end of the graph.
                    mLocalPaths.put(pendingXLoc, pendingYLoc);
                    localPaths.put(pendingXLoc, pendingYLoc);
                }
                // Clear out any pending points.
                pendingYLoc = PATH_DELIM;
                mLocalPaths.put(pendingXLoc + 1, PATH_DELIM);
                localPaths.put(pendingXLoc + 1, PATH_DELIM);
            } else {
                final int lx = getX(x);
                final int ly = getY(y);
                pendingXLoc = lx;
                if (mLocalPaths.size() > 0) {
                    int lastX = mLocalPaths.keyAt(mLocalPaths.size() - 1);
                    int lastY = mLocalPaths.valueAt(mLocalPaths.size() - 1);
                if (localPaths.size() > 0) {
                    int lastX = localPaths.keyAt(localPaths.size() - 1);
                    int lastY = localPaths.valueAt(localPaths.size() - 1);
                    if (lastY != PATH_DELIM && !hasDiff(lastX, lx) && !hasDiff(lastY, ly)) {
                        pendingYLoc = ly;
                        continue;
                    }
                }
                mLocalPaths.put(lx, ly);
                localPaths.put(lx, ly);
            }
        }
    }
@@ -189,8 +203,9 @@ public class UsageGraph extends View {
    }

    private void updateGradient() {
        mFillPaint.setShader(new LinearGradient(0, 0, 0, getHeight(),
                getColor(mAccentColor, .2f), 0, TileMode.CLAMP));
        mFillPaint.setShader(
                new LinearGradient(0, 0, 0, getHeight(), getColor(mAccentColor, .2f), 0,
                        TileMode.CLAMP));
    }

    private int getColor(int color, float alphaScale) {
@@ -207,62 +222,54 @@ public class UsageGraph extends View {
                mMiddleDividerTint);
        drawDivider(canvas.getHeight() - mDividerSize, canvas, -1);

        if (mLocalPaths.size() == 0) {
        if (mLocalPaths.size() == 0 && mProjectedPaths.size() == 0) {
            return;
        }
        if (mShowProjection) {
            drawProjection(canvas);
        }
        drawFilledPath(canvas);
        drawLinePath(canvas);
        drawLinePath(canvas, mLocalProjectedPaths, mDottedPaint);
        drawFilledPath(canvas, mLocalPaths, mFillPaint);
        drawLinePath(canvas, mLocalPaths, mLinePaint);
    }

    private void drawProjection(Canvas canvas) {
        mPath.reset();
        int x = mLocalPaths.keyAt(mLocalPaths.size() - 2);
        int y = mLocalPaths.valueAt(mLocalPaths.size() - 2);
        mPath.moveTo(x, y);
        mPath.lineTo(canvas.getWidth(), mProjectUp ? 0 : canvas.getHeight());
        canvas.drawPath(mPath, mDottedPaint);
    private void drawLinePath(Canvas canvas, SparseIntArray localPaths, Paint paint) {
        if (localPaths.size() == 0) {
            return;
        }

    private void drawLinePath(Canvas canvas) {
        mPath.reset();
        mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0));
        for (int i = 1; i < mLocalPaths.size(); i++) {
            int x = mLocalPaths.keyAt(i);
            int y = mLocalPaths.valueAt(i);
        mPath.moveTo(localPaths.keyAt(0), localPaths.valueAt(0));
        for (int i = 1; i < localPaths.size(); i++) {
            int x = localPaths.keyAt(i);
            int y = localPaths.valueAt(i);
            if (y == PATH_DELIM) {
                if (++i < mLocalPaths.size()) {
                    mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i));
                if (++i < localPaths.size()) {
                    mPath.moveTo(localPaths.keyAt(i), localPaths.valueAt(i));
                }
            } else {
                mPath.lineTo(x, y);
            }
        }
        canvas.drawPath(mPath, mLinePaint);
        canvas.drawPath(mPath, paint);
    }

    private void drawFilledPath(Canvas canvas) {
    private void drawFilledPath(Canvas canvas, SparseIntArray localPaths, Paint paint) {
        mPath.reset();
        float lastStartX = mLocalPaths.keyAt(0);
        mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0));
        for (int i = 1; i < mLocalPaths.size(); i++) {
            int x = mLocalPaths.keyAt(i);
            int y = mLocalPaths.valueAt(i);
        float lastStartX = localPaths.keyAt(0);
        mPath.moveTo(localPaths.keyAt(0), localPaths.valueAt(0));
        for (int i = 1; i < localPaths.size(); i++) {
            int x = localPaths.keyAt(i);
            int y = localPaths.valueAt(i);
            if (y == PATH_DELIM) {
                mPath.lineTo(mLocalPaths.keyAt(i - 1), getHeight());
                mPath.lineTo(localPaths.keyAt(i - 1), getHeight());
                mPath.lineTo(lastStartX, getHeight());
                mPath.close();
                if (++i < mLocalPaths.size()) {
                    lastStartX = mLocalPaths.keyAt(i);
                    mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i));
                if (++i < localPaths.size()) {
                    lastStartX = localPaths.keyAt(i);
                    mPath.moveTo(localPaths.keyAt(i), localPaths.valueAt(i));
                }
            } else {
                mPath.lineTo(x, y);
            }
        }
        canvas.drawPath(mPath, mFillPaint);
        canvas.drawPath(mPath, paint);
    }

    private void drawDivider(int y, Canvas canvas, int tintColor) {
+5 −2
Original line number Diff line number Diff line
@@ -91,9 +91,12 @@ public class UsageView extends FrameLayout {
        mUsageGraph.addPath(points);
    }

    public void configureGraph(int maxX, int maxY, boolean showProjection, boolean projectUp) {
    public void addProjectedPath(SparseIntArray points) {
        mUsageGraph.addProjectedPath(points);
    }

    public void configureGraph(int maxX, int maxY) {
        mUsageGraph.setMax(maxX, maxY);
        mUsageGraph.setShowProjection(showProjection, projectUp);
    }

    public void setAccentColor(int color) {