1af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock/* 2af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Copyright (C) 2014 The Android Open Source Project 3af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 4af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 5af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * you may not use this file except in compliance with the License. 6af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * You may obtain a copy of the License at 7af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 8af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * http://www.apache.org/licenses/LICENSE-2.0 9af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * 10af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * Unless required by applicable law or agreed to in writing, software 11af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 12af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * See the License for the specific language governing permissions and 14af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock * limitations under the License. 15af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock */ 16af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 17af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockpackage com.android.systemui.qs; 18af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 19af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.animation.Animator; 20af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.animation.Animator.AnimatorListener; 21af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.animation.AnimatorListenerAdapter; 22af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.content.Context; 237f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlockimport android.content.Intent; 24e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggiimport android.content.res.Configuration; 254bf31983d247a76142937c01bc2800b7f98d0281John Spurlockimport android.content.res.Resources; 26af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Handler; 27af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.os.Message; 28af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.util.AttributeSet; 29e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggiimport android.util.TypedValue; 307f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlockimport android.view.LayoutInflater; 31af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.view.View; 32af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport android.view.ViewGroup; 336783bef9b9b26df093b07b0044cf079a0b5011cdJason Monkimport android.view.accessibility.AccessibilityEvent; 343f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggiimport android.widget.ImageView; 35e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggiimport android.widget.TextView; 36af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 37e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggiimport com.android.systemui.FontSizeUtils; 38af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport com.android.systemui.R; 397f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlockimport com.android.systemui.qs.QSTile.DetailAdapter; 403f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggiimport com.android.systemui.settings.BrightnessController; 413f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggiimport com.android.systemui.settings.ToggleSlider; 421ef80fe5905a19cf92f073163c187a96287335e4Adrian Roosimport com.android.systemui.statusbar.phone.QSTileHost; 435fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roosimport com.android.systemui.statusbar.policy.BrightnessMirrorController; 44af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 45af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockimport java.util.ArrayList; 46bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlockimport java.util.Collection; 47af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 48af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock/** View that represents the quick settings tile panel. **/ 49af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlockpublic class QSPanel extends ViewGroup { 504bf31983d247a76142937c01bc2800b7f98d0281John Spurlock private static final float TILE_ASPECT = 1.2f; 51af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 52af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private final Context mContext; 53af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private final ArrayList<TileRecord> mRecords = new ArrayList<TileRecord>(); 547f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock private final View mDetail; 557f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock private final ViewGroup mDetailContent; 56e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi private final TextView mDetailSettingsButton; 57e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi private final TextView mDetailDoneButton; 583f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi private final View mBrightnessView; 598af525dd7d1640175fda344301a8712725557caaJohn Spurlock private final QSDetailClipper mClipper; 60af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private final H mHandler = new H(); 61af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 62af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int mColumns; 63af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int mCellWidth; 64af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int mCellHeight; 65af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int mLargeCellWidth; 66af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int mLargeCellHeight; 6792d9b19e1bc5f93ef31c4e6eb3395eaf78a5c84eJohn Spurlock private int mPanelPaddingBottom; 6839076ed379c293399292d1c6b799866c1321b44bJohn Spurlock private int mDualTileUnderlap; 69cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos private int mBrightnessPaddingTop; 708bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi private int mGridHeight; 715729d090ab44228ff342a10b4ec0552741371501John Spurlock private boolean mExpanded; 72e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi private boolean mListening; 738bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi private boolean mClosingDetail; 74af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 751ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private Record mDetailRecord; 765729d090ab44228ff342a10b4ec0552741371501John Spurlock private Callback mCallback; 773f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi private BrightnessController mBrightnessController; 781ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private QSTileHost mHost; 79af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 803d5f551cd5905c835bb789406763764a8a9a73deJason Monk private QSFooter mFooter; 81e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek private boolean mGridContentVisible = true; 823d5f551cd5905c835bb789406763764a8a9a73deJason Monk 83af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public QSPanel(Context context) { 84af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock this(context, null); 85af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 86af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 87af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public QSPanel(Context context, AttributeSet attrs) { 88af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock super(context, attrs); 89af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mContext = context; 90af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 917f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetail = LayoutInflater.from(context).inflate(R.layout.qs_detail, this, false); 927f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailContent = (ViewGroup) mDetail.findViewById(android.R.id.content); 93e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi mDetailSettingsButton = (TextView) mDetail.findViewById(android.R.id.button2); 94e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi mDetailDoneButton = (TextView) mDetail.findViewById(android.R.id.button1); 95e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk updateDetailText(); 96af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mDetail.setVisibility(GONE); 97af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mDetail.setClickable(true); 983f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi mBrightnessView = LayoutInflater.from(context).inflate( 993f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi R.layout.quick_settings_brightness_dialog, this, false); 1003d5f551cd5905c835bb789406763764a8a9a73deJason Monk mFooter = new QSFooter(this, context); 101af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock addView(mDetail); 1023f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi addView(mBrightnessView); 1033d5f551cd5905c835bb789406763764a8a9a73deJason Monk addView(mFooter.getView()); 1048af525dd7d1640175fda344301a8712725557caaJohn Spurlock mClipper = new QSDetailClipper(mDetail); 105af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock updateResources(); 1063f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi 1073f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi mBrightnessController = new BrightnessController(getContext(), 1083f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi (ImageView) findViewById(R.id.brightness_icon), 1093f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi (ToggleSlider) findViewById(R.id.brightness_slider)); 1101ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 1111ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos mDetailDoneButton.setOnClickListener(new OnClickListener() { 1121ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos @Override 1131ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos public void onClick(View v) { 114f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock closeDetail(); 1151ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 1161ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos }); 117af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 118af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 119e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk private void updateDetailText() { 120e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk mDetailDoneButton.setText(R.string.quick_settings_done); 121e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk mDetailSettingsButton.setText(R.string.quick_settings_more_settings); 122e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk } 123e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk 1245fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos public void setBrightnessMirror(BrightnessMirrorController c) { 1255fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos super.onFinishInflate(); 1265fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos ToggleSlider brightnessSlider = (ToggleSlider) findViewById(R.id.brightness_slider); 1275fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos ToggleSlider mirror = (ToggleSlider) c.getMirror().findViewById(R.id.brightness_slider); 1285fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos brightnessSlider.setMirror(mirror); 1295fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos brightnessSlider.setMirrorController(c); 1305fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos } 1315fd872e8ea44ffcd4fce1d1196736dca4f270508Adrian Roos 1325729d090ab44228ff342a10b4ec0552741371501John Spurlock public void setCallback(Callback callback) { 1335729d090ab44228ff342a10b4ec0552741371501John Spurlock mCallback = callback; 1345729d090ab44228ff342a10b4ec0552741371501John Spurlock } 1355729d090ab44228ff342a10b4ec0552741371501John Spurlock 1361ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos public void setHost(QSTileHost host) { 1371ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos mHost = host; 1383d5f551cd5905c835bb789406763764a8a9a73deJason Monk mFooter.setHost(host); 1391ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 1401ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 14100a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos public QSTileHost getHost() { 14200a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos return mHost; 14300a0b1f397557790cf9ab55fe06e72a96ebc5353Adrian Roos } 1441ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 145af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void updateResources() { 1464bf31983d247a76142937c01bc2800b7f98d0281John Spurlock final Resources res = mContext.getResources(); 1474bf31983d247a76142937c01bc2800b7f98d0281John Spurlock final int columns = Math.max(1, res.getInteger(R.integer.quick_settings_num_columns)); 1484bf31983d247a76142937c01bc2800b7f98d0281John Spurlock mCellHeight = res.getDimensionPixelSize(R.dimen.qs_tile_height); 1494bf31983d247a76142937c01bc2800b7f98d0281John Spurlock mCellWidth = (int)(mCellHeight * TILE_ASPECT); 1504bf31983d247a76142937c01bc2800b7f98d0281John Spurlock mLargeCellHeight = res.getDimensionPixelSize(R.dimen.qs_dual_tile_height); 1514bf31983d247a76142937c01bc2800b7f98d0281John Spurlock mLargeCellWidth = (int)(mLargeCellHeight * TILE_ASPECT); 15292d9b19e1bc5f93ef31c4e6eb3395eaf78a5c84eJohn Spurlock mPanelPaddingBottom = res.getDimensionPixelSize(R.dimen.qs_panel_padding_bottom); 15339076ed379c293399292d1c6b799866c1321b44bJohn Spurlock mDualTileUnderlap = res.getDimensionPixelSize(R.dimen.qs_dual_tile_padding_vertical); 154cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos mBrightnessPaddingTop = res.getDimensionPixelSize(R.dimen.qs_brightness_padding_top); 155af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (mColumns != columns) { 156af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mColumns = columns; 157af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock postInvalidate(); 158af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 1591a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock if (mListening) { 1601a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock refreshAllTiles(); 1611a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock } 162e2f4771a0105ad6a94ff759353ca00c3a5fba72aJason Monk updateDetailText(); 163af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 164af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 165e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi @Override 166e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi protected void onConfigurationChanged(Configuration newConfig) { 167e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi super.onConfigurationChanged(newConfig); 168e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi FontSizeUtils.updateFontSize(mDetailDoneButton, R.dimen.qs_detail_button_text_size); 169e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi FontSizeUtils.updateFontSize(mDetailSettingsButton, R.dimen.qs_detail_button_text_size); 170e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi 171e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi // We need to poke the detail views as well as they might not be attached to the view 172e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi // hierarchy but reused at a later point. 173e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi int count = mRecords.size(); 174e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi for (int i = 0; i < count; i++) { 175e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi View detailView = mRecords.get(i).detailView; 176e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi if (detailView != null) { 177e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi detailView.dispatchConfigurationChanged(newConfig); 178e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi } 179e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi } 180e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi mFooter.onConfigurationChanged(); 181e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi } 182e17c4b49a41ec9de5c1d7f229273fc4677ec24b1Jorim Jaggi 183af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void setExpanded(boolean expanded) { 1845729d090ab44228ff342a10b4ec0552741371501John Spurlock if (mExpanded == expanded) return; 1855729d090ab44228ff342a10b4ec0552741371501John Spurlock mExpanded = expanded; 1865729d090ab44228ff342a10b4ec0552741371501John Spurlock if (!mExpanded) { 187f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock closeDetail(); 188af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 189e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi } 190e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi 191e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi public void setListening(boolean listening) { 192e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi if (mListening == listening) return; 193e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi mListening = listening; 194af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock for (TileRecord r : mRecords) { 195e65e310fc979fa708d7469d01e42188174e47cf8Jorim Jaggi r.tile.setListening(mListening); 1961a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock } 1973d5f551cd5905c835bb789406763764a8a9a73deJason Monk mFooter.setListening(mListening); 1981a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock if (mListening) { 1991a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock refreshAllTiles(); 200af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 2013f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi if (listening) { 2023f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi mBrightnessController.registerCallbacks(); 2033f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi } else { 2043f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi mBrightnessController.unregisterCallbacks(); 2053f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi } 206af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 207af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 2081ecd7cd58ed0f823610c7fdae56806d08339e7caJorim Jaggi public void refreshAllTiles() { 2091a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock for (TileRecord r : mRecords) { 2101a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock r.tile.refreshState(); 2111a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock } 2123d5f551cd5905c835bb789406763764a8a9a73deJason Monk mFooter.refreshState(); 2131a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock } 2141a462c1d2384608e0f546631d431ba39c7e6b27cJohn Spurlock 2151ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos public void showDetailAdapter(boolean show, DetailAdapter adapter) { 2161ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos Record r = new Record(); 2171ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos r.detailAdapter = adapter; 2181ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos showDetail(show, r); 2191ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 2201ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 2211ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private void showDetail(boolean show, Record r) { 222af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mHandler.obtainMessage(H.SHOW_DETAIL, show ? 1 : 0, 0, r).sendToTarget(); 223af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 224af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 225e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek private void setTileVisibility(View v, int visibility) { 226e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek mHandler.obtainMessage(H.SET_TILE_VISIBILITY, visibility, 0, v).sendToTarget(); 227af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 228af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 229e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek private void handleSetTileVisibility(View v, int visibility) { 230e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek if (visibility == v.getVisibility()) return; 231e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek v.setVisibility(visibility); 232af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 233af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 234bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock public void setTiles(Collection<QSTile<?>> tiles) { 235bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock for (TileRecord record : mRecords) { 236bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock removeView(record.tileView); 237bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 238bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mRecords.clear(); 239bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock for (QSTile<?> tile : tiles) { 240bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock addTile(tile); 241bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 242bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock if (isShowingDetail()) { 243bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock mDetail.bringToFront(); 244bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 245bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock } 246bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock 247bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock private void addTile(final QSTile<?> tile) { 248af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final TileRecord r = new TileRecord(); 249af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tile = tile; 250af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tileView = tile.createTileView(mContext); 251af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tileView.setVisibility(View.GONE); 252bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock final QSTile.Callback callback = new QSTile.Callback() { 253af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 254af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void onStateChanged(QSTile.State state) { 255e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek int visibility = state.visible ? VISIBLE : GONE; 256e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek if (state.visible && !mGridContentVisible) { 257e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek 258e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek // We don't want to show it if the content is hidden, 259e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek // then we just set it to invisible, to ensure that it gets visible again 260e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek visibility = INVISIBLE; 261e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 262e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek setTileVisibility(r.tileView, visibility); 263af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tileView.onStateChanged(state); 264af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 265af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 266af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void onShowDetail(boolean show) { 267af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock QSPanel.this.showDetail(show, r); 268af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 2697f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock @Override 2707f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock public void onToggleStateChanged(boolean state) { 2717f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock if (mDetailRecord == r) { 2727f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock fireToggleStateChanged(state); 2737f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock } 2747f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock } 275486b78e42652466f6241eb87d5bed60040db7a25John Spurlock @Override 276486b78e42652466f6241eb87d5bed60040db7a25John Spurlock public void onScanStateChanged(boolean state) { 277465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock r.scanState = state; 278486b78e42652466f6241eb87d5bed60040db7a25John Spurlock if (mDetailRecord == r) { 279465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock fireScanStateChanged(r.scanState); 280486b78e42652466f6241eb87d5bed60040db7a25John Spurlock } 281486b78e42652466f6241eb87d5bed60040db7a25John Spurlock } 2824fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek 2834fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek @Override 2844fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek public void onAnnouncementRequested(CharSequence announcement) { 2854fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek announceForAccessibility(announcement); 2864fda7b2d97c77c64bac0b44dc7a44597ad2c48b0Selim Cinek } 287bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock }; 288bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock r.tile.setCallback(callback); 289af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final View.OnClickListener click = new View.OnClickListener() { 290af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 291af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void onClick(View v) { 292af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tile.click(); 293af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 294af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock }; 295af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final View.OnClickListener clickSecondary = new View.OnClickListener() { 296af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 297af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void onClick(View v) { 298af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock r.tile.secondaryClick(); 299af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 300af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock }; 301c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock final View.OnLongClickListener longClick = new View.OnLongClickListener() { 302c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock @Override 303c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock public boolean onLongClick(View v) { 304c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock r.tile.longClick(); 305c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock return true; 306c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock } 307c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock }; 308c247b8f7270dd70ecc36977fcc0530217879f665John Spurlock r.tileView.init(click, clickSecondary, longClick); 309bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock r.tile.setListening(mListening); 310bceed060f0090a4f86418c4515128d5ec8ebdd4aJohn Spurlock callback.onStateChanged(r.tile.getState()); 311ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock r.tile.refreshState(); 312af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mRecords.add(r); 313af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 314af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock addView(r.tileView); 315af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 316af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 317f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock public boolean isShowingDetail() { 318f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock return mDetailRecord != null; 319f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock } 320f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock 321f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock public void closeDetail() { 322f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock showDetail(false, mDetailRecord); 323f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock } 324f7ae44258fdcb452119936dff449c2d99fd8ece8John Spurlock 3258bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi public boolean isClosingDetail() { 3268bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi return mClosingDetail; 3278bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 3288bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 3298bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi public int getGridHeight() { 3308bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi return mGridHeight; 3318bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi } 3328bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi 3331ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private void handleShowDetail(Record r, boolean show) { 3341ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos if (r instanceof TileRecord) { 3351ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos handleShowDetailTile((TileRecord) r, show); 3361ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } else { 3371ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos handleShowDetailImpl(r, show, getWidth() /* x */, 0/* y */); 3381ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 3391ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 3401ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 3411ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private void handleShowDetailTile(TileRecord r, boolean show) { 3421ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos if ((mDetailRecord != null) == show) return; 3431ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 344af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (show) { 3457f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock r.detailAdapter = r.tile.getDetailAdapter(); 3467f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock if (r.detailAdapter == null) return; 3471ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 3481ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos int x = r.tileView.getLeft() + r.tileView.getWidth() / 2; 3491ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos int y = r.tileView.getTop() + r.tileView.getHeight() / 2; 3501ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos handleShowDetailImpl(r, show, x, y); 3511ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 3521ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 3531ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private void handleShowDetailImpl(Record r, boolean show, int x, int y) { 3541ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos if ((mDetailRecord != null) == show) return; // already in right state 3551ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos DetailAdapter detailAdapter = null; 3561ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos AnimatorListener listener = null; 3571ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos if (show) { 3581ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos detailAdapter = r.detailAdapter; 3591ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos r.detailView = detailAdapter.createDetailView(mContext, r.detailView, mDetailContent); 3607f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock if (r.detailView == null) throw new IllegalStateException("Must return detail view"); 3611ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 3621ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos final Intent settingsIntent = detailAdapter.getSettingsIntent(); 3637f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE); 3647f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailSettingsButton.setOnClickListener(new OnClickListener() { 3657f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock @Override 3667f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock public void onClick(View v) { 3671ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos mHost.startSettingsActivity(settingsIntent); 3687f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock } 3697f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock }); 3701ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 3717f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailContent.removeAllViews(); 372af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mDetail.bringToFront(); 3737f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailContent.addView(r.detailView); 374465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock setDetailRecord(r); 375e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek listener = mHideGridContentWhenDone; 376af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else { 3778bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi mClosingDetail = true; 378e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek setGridContentVisibility(true); 379af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock listener = mTeardownDetailWhenDone; 380465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock fireScanStateChanged(false); 381af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 3826783bef9b9b26df093b07b0044cf079a0b5011cdJason Monk sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 3831ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos fireShowingDetail(show ? detailAdapter : null); 384af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock mClipper.animateCircularClip(x, y, show, listener); 385af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 386af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 387e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek private void setGridContentVisibility(boolean visible) { 388e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek int newVis = visible ? VISIBLE : INVISIBLE; 389e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek for (int i = 0; i < mRecords.size(); i++) { 390e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek TileRecord tileRecord = mRecords.get(i); 391e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek if (tileRecord.tileView.getVisibility() != GONE) { 392e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek tileRecord.tileView.setVisibility(newVis); 393e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 394e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 395e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek mBrightnessView.setVisibility(newVis); 396e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek mGridContentVisible = visible; 397e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 398e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek 399af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 400af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 401af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int width = MeasureSpec.getSize(widthMeasureSpec); 4023f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi mBrightnessView.measure(exactly(width), MeasureSpec.UNSPECIFIED); 403cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos final int brightnessHeight = mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop; 4043d5f551cd5905c835bb789406763764a8a9a73deJason Monk mFooter.getView().measure(exactly(width), MeasureSpec.UNSPECIFIED); 405ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock int r = -1; 406ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock int c = -1; 407af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock int rows = 0; 408ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock boolean rowIsDual = false; 409af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock for (TileRecord record : mRecords) { 410af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (record.tileView.getVisibility() == GONE) continue; 411ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock // wrap to next column if we've reached the max # of columns 412ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock // also don't allow dual + single tiles on the same row 413ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock if (r == -1 || c == (mColumns - 1) || rowIsDual != record.tile.supportsDualTargets()) { 414ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock r++; 415ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock c = 0; 416ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock rowIsDual = record.tile.supportsDualTargets(); 417ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock } else { 418ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock c++; 419ccb6b9a90f228cc4e31a9442ed28756ff474c080John Spurlock } 420af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock record.row = r; 421af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock record.col = c; 422af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock rows = r + 1; 423af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 424af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 425af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock for (TileRecord record : mRecords) { 4268ba572a3277f0c729a7fcce67bbf6e101667d5f9Jason Monk if (record.tileView.setDual(record.tile.supportsDualTargets())) { 4278ba572a3277f0c729a7fcce67bbf6e101667d5f9Jason Monk record.tileView.handleStateChanged(record.tile.getState()); 4288ba572a3277f0c729a7fcce67bbf6e101667d5f9Jason Monk } 429e5557a972ca190cb82026a5dd0c53f4d119fa05aSelim Cinek if (record.tileView.getVisibility() == GONE) continue; 430af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth; 431af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int ch = record.row == 0 ? mLargeCellHeight : mCellHeight; 432af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock record.tileView.measure(exactly(cw), exactly(ch)); 433af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 434cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos int h = rows == 0 ? brightnessHeight : (getRowTop(rows) + mPanelPaddingBottom); 4353d5f551cd5905c835bb789406763764a8a9a73deJason Monk if (mFooter.hasFooter()) { 436cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos h += mFooter.getView().getMeasuredHeight(); 4373d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 4381940892d891c1d2538f51608b6618af646ab7481Adrian Roos mDetail.measure(exactly(width), MeasureSpec.UNSPECIFIED); 4391940892d891c1d2538f51608b6618af646ab7481Adrian Roos if (mDetail.getMeasuredHeight() < h) { 4401940892d891c1d2538f51608b6618af646ab7481Adrian Roos mDetail.measure(exactly(width), exactly(h)); 4411940892d891c1d2538f51608b6618af646ab7481Adrian Roos } 4428bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi mGridHeight = h; 4431940892d891c1d2538f51608b6618af646ab7481Adrian Roos setMeasuredDimension(width, Math.max(h, mDetail.getMeasuredHeight())); 444af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 445af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 446af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private static int exactly(int size) { 447af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 448af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 449af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 450af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 451af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock protected void onLayout(boolean changed, int l, int t, int r, int b) { 4524bf31983d247a76142937c01bc2800b7f98d0281John Spurlock final int w = getWidth(); 453cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos mBrightnessView.layout(0, mBrightnessPaddingTop, 454cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos mBrightnessView.getMeasuredWidth(), 455cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos mBrightnessPaddingTop + mBrightnessView.getMeasuredHeight()); 45606d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; 457af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock for (TileRecord record : mRecords) { 458af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (record.tileView.getVisibility() == GONE) continue; 459af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int cols = getColumnCount(record.row); 460af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int cw = record.row == 0 ? mLargeCellWidth : mCellWidth; 461af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int extra = (w - cw * cols) / (cols + 1); 46206d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek int left = record.col * cw + (record.col + 1) * extra; 463af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock final int top = getRowTop(record.row); 46406d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek int right; 46506d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek int tileWith = record.tileView.getMeasuredWidth(); 46606d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek if (isRtl) { 46706d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek right = w - left; 46806d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek left = right - tileWith; 46906d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek } else { 47006d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek right = left + tileWith; 47106d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek } 47206d3bca095aecbb7542ebf4bdaa56b368261dd9dSelim Cinek record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight()); 473af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 4743e04cc8c9bcb6daa8f5336934a88dc6c4fdd5221John Spurlock final int dh = Math.max(mDetail.getMeasuredHeight(), getMeasuredHeight()); 4753e04cc8c9bcb6daa8f5336934a88dc6c4fdd5221John Spurlock mDetail.layout(0, 0, mDetail.getMeasuredWidth(), dh); 4763d5f551cd5905c835bb789406763764a8a9a73deJason Monk if (mFooter.hasFooter()) { 4773d5f551cd5905c835bb789406763764a8a9a73deJason Monk View footer = mFooter.getView(); 4783d5f551cd5905c835bb789406763764a8a9a73deJason Monk footer.layout(0, getMeasuredHeight() - footer.getMeasuredHeight(), 4793d5f551cd5905c835bb789406763764a8a9a73deJason Monk footer.getMeasuredWidth(), getMeasuredHeight()); 4803d5f551cd5905c835bb789406763764a8a9a73deJason Monk } 481af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 482af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 483af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int getRowTop(int row) { 484cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos if (row <= 0) return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop; 485cd542b8a98ea9c648622c9360c251de4be4223e4Adrian Roos return mBrightnessView.getMeasuredHeight() + mBrightnessPaddingTop 4863f48f46d7e9073edbc4d8613a6dd4d68a37a11b6Jorim Jaggi + mLargeCellHeight - mDualTileUnderlap + (row - 1) * mCellHeight; 487af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 488af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 489af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private int getColumnCount(int row) { 490af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock int cols = 0; 491af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock for (TileRecord record : mRecords) { 492af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (record.tileView.getVisibility() == GONE) continue; 493af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (record.row == row) cols++; 494af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 495af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock return cols; 496af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 497af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 4987f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock private void fireShowingDetail(QSTile.DetailAdapter detail) { 4997f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock if (mCallback != null) { 5007f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mCallback.onShowingDetail(detail); 5017f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock } 5027f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock } 5037f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock 5047f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock private void fireToggleStateChanged(boolean state) { 5055729d090ab44228ff342a10b4ec0552741371501John Spurlock if (mCallback != null) { 5067f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mCallback.onToggleStateChanged(state); 5075729d090ab44228ff342a10b4ec0552741371501John Spurlock } 5085729d090ab44228ff342a10b4ec0552741371501John Spurlock } 5095729d090ab44228ff342a10b4ec0552741371501John Spurlock 510486b78e42652466f6241eb87d5bed60040db7a25John Spurlock private void fireScanStateChanged(boolean state) { 511486b78e42652466f6241eb87d5bed60040db7a25John Spurlock if (mCallback != null) { 512486b78e42652466f6241eb87d5bed60040db7a25John Spurlock mCallback.onScanStateChanged(state); 513486b78e42652466f6241eb87d5bed60040db7a25John Spurlock } 514486b78e42652466f6241eb87d5bed60040db7a25John Spurlock } 515486b78e42652466f6241eb87d5bed60040db7a25John Spurlock 516465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock private void setDetailRecord(Record r) { 517465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock if (r == mDetailRecord) return; 518465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock mDetailRecord = r; 519465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock final boolean scanState = mDetailRecord instanceof TileRecord 520465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock && ((TileRecord) mDetailRecord).scanState; 521465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock fireScanStateChanged(scanState); 522465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock } 523465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock 524af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private class H extends Handler { 525af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private static final int SHOW_DETAIL = 1; 526af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private static final int SET_TILE_VISIBILITY = 2; 527af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock @Override 528af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void handleMessage(Message msg) { 529af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock if (msg.what == SHOW_DETAIL) { 5301ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos handleShowDetail((Record)msg.obj, msg.arg1 != 0); 531af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } else if (msg.what == SET_TILE_VISIBILITY) { 532e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek handleSetTileVisibility((View)msg.obj, msg.arg1); 533af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 534af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 535af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 536af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 5371ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private static class Record { 538856edebad73560e9b1cce021a7de9a0470d07176John Spurlock View detailView; 5397f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock DetailAdapter detailAdapter; 5401ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos } 5411ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos 5421ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos private static final class TileRecord extends Record { 5431ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos QSTile<?> tile; 5441ef80fe5905a19cf92f073163c187a96287335e4Adrian Roos QSTileView tileView; 545af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock int row; 546af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock int col; 547465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock boolean scanState; 548af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock } 549af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock 550af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock private final AnimatorListenerAdapter mTeardownDetailWhenDone = new AnimatorListenerAdapter() { 551af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock public void onAnimationEnd(Animator animation) { 5527f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock mDetailContent.removeAllViews(); 553465cefa1a26b256c9b7073d17a57cf82a17d6b87John Spurlock setDetailRecord(null); 5548bc983efc439c321c8f548d384d807c31daf9180Jorim Jaggi mClosingDetail = false; 555af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock }; 556af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock }; 5575729d090ab44228ff342a10b4ec0552741371501John Spurlock 558e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek private final AnimatorListenerAdapter mHideGridContentWhenDone = new AnimatorListenerAdapter() { 5598a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk public void onAnimationCancel(Animator animation) { 5608a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk // If we have been cancelled, remove the listener so that onAnimationEnd doesn't get 5618a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk // called, this will avoid accidentally turning off the grid when we don't want to. 5628a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk animation.removeListener(this); 5638a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk }; 5648a2d4fc5be174fb200c788659d0a422564ae6f97Jason Monk 565e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek @Override 566e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek public void onAnimationEnd(Animator animation) { 56798fa70c98f61fe1589b81deb260422b92d4c443aJason Monk // Only hide content if still in detail state. 56898fa70c98f61fe1589b81deb260422b92d4c443aJason Monk if (mDetailRecord != null) { 56998fa70c98f61fe1589b81deb260422b92d4c443aJason Monk setGridContentVisibility(false); 57098fa70c98f61fe1589b81deb260422b92d4c443aJason Monk } 571e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek } 572e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek }; 573e32010ac6120278fea41e49b9832af79b1b5463eSelim Cinek 5745729d090ab44228ff342a10b4ec0552741371501John Spurlock public interface Callback { 5757f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock void onShowingDetail(QSTile.DetailAdapter detail); 5767f8f22a53005f776c8ee4d299e748e74b077ffd9John Spurlock void onToggleStateChanged(boolean state); 577486b78e42652466f6241eb87d5bed60040db7a25John Spurlock void onScanStateChanged(boolean state); 5785729d090ab44228ff342a10b4ec0552741371501John Spurlock } 579af8d6c44f06d2f8baac2c5774a9efdae3fc36797John Spurlock} 580