1d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung/*
2d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * Copyright (C) 2012 The Android Open Source Project
3d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung *
4d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * you may not use this file except in compliance with the License.
6d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * You may obtain a copy of the License at
7d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung *
8d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung *
10d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * Unless required by applicable law or agreed to in writing, software
11d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * See the License for the specific language governing permissions and
14d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung * limitations under the License.
15d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung */
16d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
17d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungpackage com.android.systemui.statusbar.phone;
18d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
19d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.animation.LayoutTransition;
20d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.content.Context;
21d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.content.res.Resources;
22d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.util.AttributeSet;
23c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chungimport android.view.View;
24d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.view.ViewGroup;
25d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport android.widget.FrameLayout;
26d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
27d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungimport com.android.systemui.R;
28d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
29d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung/**
30d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung *
31d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung */
32d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chungclass QuickSettingsContainerView extends FrameLayout {
33d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
34d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    // The number of columns in the QuickSettings grid
35d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    private int mNumColumns;
36d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
37d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    // The gap between tiles in the QuickSettings grid
38d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    private float mCellGap;
39d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
40d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    public QuickSettingsContainerView(Context context, AttributeSet attrs) {
41d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        super(context, attrs);
42d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
43d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        updateResources();
44d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    }
45d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
46d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    @Override
47d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    protected void onFinishInflate() {
48d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        super.onFinishInflate();
49d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
50d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        // TODO: Setup the layout transitions
51d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        LayoutTransition transitions = getLayoutTransition();
52d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    }
53d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
54d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    void updateResources() {
55d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        Resources r = getContext().getResources();
56d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap);
57d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        mNumColumns = r.getInteger(R.integer.quick_settings_num_columns);
58d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        requestLayout();
59d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    }
60d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
61d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    @Override
62d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
63d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        // Calculate the cell width dynamically
64d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int width = MeasureSpec.getSize(widthMeasureSpec);
65d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int height = MeasureSpec.getSize(heightMeasureSpec);
66d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int availableWidth = (int) (width - getPaddingLeft() - getPaddingRight() -
67d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                (mNumColumns - 1) * mCellGap);
68f4b5ab193c95675c07b8e361846d21d79571da0eWinson Chung        float cellWidth = (float) Math.ceil(((float) availableWidth) / mNumColumns);
69d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
70d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        // Update each of the children's widths accordingly to the cell width
718afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio        final int N = getChildCount();
72d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int cellHeight = 0;
73d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int cursor = 0;
74d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        for (int i = 0; i < N; ++i) {
75d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung            // Update the child's width
76d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung            QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
77c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung            if (v.getVisibility() != View.GONE) {
78c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
79c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                int colSpan = v.getColumnSpan();
80c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap);
81c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung
82c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                // Measure the child
83c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                int newWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
84c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                int newHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
85c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                v.measure(newWidthSpec, newHeightSpec);
86c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung
87c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                // Save the cell height
88c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                if (cellHeight <= 0) {
89c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                    cellHeight = v.getMeasuredHeight();
90c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                }
91c86b23b9a6bc4763ff3fbe8d0ae8a9b2e21a1649Winson Chung                cursor += colSpan;
92d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung            }
93d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        }
94d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
95d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        // Set the measured dimensions.  We always fill the tray width, but wrap to the height of
96d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        // all the tiles.
97d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int numRows = (int) Math.ceil((float) cursor / mNumColumns);
98d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int newHeight = (int) ((numRows * cellHeight) + ((numRows - 1) * mCellGap)) +
99d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                getPaddingTop() + getPaddingBottom();
100d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        setMeasuredDimension(width, newHeight);
101d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    }
102d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
103d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    @Override
104d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
1058afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio        final int N = getChildCount();
1068afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio        final boolean isLayoutRtl = isLayoutRtl();
1078afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio        final int width = getWidth();
1088afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
1098afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio        int x = getPaddingStart();
110d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int y = getPaddingTop();
111d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        int cursor = 0;
1128afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
113d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        for (int i = 0; i < N; ++i) {
1148afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio            QuickSettingsTileView child = (QuickSettingsTileView) getChildAt(i);
1158afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio            ViewGroup.LayoutParams lp = child.getLayoutParams();
1168afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio            if (child.getVisibility() != GONE) {
1178afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int col = cursor % mNumColumns;
1188afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int colSpan = child.getColumnSpan();
1198afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
1208afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childWidth = lp.width;
1218afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childHeight = lp.height;
1228afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
123d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                int row = (int) (cursor / mNumColumns);
124d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
125d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                // Push the item to the next row if it can't fit on this one
126d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                if ((col + colSpan) > mNumColumns) {
1278afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                    x = getPaddingStart();
1288afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                    y += childHeight + mCellGap;
129d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                    row++;
130d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                }
131d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
1328afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childLeft = (isLayoutRtl) ? width - x - childWidth : x;
1338afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childRight = childLeft + childWidth;
1348afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
1358afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childTop = y;
1368afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                final int childBottom = childTop + childHeight;
1378afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio
138d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                // Layout the container
1398afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                child.layout(childLeft, childTop, childRight, childBottom);
140d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung
141d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                // Offset the position by the cell gap or reset the position and cursor when we
142d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                // reach the end of the row
1438afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                cursor += child.getColumnSpan();
144d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                if (cursor < (((row + 1) * mNumColumns))) {
1458afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                    x += childWidth + mCellGap;
146d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                } else {
1478afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                    x = getPaddingStart();
1488afcd149970c79054a3a16377834aa0aec35eee0Fabrice Di Meglio                    y += childHeight + mCellGap;
149d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung                }
150d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung            }
151d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung        }
152d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung    }
153d63c59786509aadd6a8d0c5cb45ed696339f16b7Winson Chung}