16b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor/* 26b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * Copyright 2017 The Android Open Source Project 36b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * 46b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * Licensed under the Apache License, Version 2.0 (the "License"); 56b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * you may not use this file except in compliance with the License. 66b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * You may obtain a copy of the License at 76b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * 86b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * http://www.apache.org/licenses/LICENSE-2.0 96b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * 106b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * Unless required by applicable law or agreed to in writing, software 116b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * distributed under the License is distributed on an "AS IS" BASIS, 126b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * See the License for the specific language governing permissions and 146b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * limitations under the License. 156b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 166b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 1785ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikaspackage androidx.slice.widget; 186b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 19378ff19cef9998493bc715c58d923150cfd3d816Mady Mellorimport static android.app.slice.Slice.HINT_HORIZONTAL; 20891ce204e1ecd60342507c7bd0c1160bac93be01Mady Mellorimport static android.app.slice.Slice.HINT_PARTIAL; 2153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellorimport static android.app.slice.Slice.HINT_SEE_MORE; 22af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellorimport static android.app.slice.Slice.HINT_SHORTCUT; 23968346929453133f937381a2e685bc4e47788e2cMady Mellorimport static android.app.slice.Slice.HINT_SUMMARY; 246b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.Slice.HINT_TITLE; 254c4a519b7320e1736f55dcd20351d10f692d492cMady Mellorimport static android.app.slice.Slice.SUBTYPE_CONTENT_DESCRIPTION; 263bc2c820c8cbab1cf67dbd836697f780265f0e7aMady Mellorimport static android.app.slice.Slice.SUBTYPE_RANGE; 276b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_ACTION; 286b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_IMAGE; 29f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikhimport static android.app.slice.SliceItem.FORMAT_INT; 309e9f857ec07b05e1a6885c9fc6a2bf25b813259bJason Monkimport static android.app.slice.SliceItem.FORMAT_LONG; 316b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_REMOTE_INPUT; 326b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_SLICE; 336b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_TEXT; 3437bd0717b1f1f8851125d60f87b242a57899298cMady Mellor 350707dbe9fa3225cc921a2305a611272f0dee1ca8Mady Mellorimport static androidx.slice.core.SliceHints.HINT_KEYWORDS; 3663fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport static androidx.slice.core.SliceHints.HINT_LAST_UPDATED; 3763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport static androidx.slice.core.SliceHints.HINT_TTL; 386b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 398a2763f580c71e17a0b13e682c73012e902b4232Mady Mellorimport android.content.Context; 408a2763f580c71e17a0b13e682c73012e902b4232Mady Mellorimport android.text.TextUtils; 416b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport android.util.Log; 426b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 434c4a519b7320e1736f55dcd20351d10f692d492cMady Mellorimport androidx.annotation.NonNull; 444c4a519b7320e1736f55dcd20351d10f692d492cMady Mellorimport androidx.annotation.Nullable; 454c4a519b7320e1736f55dcd20351d10f692d492cMady Mellorimport androidx.annotation.RestrictTo; 4685ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.SliceItem; 47ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellorimport androidx.slice.core.SliceAction; 48ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellorimport androidx.slice.core.SliceActionImpl; 4985ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.core.SliceQuery; 5085ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.view.R; 516b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 52d0babfc47d7a429b80c1f7a3998d57c0aa15dd83Jason Monkimport java.util.ArrayList; 53d0babfc47d7a429b80c1f7a3998d57c0aa15dd83Jason Monkimport java.util.List; 54d0babfc47d7a429b80c1f7a3998d57c0aa15dd83Jason Monk 556b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor/** 566b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * Extracts information required to present content in a row format from a slice. 576b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @hide 586b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 596b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 606b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorpublic class RowContent { 616b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private static final String TAG = "RowContent"; 626b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 63af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor private SliceItem mPrimaryAction; 6453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor private SliceItem mRowSlice; 656b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private SliceItem mStartItem; 666b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private SliceItem mTitleItem; 676b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private SliceItem mSubtitleItem; 68968346929453133f937381a2e685bc4e47788e2cMady Mellor private SliceItem mSummaryItem; 696b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private ArrayList<SliceItem> mEndItems = new ArrayList<>(); 70ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor private ArrayList<SliceAction> mToggleItems = new ArrayList<>(); 71853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh private SliceItem mRange; 724c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor private SliceItem mContentDescr; 734c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor private boolean mEndItemsContainAction; 74968346929453133f937381a2e685bc4e47788e2cMady Mellor private boolean mIsHeader; 758a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private int mLineCount = 0; 768a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private int mMaxHeight; 778a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private int mMinHeight; 788dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor private int mRangeHeight; 796b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 808a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor public RowContent(Context context, SliceItem rowSlice, boolean isHeader) { 81968346929453133f937381a2e685bc4e47788e2cMady Mellor populate(rowSlice, isHeader); 828a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor mMaxHeight = context.getResources().getDimensionPixelSize(R.dimen.abc_slice_row_max_height); 838a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor mMinHeight = context.getResources().getDimensionPixelSize(R.dimen.abc_slice_row_min_height); 848dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor mRangeHeight = context.getResources().getDimensionPixelSize( 858dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor R.dimen.abc_slice_row_range_height); 866b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 876b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 886b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 896b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @return whether this row has content that is valid to display. 906b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 918a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private boolean populate(SliceItem rowSlice, boolean isHeader) { 92968346929453133f937381a2e685bc4e47788e2cMady Mellor mIsHeader = isHeader; 9353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor mRowSlice = rowSlice; 946b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if (!isValidRow(rowSlice)) { 956b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor Log.w(TAG, "Provided SliceItem is invalid for RowContent"); 966b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return false; 976b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 98977517c547084945539210fd3bf075bb81077105Mady Mellor determineStartAndPrimaryAction(rowSlice); 99d0babfc47d7a429b80c1f7a3998d57c0aa15dd83Jason Monk 1004c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor mContentDescr = SliceQuery.findSubtype(rowSlice, FORMAT_TEXT, SUBTYPE_CONTENT_DESCRIPTION); 1014c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor 1026b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor // Filter anything not viable for displaying in a row 103f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh ArrayList<SliceItem> rowItems = filterInvalidItems(rowSlice); 1046b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor // If we've only got one item that's a slice / action use those items instead 1056b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if (rowItems.size() == 1 && (FORMAT_ACTION.equals(rowItems.get(0).getFormat()) 106af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor || FORMAT_SLICE.equals(rowItems.get(0).getFormat())) 107977517c547084945539210fd3bf075bb81077105Mady Mellor && !rowItems.get(0).hasAnyHints(HINT_SHORTCUT, HINT_TITLE)) { 1086b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if (isValidRow(rowItems.get(0))) { 1096b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor rowSlice = rowItems.get(0); 110f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh rowItems = filterInvalidItems(rowSlice); 1116b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1126b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 113853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh if (SUBTYPE_RANGE.equals(rowSlice.getSubType())) { 114853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh mRange = rowSlice; 115f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh } 1166b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if (rowItems.size() > 0) { 117977517c547084945539210fd3bf075bb81077105Mady Mellor // Remove the things we already know about 118977517c547084945539210fd3bf075bb81077105Mady Mellor if (mStartItem != null) { 119977517c547084945539210fd3bf075bb81077105Mady Mellor rowItems.remove(mStartItem); 120977517c547084945539210fd3bf075bb81077105Mady Mellor } 121977517c547084945539210fd3bf075bb81077105Mady Mellor if (mPrimaryAction != null) { 122977517c547084945539210fd3bf075bb81077105Mady Mellor rowItems.remove(mPrimaryAction); 1236b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 124af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor 1256b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor // Text + end items 126238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor ArrayList<SliceItem> endItems = new ArrayList<>(); 1276b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor for (int i = 0; i < rowItems.size(); i++) { 1286b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor final SliceItem item = rowItems.get(i); 1296b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if (FORMAT_TEXT.equals(item.getFormat())) { 1306b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor if ((mTitleItem == null || !mTitleItem.hasHint(HINT_TITLE)) 131968346929453133f937381a2e685bc4e47788e2cMady Mellor && item.hasHint(HINT_TITLE) && !item.hasHint(HINT_SUMMARY)) { 1326b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor mTitleItem = item; 133968346929453133f937381a2e685bc4e47788e2cMady Mellor } else if (mSubtitleItem == null && !item.hasHint(HINT_SUMMARY)) { 1346b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor mSubtitleItem = item; 135968346929453133f937381a2e685bc4e47788e2cMady Mellor } else if (mSummaryItem == null && item.hasHint(HINT_SUMMARY)) { 136968346929453133f937381a2e685bc4e47788e2cMady Mellor mSummaryItem = item; 1376b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1386b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } else { 139238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor endItems.add(item); 140238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor } 141238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor } 1428a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor if (hasText(mTitleItem)) { 1438a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor mLineCount++; 1448a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 1458a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor if (hasText(mSubtitleItem)) { 1468a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor mLineCount++; 1478a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 14807a4a56611cc044fd48b052db05aea332201216eJason Monk // Special rules for end items: only one timestamp 149238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor boolean hasTimestamp = mStartItem != null 1509e9f857ec07b05e1a6885c9fc6a2bf25b813259bJason Monk && FORMAT_LONG.equals(mStartItem.getFormat()); 151238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor for (int i = 0; i < endItems.size(); i++) { 152238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor final SliceItem item = endItems.get(i); 15307a4a56611cc044fd48b052db05aea332201216eJason Monk boolean isAction = SliceQuery.find(item, FORMAT_ACTION) != null; 1549e9f857ec07b05e1a6885c9fc6a2bf25b813259bJason Monk if (FORMAT_LONG.equals(item.getFormat())) { 155238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor if (!hasTimestamp) { 156238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor hasTimestamp = true; 157238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor mEndItems.add(item); 158238b9b6aad4ef0c63acbecfa89605a3d753931feMady Mellor } 15907a4a56611cc044fd48b052db05aea332201216eJason Monk } else { 160ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor processContent(item, isAction); 1616b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1626b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1636b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1646b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return isValid(); 1656b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1666b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 167ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor private void processContent(@NonNull SliceItem item, boolean isAction) { 168ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (isAction) { 169ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor SliceAction ac = new SliceActionImpl(item); 170ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (ac.isToggle()) { 171ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor mToggleItems.add(ac); 172ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 173ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 174ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor mEndItems.add(item); 175ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor mEndItemsContainAction |= isAction; 176ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 177ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor 1786b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 179977517c547084945539210fd3bf075bb81077105Mady Mellor * Sets the {@link #getPrimaryAction()} and {@link #getStartItem()} for this row. 180977517c547084945539210fd3bf075bb81077105Mady Mellor */ 181977517c547084945539210fd3bf075bb81077105Mady Mellor private void determineStartAndPrimaryAction(@NonNull SliceItem rowSlice) { 182977517c547084945539210fd3bf075bb81077105Mady Mellor List<SliceItem> possibleStartItems = SliceQuery.findAll(rowSlice, null, HINT_TITLE, null); 183977517c547084945539210fd3bf075bb81077105Mady Mellor if (possibleStartItems.size() > 0) { 184977517c547084945539210fd3bf075bb81077105Mady Mellor // The start item will be at position 0 if it exists 185977517c547084945539210fd3bf075bb81077105Mady Mellor String format = possibleStartItems.get(0).getFormat(); 186977517c547084945539210fd3bf075bb81077105Mady Mellor if ((FORMAT_ACTION.equals(format) 187977517c547084945539210fd3bf075bb81077105Mady Mellor && SliceQuery.find(possibleStartItems.get(0), FORMAT_IMAGE) != null) 188977517c547084945539210fd3bf075bb81077105Mady Mellor || FORMAT_SLICE.equals(format) 1894e324256a5aadb8e1001b0ee7ead3cda48bfec7fAlan Viverette || FORMAT_LONG.equals(format) 190977517c547084945539210fd3bf075bb81077105Mady Mellor || FORMAT_IMAGE.equals(format)) { 191977517c547084945539210fd3bf075bb81077105Mady Mellor mStartItem = possibleStartItems.get(0); 192977517c547084945539210fd3bf075bb81077105Mady Mellor } 193977517c547084945539210fd3bf075bb81077105Mady Mellor } 194977517c547084945539210fd3bf075bb81077105Mady Mellor 195977517c547084945539210fd3bf075bb81077105Mady Mellor String[] hints = new String[] {HINT_SHORTCUT, HINT_TITLE}; 196977517c547084945539210fd3bf075bb81077105Mady Mellor List<SliceItem> possiblePrimaries = SliceQuery.findAll(rowSlice, FORMAT_SLICE, hints, null); 197977517c547084945539210fd3bf075bb81077105Mady Mellor if (possiblePrimaries.isEmpty() && FORMAT_ACTION.equals(rowSlice.getFormat()) 198977517c547084945539210fd3bf075bb81077105Mady Mellor && rowSlice.getSlice().getItems().size() == 1) { 199977517c547084945539210fd3bf075bb81077105Mady Mellor mPrimaryAction = rowSlice; 200977517c547084945539210fd3bf075bb81077105Mady Mellor } else if (mStartItem != null && possiblePrimaries.size() > 1 201977517c547084945539210fd3bf075bb81077105Mady Mellor && possiblePrimaries.get(0) == mStartItem) { 202977517c547084945539210fd3bf075bb81077105Mady Mellor // Next item is the primary action 203977517c547084945539210fd3bf075bb81077105Mady Mellor mPrimaryAction = possiblePrimaries.get(1); 204977517c547084945539210fd3bf075bb81077105Mady Mellor } else if (possiblePrimaries.size() > 0) { 205977517c547084945539210fd3bf075bb81077105Mady Mellor mPrimaryAction = possiblePrimaries.get(0); 206977517c547084945539210fd3bf075bb81077105Mady Mellor } 207977517c547084945539210fd3bf075bb81077105Mady Mellor } 208977517c547084945539210fd3bf075bb81077105Mady Mellor 209977517c547084945539210fd3bf075bb81077105Mady Mellor /** 21053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the {@link SliceItem} used to populate this row. 21153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 21253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor @NonNull 21353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public SliceItem getSlice() { 21453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return mRowSlice; 21553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 21653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 21753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 218853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh * @return the {@link SliceItem} representing the range in the row; can be null. 219f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh */ 220f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh @Nullable 221853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh public SliceItem getRange() { 222853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh return mRange; 223f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh } 224f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh 225f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh /** 226c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor * @return the {@link SliceItem} for the icon to use for the input range thumb drawable. 227c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor */ 228c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor @Nullable 229c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor public SliceItem getInputRangeThumb() { 230c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor if (mRange != null) { 231c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor List<SliceItem> items = mRange.getSlice().getItems(); 232c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor for (int i = 0; i < items.size(); i++) { 233c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor if (FORMAT_IMAGE.equals(items.get(i).getFormat())) { 234c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor return items.get(i); 235c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor } 236c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor } 237c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor } 238c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor return null; 239c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor } 240c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor 241c1a0996f6ada4bcac69f7aa07048fdd2c9bba4d7Mady Mellor /** 24253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the {@link SliceItem} used for the main intent for this row; can be null. 2436b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 2446b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 245af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor public SliceItem getPrimaryAction() { 246af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor return mPrimaryAction; 2476b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2486b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 24953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 25053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the {@link SliceItem} to display at the start of this row; can be null. 25153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 2526b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 2536b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public SliceItem getStartItem() { 254968346929453133f937381a2e685bc4e47788e2cMady Mellor return mIsHeader ? null : mStartItem; 2556b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2566b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 25753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 25853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the {@link SliceItem} representing the title text for this row; can be null. 25953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 2606b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 2616b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public SliceItem getTitleItem() { 2626b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return mTitleItem; 2636b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2646b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 26553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 26653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the {@link SliceItem} representing the subtitle text for this row; can be null. 26753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 2686b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 2696b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public SliceItem getSubtitleItem() { 2706b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return mSubtitleItem; 2716b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2726b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 273968346929453133f937381a2e685bc4e47788e2cMady Mellor @Nullable 274968346929453133f937381a2e685bc4e47788e2cMady Mellor public SliceItem getSummaryItem() { 275968346929453133f937381a2e685bc4e47788e2cMady Mellor return mSummaryItem == null ? mSubtitleItem : mSummaryItem; 276968346929453133f937381a2e685bc4e47788e2cMady Mellor } 277968346929453133f937381a2e685bc4e47788e2cMady Mellor 27853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 27953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the list of {@link SliceItem} that can be shown as items at the end of the row. 28053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 2816b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public ArrayList<SliceItem> getEndItems() { 2826b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return mEndItems; 2836b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2846b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 2856b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 286ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor * @return a list of toggles associated with this row. 287ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor */ 288ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor public ArrayList<SliceAction> getToggleItems() { 289ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return mToggleItems; 290ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 291ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor 292ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor /** 2934c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor * @return the content description to use for this row. 2944c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor */ 2954c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor @Nullable 2964c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor public CharSequence getContentDescription() { 2974c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor return mContentDescr != null ? mContentDescr.getText() : null; 2984c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor } 2994c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor 3004c4a519b7320e1736f55dcd20351d10f692d492cMady Mellor /** 301af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellor * @return whether {@link #getEndItems()} contains a SliceItem with FORMAT_SLICE, HINT_SHORTCUT 302bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh */ 303bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh public boolean endItemsContainAction() { 304bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh return mEndItemsContainAction; 305bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh } 306bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh 307bfeddbaf2e0d5707b101a91fa1287c93757ff4a9Amin Shaikh /** 3088a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor * @return the number of lines of text contained in this row. 3098a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor */ 3108a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor public int getLineCount() { 3118a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor return mLineCount; 3128a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 3138a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor 3148a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor /** 3158a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor * @return the height to display a row at when it is used as a small template. 3168a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor */ 3178a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor public int getSmallHeight() { 3188dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor return getRange() != null 3198dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor ? getActualHeight() 320ec2359f11170a2742cd1650900de320aa22eab58Mady Mellor : mMaxHeight; 3218a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 3228a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor 3238a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor /** 3248a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor * @return the height the content in this template requires to be displayed. 3258a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor */ 3268a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor public int getActualHeight() { 327ec2359f11170a2742cd1650900de320aa22eab58Mady Mellor if (!isValid()) { 328ec2359f11170a2742cd1650900de320aa22eab58Mady Mellor return 0; 329ec2359f11170a2742cd1650900de320aa22eab58Mady Mellor } 3308dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor int rowHeight = (getLineCount() > 1 || mIsHeader) ? mMaxHeight : mMinHeight; 3318dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor if (getRange() != null) { 3328dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor if (getLineCount() > 0) { 3338dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor rowHeight += mRangeHeight; 3348dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor } else { 3358dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor rowHeight = mIsHeader ? mMaxHeight : mRangeHeight; 3368dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor } 337ec2359f11170a2742cd1650900de320aa22eab58Mady Mellor } 3388dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor return rowHeight; 3398a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 3408a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor 3418a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private static boolean hasText(SliceItem textSlice) { 342891ce204e1ecd60342507c7bd0c1160bac93be01Mady Mellor return textSlice != null 343891ce204e1ecd60342507c7bd0c1160bac93be01Mady Mellor && (textSlice.hasHint(HINT_PARTIAL) 344891ce204e1ecd60342507c7bd0c1160bac93be01Mady Mellor || !TextUtils.isEmpty(textSlice.getText())); 3458a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 3468a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor 3478a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor /** 34853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return whether this row content represents a default see more item. 34953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 35053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public boolean isDefaultSeeMore() { 35153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return FORMAT_ACTION.equals(mRowSlice.getFormat()) 35253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor && mRowSlice.getSlice().hasHint(HINT_SEE_MORE) 35353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor && mRowSlice.getSlice().getItems().isEmpty(); 35453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 35553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 35653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 35753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return whether this row has content that is valid to display. 35853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 35953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public boolean isValid() { 36053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return mStartItem != null 361977517c547084945539210fd3bf075bb81077105Mady Mellor || mPrimaryAction != null 36253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor || mTitleItem != null 36353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor || mSubtitleItem != null 36453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor || mEndItems.size() > 0 3658dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor || mRange != null 36653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor || isDefaultSeeMore(); 36753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 36853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 36953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 3706b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @return whether this is a valid item to use to populate a row of content. 3716b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 372f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh private static boolean isValidRow(SliceItem rowSlice) { 373968346929453133f937381a2e685bc4e47788e2cMady Mellor if (rowSlice == null) { 374968346929453133f937381a2e685bc4e47788e2cMady Mellor return false; 375968346929453133f937381a2e685bc4e47788e2cMady Mellor } 3766b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor // Must be slice or action 377f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh if (FORMAT_SLICE.equals(rowSlice.getFormat()) 378f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh || FORMAT_ACTION.equals(rowSlice.getFormat())) { 379f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh List<SliceItem> rowItems = rowSlice.getSlice().getItems(); 380977517c547084945539210fd3bf075bb81077105Mady Mellor // Special case: default see more just has an action but no other items 381977517c547084945539210fd3bf075bb81077105Mady Mellor if (rowSlice.hasHint(HINT_SEE_MORE) && rowItems.isEmpty()) { 382977517c547084945539210fd3bf075bb81077105Mady Mellor return true; 383977517c547084945539210fd3bf075bb81077105Mady Mellor } 384977517c547084945539210fd3bf075bb81077105Mady Mellor // Must have at least one legitimate child 3856b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor for (int i = 0; i < rowItems.size(); i++) { 386f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh if (isValidRowContent(rowSlice, rowItems.get(i))) { 3876b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return true; 3886b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 3896b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 3906b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 3916b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return false; 3926b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 3936b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 39453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 39553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return list of {@link SliceItem}s that are valid to display in a row according 39653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * to {@link #isValidRowContent(SliceItem, SliceItem)}. 39753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 398f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh private static ArrayList<SliceItem> filterInvalidItems(SliceItem rowSlice) { 3996b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor ArrayList<SliceItem> filteredList = new ArrayList<>(); 400f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh for (SliceItem i : rowSlice.getSlice().getItems()) { 401f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh if (isValidRowContent(rowSlice, i)) { 4026b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor filteredList.add(i); 4036b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 4046b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 4056b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return filteredList; 4066b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 4076b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 4086b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 409977517c547084945539210fd3bf075bb81077105Mady Mellor * @return whether this item is valid content to visibly appear in a row. 4106b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 411f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh private static boolean isValidRowContent(SliceItem slice, SliceItem item) { 412378ff19cef9998493bc715c58d923150cfd3d816Mady Mellor if (item.hasAnyHints(HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED, HINT_HORIZONTAL) 413977517c547084945539210fd3bf075bb81077105Mady Mellor || SUBTYPE_CONTENT_DESCRIPTION.equals(item.getSubType())) { 414bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellor return false; 415bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellor } 4166b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor final String itemFormat = item.getFormat(); 417977517c547084945539210fd3bf075bb81077105Mady Mellor return FORMAT_IMAGE.equals(itemFormat) 418977517c547084945539210fd3bf075bb81077105Mady Mellor || FORMAT_TEXT.equals(itemFormat) 4199e9f857ec07b05e1a6885c9fc6a2bf25b813259bJason Monk || FORMAT_LONG.equals(itemFormat) 420f2cdc3aa79e0798d6987985ab94395914b83b7e4Amin Shaikh || FORMAT_ACTION.equals(itemFormat) 421977517c547084945539210fd3bf075bb81077105Mady Mellor || FORMAT_REMOTE_INPUT.equals(itemFormat) 422977517c547084945539210fd3bf075bb81077105Mady Mellor || FORMAT_SLICE.equals(itemFormat) 423853c11f11cd3d1378eac2c37d1e8c258420644a8Amin Shaikh || (FORMAT_INT.equals(itemFormat) && SUBTYPE_RANGE.equals(slice.getSubType())); 4246b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 4256b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor} 426