1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.widget;
18 
19 import static com.android.settings.DataUsageSummary.formatDateRange;
20 
21 import android.content.Context;
22 import android.content.res.ColorStateList;
23 import android.content.res.Resources;
24 import android.content.res.TypedArray;
25 import android.graphics.Canvas;
26 import android.graphics.Paint;
27 import android.graphics.drawable.Drawable;
28 import android.text.Layout;
29 import android.text.StaticLayout;
30 import android.text.TextPaint;
31 import android.util.AttributeSet;
32 import android.util.Log;
33 import android.util.TypedValue;
34 import android.view.View;
35 
36 import com.android.internal.util.Preconditions;
37 import com.android.settings.R;
38 
39 import java.util.Locale;
40 
41 /**
42  * Background of {@link ChartView} that renders grid lines as requested by
43  * {@link ChartAxis#getTickPoints()}.
44  */
45 public class ChartGridView extends View {
46 
47     private ChartAxis mHoriz;
48     private ChartAxis mVert;
49 
50     private Drawable mPrimary;
51     private Drawable mSecondary;
52     private Drawable mBorder;
53 
54     private int mLabelSize;
55     private int mLabelColor;
56 
57     private Layout mLabelStart;
58     private Layout mLabelMid;
59     private Layout mLabelEnd;
60 
ChartGridView(Context context)61     public ChartGridView(Context context) {
62         this(context, null, 0);
63     }
64 
ChartGridView(Context context, AttributeSet attrs)65     public ChartGridView(Context context, AttributeSet attrs) {
66         this(context, attrs, 0);
67     }
68 
ChartGridView(Context context, AttributeSet attrs, int defStyle)69     public ChartGridView(Context context, AttributeSet attrs, int defStyle) {
70         super(context, attrs, defStyle);
71 
72         setWillNotDraw(false);
73 
74         final TypedArray a = context.obtainStyledAttributes(
75                 attrs, R.styleable.ChartGridView, defStyle, 0);
76 
77         mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
78         mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
79         mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
80 
81         final int taId = a.getResourceId(R.styleable.ChartGridView_android_textAppearance, -1);
82         final TypedArray ta = context.obtainStyledAttributes(taId,
83                 com.android.internal.R.styleable.TextAppearance);
84         mLabelSize = ta.getDimensionPixelSize(
85                 com.android.internal.R.styleable.TextAppearance_textSize, 0);
86         ta.recycle();
87 
88         final ColorStateList labelColor = a.getColorStateList(
89                 R.styleable.ChartGridView_android_textColor);
90         mLabelColor = labelColor.getDefaultColor();
91 
92         a.recycle();
93     }
94 
init(ChartAxis horiz, ChartAxis vert)95     void init(ChartAxis horiz, ChartAxis vert) {
96         mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
97         mVert = Preconditions.checkNotNull(vert, "missing vert");
98     }
99 
setBounds(long start, long end)100     void setBounds(long start, long end) {
101         final Context context = getContext();
102         final long mid = (start + end) / 2;
103         mLabelStart = makeLabel(formatDateRange(context, start, start));
104         mLabelMid = makeLabel(formatDateRange(context, mid, mid));
105         mLabelEnd = makeLabel(formatDateRange(context, end, end));
106         invalidate();
107     }
108 
109     @Override
onDraw(Canvas canvas)110     protected void onDraw(Canvas canvas) {
111         final int width = getWidth();
112         final int height = getHeight() - getPaddingBottom();
113 
114         final Drawable secondary = mSecondary;
115         if (secondary != null) {
116             final int secondaryHeight = secondary.getIntrinsicHeight();
117 
118             final float[] vertTicks = mVert.getTickPoints();
119             for (float y : vertTicks) {
120                 final int bottom = (int) Math.min(y + secondaryHeight, height);
121                 secondary.setBounds(0, (int) y, width, bottom);
122                 secondary.draw(canvas);
123             }
124         }
125 
126         final Drawable primary = mPrimary;
127         if (primary != null) {
128             final int primaryWidth = primary.getIntrinsicWidth();
129             final int primaryHeight = primary.getIntrinsicHeight();
130 
131             final float[] horizTicks = mHoriz.getTickPoints();
132             for (float x : horizTicks) {
133                 final int right = (int) Math.min(x + primaryWidth, width);
134                 primary.setBounds((int) x, 0, right, height);
135                 primary.draw(canvas);
136             }
137         }
138 
139         mBorder.setBounds(0, 0, width, height);
140         mBorder.draw(canvas);
141 
142         final int padding = mLabelStart != null ? mLabelStart.getHeight() / 8 : 0;
143 
144         final Layout start = mLabelStart;
145         if (start != null) {
146             final int saveCount = canvas.save();
147             canvas.translate(0, height + padding);
148             start.draw(canvas);
149             canvas.restoreToCount(saveCount);
150         }
151 
152         final Layout mid = mLabelMid;
153         if (mid != null) {
154             final int saveCount = canvas.save();
155             canvas.translate((width - mid.getWidth()) / 2, height + padding);
156             mid.draw(canvas);
157             canvas.restoreToCount(saveCount);
158         }
159 
160         final Layout end = mLabelEnd;
161         if (end != null) {
162             final int saveCount = canvas.save();
163             canvas.translate(width - end.getWidth(), height + padding);
164             end.draw(canvas);
165             canvas.restoreToCount(saveCount);
166         }
167     }
168 
makeLabel(CharSequence text)169     private Layout makeLabel(CharSequence text) {
170         final Resources res = getResources();
171         final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
172         paint.density = res.getDisplayMetrics().density;
173         paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
174         paint.setColor(mLabelColor);
175         paint.setTextSize(mLabelSize);
176 
177         return new StaticLayout(text, paint,
178                 (int) Math.ceil(Layout.getDesiredWidth(text, paint)),
179                 Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
180     }
181 }
182