blob: 768a7173013c182afebc91e96e5239d16623bace [file] [log] [blame]
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -07001/*
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
17package com.android.settings.widget;
18
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070019import android.content.Context;
Jeff Sharkey54d0af52011-08-11 18:26:57 -070020import android.content.res.TypedArray;
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070021import android.graphics.Rect;
Jeff Sharkey52c3f442011-06-23 00:39:38 -070022import android.util.AttributeSet;
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070023import android.view.Gravity;
24import android.view.View;
Jeff Sharkey54d0af52011-08-11 18:26:57 -070025import android.view.ViewDebug;
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070026import android.widget.FrameLayout;
27
Jeff Sharkeye6c50032013-03-06 11:46:54 -080028import com.android.internal.util.Preconditions;
Jeff Sharkey54d0af52011-08-11 18:26:57 -070029import com.android.settings.R;
30
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070031/**
32 * Container for two-dimensional chart, drawn with a combination of
Doris Ling8e208c62018-10-08 14:18:50 -070033 * {@link ChartGridView} and {@link ChartSweepView} children. The entire chart uses
34 * {@link ChartAxis} to map between raw values
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070035 * and screen coordinates.
36 */
37public class ChartView extends FrameLayout {
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070038 // TODO: extend something that supports two-dimensional scrolling
39
Fabrice Di Meglio79d8e802012-07-19 19:25:50 -070040 private static final int SWEEP_GRAVITY = Gravity.TOP | Gravity.START;
Jeff Sharkeyf54f4352011-06-23 22:15:54 -070041
Jeff Sharkey52c3f442011-06-23 00:39:38 -070042 ChartAxis mHoriz;
43 ChartAxis mVert;
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070044
Jeff Sharkey54d0af52011-08-11 18:26:57 -070045 @ViewDebug.ExportedProperty
46 private int mOptimalWidth = -1;
47 private float mOptimalWidthWeight = 0;
48
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070049 private Rect mContent = new Rect();
50
Jeff Sharkey52c3f442011-06-23 00:39:38 -070051 public ChartView(Context context) {
52 this(context, null, 0);
53 }
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070054
Jeff Sharkey52c3f442011-06-23 00:39:38 -070055 public ChartView(Context context, AttributeSet attrs) {
56 this(context, attrs, 0);
57 }
58
59 public ChartView(Context context, AttributeSet attrs, int defStyle) {
60 super(context, attrs, defStyle);
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070061
Jeff Sharkey54d0af52011-08-11 18:26:57 -070062 final TypedArray a = context.obtainStyledAttributes(
63 attrs, R.styleable.ChartView, defStyle, 0);
64 setOptimalWidth(a.getDimensionPixelSize(R.styleable.ChartView_optimalWidth, -1),
65 a.getFloat(R.styleable.ChartView_optimalWidthWeight, 0));
66 a.recycle();
67
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070068 setClipToPadding(false);
69 setClipChildren(false);
70 }
71
Jeff Sharkey52c3f442011-06-23 00:39:38 -070072 void init(ChartAxis horiz, ChartAxis vert) {
Jeff Sharkeye6c50032013-03-06 11:46:54 -080073 mHoriz = Preconditions.checkNotNull(horiz, "missing horiz");
74 mVert = Preconditions.checkNotNull(vert, "missing vert");
Jeff Sharkey52c3f442011-06-23 00:39:38 -070075 }
76
Jeff Sharkey54d0af52011-08-11 18:26:57 -070077 public void setOptimalWidth(int optimalWidth, float optimalWidthWeight) {
78 mOptimalWidth = optimalWidth;
79 mOptimalWidthWeight = optimalWidthWeight;
80 requestLayout();
81 }
82
83 @Override
84 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
85 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
86
87 final int slack = getMeasuredWidth() - mOptimalWidth;
88 if (mOptimalWidth > 0 && slack > 0) {
89 final int targetWidth = (int) (mOptimalWidth + (slack * mOptimalWidthWeight));
90 widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY);
91 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
92 }
93 }
94
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070095 @Override
96 protected void onLayout(boolean changed, int l, int t, int r, int b) {
Jeff Sharkey8a503642011-06-10 13:31:21 -070097 mContent.set(getPaddingLeft(), getPaddingTop(), r - l - getPaddingRight(),
98 b - t - getPaddingBottom());
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -070099 final int width = mContent.width();
100 final int height = mContent.height();
101
102 // no scrolling yet, so tell dimensions to fill exactly
103 mHoriz.setSize(width);
104 mVert.setSize(height);
105
106 final Rect parentRect = new Rect();
107 final Rect childRect = new Rect();
108
109 for (int i = 0; i < getChildCount(); i++) {
110 final View child = getChildAt(i);
111 final LayoutParams params = (LayoutParams) child.getLayoutParams();
112
113 parentRect.set(mContent);
114
Doris Ling8e208c62018-10-08 14:18:50 -0700115 if (child instanceof ChartGridView) {
Jeff Sharkeyb6548462014-07-21 15:38:06 -0700116 // Grid uses some extra room for labels
117 Gravity.apply(params.gravity, width, height, parentRect, childRect);
118 child.layout(childRect.left, childRect.top, childRect.right,
119 childRect.bottom + child.getPaddingBottom());
120
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -0700121 } else if (child instanceof ChartSweepView) {
Jeff Sharkey55d18a52011-08-27 17:09:43 -0700122 layoutSweep((ChartSweepView) child, parentRect, childRect);
123 child.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -0700124 }
Jeff Sharkey55d18a52011-08-27 17:09:43 -0700125 }
126 }
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -0700127
Jeff Sharkey55d18a52011-08-27 17:09:43 -0700128 protected void layoutSweep(ChartSweepView sweep) {
129 final Rect parentRect = new Rect(mContent);
130 final Rect childRect = new Rect();
131
132 layoutSweep(sweep, parentRect, childRect);
133 sweep.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
134 }
135
136 protected void layoutSweep(ChartSweepView sweep, Rect parentRect, Rect childRect) {
137 final Rect sweepMargins = sweep.getMargins();
138
139 // sweep is always placed along specific dimension
140 if (sweep.getFollowAxis() == ChartSweepView.VERTICAL) {
141 parentRect.top += sweepMargins.top + (int) sweep.getPoint();
142 parentRect.bottom = parentRect.top;
143 parentRect.left += sweepMargins.left;
144 parentRect.right += sweepMargins.right;
145 Gravity.apply(SWEEP_GRAVITY, parentRect.width(), sweep.getMeasuredHeight(),
146 parentRect, childRect);
147
148 } else {
149 parentRect.left += sweepMargins.left + (int) sweep.getPoint();
150 parentRect.right = parentRect.left;
151 parentRect.top += sweepMargins.top;
152 parentRect.bottom += sweepMargins.bottom;
153 Gravity.apply(SWEEP_GRAVITY, sweep.getMeasuredWidth(), parentRect.height(),
154 parentRect, childRect);
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -0700155 }
156 }
Jeff Sharkeyab2d8d32011-05-30 16:19:56 -0700157}