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