196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk/* 296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * Copyright (C) 2016 The Android Open Source Project 396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * 496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * except in compliance with the License. You may obtain a copy of the License at 696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * 796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * http://www.apache.org/licenses/LICENSE-2.0 896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * 996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * Unless required by applicable law or agreed to in writing, software distributed under the 1096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * KIND, either express or implied. See the License for the specific language governing 1296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk * permissions and limitations under the License. 1396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk */ 1496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 1596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkpackage com.android.settingslib.graph; 1696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 1796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.annotation.Nullable; 1896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.content.Context; 1996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.content.res.Resources; 2096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Canvas; 2196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.CornerPathEffect; 2296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.DashPathEffect; 2396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.LinearGradient; 2496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Paint; 2596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Paint.Cap; 2696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Paint.Join; 2796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Paint.Style; 2896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Path; 2996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.Shader.TileMode; 3096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.graphics.drawable.Drawable; 3196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.util.AttributeSet; 3296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.util.SparseIntArray; 3396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.util.TypedValue; 3496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport android.view.View; 3596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkimport com.android.settingslib.R; 3696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 3796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monkpublic class UsageGraph extends View { 3896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 3996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private static final int PATH_DELIM = -1; 4096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 4196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final Paint mLinePaint; 4296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final Paint mFillPaint; 4396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final Paint mDottedPaint; 4496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 4596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final Drawable mDivider; 460193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private final Drawable mTintedDivider; 4796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final int mDividerSize; 4896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 4996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final Path mPath = new Path(); 5096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 5196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk // Paths in coordinates they are passed in. 5296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final SparseIntArray mPaths = new SparseIntArray(); 5396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk // Paths in local coordinates for drawing. 5496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private final SparseIntArray mLocalPaths = new SparseIntArray(); 550193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private final int mCornerRadius; 5696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 5796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private int mAccentColor; 5896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private boolean mShowProjection; 5996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private boolean mProjectUp; 6096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 6196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private float mMaxX = 100; 6296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private float mMaxY = 100; 6396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 640193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private float mMiddleDividerLoc = .5f; 650193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private int mMiddleDividerTint = -1; 660193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private int mTopDividerTint = -1; 670193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk 6896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk public UsageGraph(Context context, @Nullable AttributeSet attrs) { 6996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk super(context, attrs); 7096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk final Resources resources = context.getResources(); 7196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 7296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint = new Paint(); 7396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setStyle(Style.STROKE); 7496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setStrokeCap(Cap.ROUND); 7596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setStrokeJoin(Join.ROUND); 7696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setAntiAlias(true); 770193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mCornerRadius = resources.getDimensionPixelSize(R.dimen.usage_graph_line_corner_radius); 780193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mLinePaint.setPathEffect(new CornerPathEffect(mCornerRadius)); 7996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setStrokeWidth(resources.getDimensionPixelSize(R.dimen.usage_graph_line_width)); 8096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 8196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mFillPaint = new Paint(mLinePaint); 8296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mFillPaint.setStyle(Style.FILL); 8396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 8496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDottedPaint = new Paint(mLinePaint); 8596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDottedPaint.setStyle(Style.STROKE); 8696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk float dots = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_size); 8796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk float interval = resources.getDimensionPixelSize(R.dimen.usage_graph_dot_interval); 8896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDottedPaint.setStrokeWidth(dots * 3); 8996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDottedPaint.setPathEffect(new DashPathEffect(new float[] {dots, interval}, 0)); 9096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDottedPaint.setColor(context.getColor(R.color.usage_graph_dots)); 9196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 9296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk TypedValue v = new TypedValue(); 9396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk context.getTheme().resolveAttribute(com.android.internal.R.attr.listDivider, v, true); 9496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDivider = context.getDrawable(v.resourceId); 950193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mTintedDivider = context.getDrawable(v.resourceId); 9696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mDividerSize = resources.getDimensionPixelSize(R.dimen.usage_graph_divider_size); 9796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 9896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 9996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk void clearPaths() { 10096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPaths.clear(); 10196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 10296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 10396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk void setMax(int maxX, int maxY) { 10496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mMaxX = maxX; 10596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mMaxY = maxY; 10696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 10796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 1080193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk void setDividerLoc(int height) { 1090193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mMiddleDividerLoc = 1 - height / mMaxY; 1100193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk } 1110193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk 1120193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk void setDividerColors(int middleColor, int topColor) { 1130193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mMiddleDividerTint = middleColor; 1140193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mTopDividerTint = topColor; 1150193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk } 1160193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk 11796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk public void addPath(SparseIntArray points) { 11896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk for (int i = 0; i < points.size(); i++) { 11996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPaths.put(points.keyAt(i), points.valueAt(i)); 12096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 12196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPaths.put(points.keyAt(points.size() - 1) + 1, PATH_DELIM); 12296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk calculateLocalPaths(); 12396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk postInvalidate(); 12496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 12596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 12696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk void setAccentColor(int color) { 12796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mAccentColor = color; 12896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLinePaint.setColor(mAccentColor); 12996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk updateGradient(); 13096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk postInvalidate(); 13196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 13296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 13396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk void setShowProjection(boolean showProjection, boolean projectUp) { 13496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mShowProjection = showProjection; 13596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mProjectUp = projectUp; 13696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk postInvalidate(); 13796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 13896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 13996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk @Override 14096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk protected void onSizeChanged(int w, int h, int oldw, int oldh) { 14196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk super.onSizeChanged(w, h, oldw, oldh); 14296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk updateGradient(); 14396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk calculateLocalPaths(); 14496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 14596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 14696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private void calculateLocalPaths() { 14796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (getWidth() == 0) return; 14896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLocalPaths.clear(); 14996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int pendingXLoc = 0; 15096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int pendingYLoc = PATH_DELIM; 15196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk for (int i = 0; i < mPaths.size(); i++) { 15296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int x = mPaths.keyAt(i); 15396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int y = mPaths.valueAt(i); 15496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (y == PATH_DELIM) { 15596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (i == mPaths.size() - 1 && pendingYLoc != PATH_DELIM) { 15696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk // Connect to the end of the graph. 15796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLocalPaths.put(pendingXLoc, pendingYLoc); 15896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 15996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk // Clear out any pending points. 16096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk pendingYLoc = PATH_DELIM; 16196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLocalPaths.put(pendingXLoc + 1, PATH_DELIM); 16296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } else { 16396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk final int lx = getX(x); 16496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk final int ly = getY(y); 16596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk pendingXLoc = lx; 16696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (mLocalPaths.size() > 0) { 16796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int lastX = mLocalPaths.keyAt(mLocalPaths.size() - 1); 16896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int lastY = mLocalPaths.valueAt(mLocalPaths.size() - 1); 1690193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk if (lastY != PATH_DELIM && !hasDiff(lastX, lx) && !hasDiff(lastY, ly)) { 17096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk pendingYLoc = ly; 17196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk continue; 17296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 17396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 17496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mLocalPaths.put(lx, ly); 17596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 17696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 17796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 17896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 1790193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private boolean hasDiff(int x1, int x2) { 1800193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk return Math.abs(x2 - x1) >= mCornerRadius; 1810193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk } 1820193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk 18396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private int getX(float x) { 18496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk return (int) (x / mMaxX * getWidth()); 18596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 18696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 18796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private int getY(float y) { 18896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk return (int) (getHeight() * (1 - (y / mMaxY))); 18996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 19096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 19196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private void updateGradient() { 19296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mFillPaint.setShader(new LinearGradient(0, 0, 0, getHeight(), 19396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk getColor(mAccentColor, .2f), 0, TileMode.CLAMP)); 19496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 19596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 19696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private int getColor(int color, float alphaScale) { 19796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk return (color & (((int) (0xff * alphaScale) << 24) | 0xffffff)); 19896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 19996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 20096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk @Override 20196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk protected void onDraw(Canvas canvas) { 20296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk // Draw lines across the top, middle, and bottom. 2030193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk if (mMiddleDividerLoc != 0) { 2040193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk drawDivider(0, canvas, mTopDividerTint); 2050193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk } 2060193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk drawDivider((int) ((canvas.getHeight() - mDividerSize) * mMiddleDividerLoc), canvas, 2070193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mMiddleDividerTint); 2080193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk drawDivider(canvas.getHeight() - mDividerSize, canvas, -1); 20996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 21096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (mLocalPaths.size() == 0) { 21196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk return; 21296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 21396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (mShowProjection) { 21496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk drawProjection(canvas); 21596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 21696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk drawFilledPath(canvas); 21796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk drawLinePath(canvas); 21896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 21996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 22096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private void drawProjection(Canvas canvas) { 22196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.reset(); 22296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int x = mLocalPaths.keyAt(mLocalPaths.size() - 2); 22396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int y = mLocalPaths.valueAt(mLocalPaths.size() - 2); 22496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.moveTo(x, y); 22596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.lineTo(canvas.getWidth(), mProjectUp ? 0 : canvas.getHeight()); 22696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk canvas.drawPath(mPath, mDottedPaint); 22796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 22896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 22996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private void drawLinePath(Canvas canvas) { 23096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.reset(); 23196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0)); 23296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk for (int i = 1; i < mLocalPaths.size(); i++) { 23396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int x = mLocalPaths.keyAt(i); 23496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int y = mLocalPaths.valueAt(i); 23596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (y == PATH_DELIM) { 23696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (++i < mLocalPaths.size()) { 23796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i)); 23896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 23996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } else { 24096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.lineTo(x, y); 24196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 24296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 24396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk canvas.drawPath(mPath, mLinePaint); 24496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 24596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 24696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk private void drawFilledPath(Canvas canvas) { 24796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.reset(); 24896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk float lastStartX = mLocalPaths.keyAt(0); 24996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.moveTo(mLocalPaths.keyAt(0), mLocalPaths.valueAt(0)); 25096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk for (int i = 1; i < mLocalPaths.size(); i++) { 25196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int x = mLocalPaths.keyAt(i); 25296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk int y = mLocalPaths.valueAt(i); 25396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (y == PATH_DELIM) { 25496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.lineTo(mLocalPaths.keyAt(i - 1), getHeight()); 25596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.lineTo(lastStartX, getHeight()); 25696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.close(); 25796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk if (++i < mLocalPaths.size()) { 25896ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk lastStartX = mLocalPaths.keyAt(i); 25996ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.moveTo(mLocalPaths.keyAt(i), mLocalPaths.valueAt(i)); 26096ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 26196ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } else { 26296ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk mPath.lineTo(x, y); 26396ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 26496ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 26596ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk canvas.drawPath(mPath, mFillPaint); 26696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 26796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk 2680193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk private void drawDivider(int y, Canvas canvas, int tintColor) { 2690193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk Drawable d = mDivider; 2700193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk if (tintColor != -1) { 2710193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk mTintedDivider.setTint(tintColor); 2720193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk d = mTintedDivider; 2730193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk } 2740193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk d.setBounds(0, y, canvas.getWidth(), y + mDividerSize); 2750193a87196f5c027b82285e711d8a13e41e4c7d8Jason Monk d.draw(canvas); 27696ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk } 27796ab63640f186dd7f983b35f2c4e1a95436e5052Jason Monk} 278