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 android.content.Context;
20 import android.content.res.ColorStateList;
21 import android.content.res.Resources;
22 import android.content.res.TypedArray;
23 import android.graphics.Canvas;
24 import android.graphics.Paint;
25 import android.graphics.drawable.Drawable;
26 import android.text.Layout;
27 import android.text.StaticLayout;
28 import android.text.TextPaint;
29 import android.util.AttributeSet;
30 import android.view.View;
31 
32 import com.android.internal.util.Preconditions;
33 import com.android.settings.R;
34 
35 import static com.android.settings.Utils.formatDateRange;
36 
37 /**
38  * Background of {@link ChartView} that renders grid lines as requested by
39  * {@link ChartAxis#getTickPoints()}.
40  */
41 public class ChartGridView extends View {
42 
43     private ChartAxis mHoriz;
44     private ChartAxis mVert;
45 
46     private Drawable mPrimary;
47     private Drawable mSecondary;
48     private Drawable mBorder;
49 
50     private int mLabelSize;
51     private int mLabelColor;
52 
53     private Layout mLabelStart;
54     private Layout mLabelMid;
55     private Layout mLabelEnd;
56 
ChartGridView(Context context)57     public ChartGridView(Context context) {
58         this(context, null, 0);
59     }
60 
ChartGridView(Context context, AttributeSet attrs)61     public ChartGridView(Context context, AttributeSet attrs) {
62         this(context, attrs, 0);
63     }
64 
ChartGridView(Context context, AttributeSet attrs, int defStyle)65     public ChartGridView(Context context, AttributeSet attrs, int defStyle) {
66         super(context, attrs, defStyle);
67 
68         setWillNotDraw(false);
69 
70         final TypedArray a = context.obtainStyledAttributes(
71                 attrs, R.styleable.ChartGridView, defStyle, 0);
72 
73         mPrimary = a.getDrawable(R.styleable.ChartGridView_primaryDrawable);
74         mSecondary = a.getDrawable(R.styleable.ChartGridView_secondaryDrawable);
75         mBorder = a.getDrawable(R.styleable.ChartGridView_borderDrawable);
76 
77         final int taId = a.getResourceId(R.styleable.ChartGridView_android_textAppearance, -1);
78         final TypedArray ta = context.obtainStyledAttributes(taId,
79                 com.android.internal.R.styleable.TextAppearance);
80         mLabelSize = ta.getDimensionPixelSize(
81                 com.android.internal.R.styleable.TextAppearance_textSize, 0);
82         ta.recycle();
83 
84         final ColorStateList labelColor = a.getColorStateList(
85                 R.styleable.ChartGridView_android_textColor);
86         mLabelColor = labelColor.getDefaultColor();
87 
88         a.recycle();
89     }
90 
init(ChartAxis horiz, ChartAxis vert)91     void init(ChartAxis horiz, ChartAxis vert) {
92         mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
93         mVert = Preconditions.checkNotNull(vert, "missing vert");
94     }
95 
setBounds(long start, long end)96     void setBounds(long start, long end) {
97         final Context context = getContext();
98         final long mid = (start + end) / 2;
99         mLabelStart = makeLabel(formatDateRange(context, start, start));
100         mLabelMid = makeLabel(formatDateRange(context, mid, mid));
101         mLabelEnd = makeLabel(formatDateRange(context, end, end));
102         invalidate();
103     }
104 
105     @Override
onDraw(Canvas canvas)106     protected void onDraw(Canvas canvas) {
107         final int width = getWidth();
108         final int height = getHeight() - getPaddingBottom();
109 
110         final Drawable secondary = mSecondary;
111         if (secondary != null) {
112             final int secondaryHeight = secondary.getIntrinsicHeight();
113 
114             final float[] vertTicks = mVert.getTickPoints();
115             for (float y : vertTicks) {
116                 final int bottom = (int) Math.min(y + secondaryHeight, height);
117                 secondary.setBounds(0, (int) y, width, bottom);
118                 secondary.draw(canvas);
119             }
120         }
121 
122         final Drawable primary = mPrimary;
123         if (primary != null) {
124             final int primaryWidth = primary.getIntrinsicWidth();
125             final int primaryHeight = primary.getIntrinsicHeight();
126 
127             final float[] horizTicks = mHoriz.getTickPoints();
128             for (float x : horizTicks) {
129                 final int right = (int) Math.min(x + primaryWidth, width);
130                 primary.setBounds((int) x, 0, right, height);
131                 primary.draw(canvas);
132             }
133         }
134 
135         mBorder.setBounds(0, 0, width, height);
136         mBorder.draw(canvas);
137 
138         final int padding = mLabelStart != null ? mLabelStart.getHeight() / 8 : 0;
139 
140         final Layout start = mLabelStart;
141         if (start != null) {
142             final int saveCount = canvas.save();
143             canvas.translate(0, height + padding);
144             start.draw(canvas);
145             canvas.restoreToCount(saveCount);
146         }
147 
148         final Layout mid = mLabelMid;
149         if (mid != null) {
150             final int saveCount = canvas.save();
151             canvas.translate((width - mid.getWidth()) / 2, height + padding);
152             mid.draw(canvas);
153             canvas.restoreToCount(saveCount);
154         }
155 
156         final Layout end = mLabelEnd;
157         if (end != null) {
158             final int saveCount = canvas.save();
159             canvas.translate(width - end.getWidth(), height + padding);
160             end.draw(canvas);
161             canvas.restoreToCount(saveCount);
162         }
163     }
164 
makeLabel(CharSequence text)165     private Layout makeLabel(CharSequence text) {
166         final Resources res = getResources();
167         final TextPaint paint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
168         paint.density = res.getDisplayMetrics().density;
169         paint.setCompatibilityScaling(res.getCompatibilityInfo().applicationScale);
170         paint.setColor(mLabelColor);
171         paint.setTextSize(mLabelSize);
172 
173         return new StaticLayout(text, paint,
174                 (int) Math.ceil(Layout.getDesiredWidth(text, paint)),
175                 Layout.Alignment.ALIGN_NORMAL, 1.f, 0, true);
176     }
177 }
178