1ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey/* 2ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Copyright (C) 2011 The Android Open Source Project 3ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 4ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License"); 5ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * you may not use this file except in compliance with the License. 6ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * You may obtain a copy of the License at 7ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 8ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * http://www.apache.org/licenses/LICENSE-2.0 9ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * 10ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Unless required by applicable law or agreed to in writing, software 11ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS, 12ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * See the License for the specific language governing permissions and 14ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * limitations under the License. 15ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey */ 16ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 17ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypackage com.android.settings.widget; 18ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 19ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.content.Context; 20d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.content.res.Resources; 2152c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkeyimport android.content.res.TypedArray; 22ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.graphics.Canvas; 23d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.graphics.Color; 24d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.graphics.Paint; 2552c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkeyimport android.graphics.drawable.Drawable; 26d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.text.Layout; 27d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.text.StaticLayout; 28d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.text.TextPaint; 2952c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkeyimport android.util.AttributeSet; 30d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport android.util.TypedValue; 31ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport android.view.View; 32ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 33d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkeyimport com.android.settings.DataUsageSummary; 3452c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkeyimport com.android.settings.R; 35ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeyimport com.google.common.base.Preconditions; 36ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 37ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey/** 38ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * Background of {@link ChartView} that renders grid lines as requested by 39ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey * {@link ChartAxis#getTickPoints()}. 40ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey */ 41ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkeypublic class ChartGridView extends View { 42ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 4352c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey private ChartAxis mHoriz; 4452c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey private ChartAxis mVert; 45ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 4652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey private Drawable mPrimary; 4752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey private Drawable mSecondary; 4852c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey private Drawable mBorder; 49d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey private int mLabelColor; 50d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 51d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey private Layout mLayoutStart; 52d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey private Layout mLayoutEnd; 53ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 5452c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey public ChartGridView(Context context) { 5552c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey this(context, null, 0); 5652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey } 5752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 5852c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey public ChartGridView(Context context, AttributeSet attrs) { 5952c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey this(context, attrs, 0); 6052c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey } 6152c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 6252c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey public ChartGridView(Context context, AttributeSet attrs, int defStyle) { 6352c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey super(context, attrs, defStyle); 64ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 65ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey setWillNotDraw(false); 66ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 6752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final TypedArray a = context.obtainStyledAttributes( 6852c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey attrs, R.styleable.ChartGridView, defStyle, 0); 6952c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 7052c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable); 7152c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable); 7252c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable); 73d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey mLabelColor = a.getColor(R.styleable.ChartGridView_labelColor, Color.RED); 7452c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 7552c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey a.recycle(); 7652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey } 7752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 7852c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey void init(ChartAxis horiz, ChartAxis vert) { 7952c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mHoriz = Preconditions.checkNotNull(horiz, "missing horiz"); 8052c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mVert = Preconditions.checkNotNull(vert, "missing vert"); 81ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 82ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 83d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey void setBounds(long start, long end) { 84d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey final Context context = getContext(); 85d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey mLayoutStart = makeLayout(DataUsageSummary.formatDateRange(context, start, start, true)); 86d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey mLayoutEnd = makeLayout(DataUsageSummary.formatDateRange(context, end, end, true)); 87d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey invalidate(); 88d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey } 89d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 90ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey @Override 91ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey protected void onDraw(Canvas canvas) { 92ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int width = getWidth(); 93ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final int height = getHeight(); 94ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 9552c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final Drawable secondary = mSecondary; 9652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final int secondaryHeight = mSecondary.getIntrinsicHeight(); 9752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 98ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final float[] vertTicks = mVert.getTickPoints(); 99ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey for (float y : vertTicks) { 10052c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final int bottom = (int) Math.min(y + secondaryHeight, height); 10152c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey secondary.setBounds(0, (int) y, width, bottom); 10252c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey secondary.draw(canvas); 103ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 104ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 10552c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final Drawable primary = mPrimary; 10652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final int primaryWidth = mPrimary.getIntrinsicWidth(); 10752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final int primaryHeight = mPrimary.getIntrinsicHeight(); 10852c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey 109ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey final float[] horizTicks = mHoriz.getTickPoints(); 110ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey for (float x : horizTicks) { 11152c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey final int right = (int) Math.min(x + primaryWidth, width); 11252c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey primary.setBounds((int) x, 0, right, height); 11352c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey primary.draw(canvas); 114ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 115ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey 11652c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mBorder.setBounds(0, 0, width, height); 11752c3f4461b806e4f1ce48455ee2ba0ac05dfdab4Jeff Sharkey mBorder.draw(canvas); 118d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 11930dde0f5a07e1b15de21d6a278721d918c5900beJeff Sharkey final int padding = mLayoutStart != null ? mLayoutStart.getHeight() / 8 : 0; 120d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 121d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey final Layout start = mLayoutStart; 122d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey if (start != null) { 123d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.save(); 124d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.translate(0, height + padding); 125d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey start.draw(canvas); 126d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.restore(); 127d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey } 128d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 129d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey final Layout end = mLayoutEnd; 130d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey if (end != null) { 131d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.save(); 132d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.translate(width - end.getWidth(), height + padding); 133d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey end.draw(canvas); 134d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey canvas.restore(); 135d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey } 136ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey } 137d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 138d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey private Layout makeLayout(CharSequence text) { 139d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey final Resources res = getResources(); 140d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 141d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey paint.density = res.getDisplayMetrics().density; 142d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale); 143d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey paint.setColor(mLabelColor); 144d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey paint.setTextSize( 145d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 10, res.getDisplayMetrics())); 146d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 147d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey return new StaticLayout(text, paint, 148d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey (int) Math.ceil(Layout.getDesiredWidth(text, paint)), 149d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true); 150d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey } 151d39c6e4083f1212519d5dc14f64132a10f2b7c7aJeff Sharkey 152ab2d8d3a38857b8c155e6c6393c5821f5a341aaeJeff Sharkey} 153