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.Utils.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.view.View; 33 34 import com.android.internal.util.Preconditions; 35 import com.android.settings.R; 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 StaticLayout.Builder.obtain(text, 0, text.length(), paint, 174 (int) Math.ceil(Layout.getDesiredWidth(text, paint))) 175 .setUseLineSpacingFromFallbacks(true) 176 .build(); 177 } 178 } 179