ListContent.java revision 92952f5bbd2b743091af437767b0b48e48d292b5
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 196b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.Slice.HINT_ACTIONS; 208a2763f580c71e17a0b13e682c73012e902b4232Mady Mellorimport static android.app.slice.Slice.HINT_HORIZONTAL; 216b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.Slice.HINT_LIST_ITEM; 2253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellorimport static android.app.slice.Slice.HINT_SEE_MORE; 23af76b3bd62a6b218bb44917b1dddfa1ee4803149Mady Mellorimport static android.app.slice.Slice.HINT_SHORTCUT; 246b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.Slice.SUBTYPE_COLOR; 256b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_ACTION; 266b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_INT; 276b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorimport static android.app.slice.SliceItem.FORMAT_SLICE; 28968346929453133f937381a2e685bc4e47788e2cMady Mellorimport static android.app.slice.SliceItem.FORMAT_TEXT; 296b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 300707dbe9fa3225cc921a2305a611272f0dee1ca8Mady Mellorimport static androidx.slice.core.SliceHints.HINT_KEYWORDS; 3163fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport static androidx.slice.core.SliceHints.HINT_LAST_UPDATED; 3263fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellorimport static androidx.slice.core.SliceHints.HINT_TTL; 33bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellor 348a2763f580c71e17a0b13e682c73012e902b4232Mady Mellorimport android.content.Context; 356b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 36bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellorimport androidx.annotation.NonNull; 37bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellorimport androidx.annotation.Nullable; 38bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellorimport androidx.annotation.RestrictTo; 3985ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.Slice; 4085ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.SliceItem; 41e7f1c6cf75ce36c633075445bd676572a9fe0f47Mady Mellorimport androidx.slice.SliceMetadata; 42ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellorimport androidx.slice.core.SliceAction; 43ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellorimport androidx.slice.core.SliceActionImpl; 4485ef1446b82c8783a50af92c4cb1389fe0d0e907Aurimas Liutikasimport androidx.slice.core.SliceQuery; 456b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 46c50cc30733ad1058f98523c25f7413745638332aMady Mellorimport java.util.ArrayList; 47c50cc30733ad1058f98523c25f7413745638332aMady Mellorimport java.util.List; 48c50cc30733ad1058f98523c25f7413745638332aMady Mellor 496b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor/** 506b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * Extracts information required to present content in a list format from a slice. 516b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @hide 526b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 536b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 546b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellorpublic class ListContent { 556b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 56968346929453133f937381a2e685bc4e47788e2cMady Mellor private SliceItem mHeaderItem; 576b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private SliceItem mColorItem; 5853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor private SliceItem mSeeMoreItem; 596b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor private ArrayList<SliceItem> mRowItems = new ArrayList<>(); 60968346929453133f937381a2e685bc4e47788e2cMady Mellor private List<SliceItem> mSliceActions; 618a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private Context mContext; 626b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 638a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor public ListContent(Context context, Slice slice) { 648a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor mContext = context; 656b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor populate(slice); 666b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 676b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 686b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 696b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @return whether this row has content that is valid to display. 706b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 718a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor private boolean populate(Slice slice) { 726b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor mColorItem = SliceQuery.findSubtype(slice, FORMAT_INT, SUBTYPE_COLOR); 73968346929453133f937381a2e685bc4e47788e2cMady Mellor // Find slice actions 74e7f1c6cf75ce36c633075445bd676572a9fe0f47Mady Mellor mSliceActions = SliceMetadata.getSliceActions(slice); 75968346929453133f937381a2e685bc4e47788e2cMady Mellor // Find header 76968346929453133f937381a2e685bc4e47788e2cMady Mellor mHeaderItem = findHeaderItem(slice); 77968346929453133f937381a2e685bc4e47788e2cMady Mellor if (mHeaderItem != null) { 78968346929453133f937381a2e685bc4e47788e2cMady Mellor mRowItems.add(mHeaderItem); 79968346929453133f937381a2e685bc4e47788e2cMady Mellor } 8053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor mSeeMoreItem = getSeeMoreItem(slice); 816b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor // Filter + create row items 826b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor List<SliceItem> children = slice.getItems(); 836b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor for (int i = 0; i < children.size(); i++) { 846b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor final SliceItem child = children.get(i); 856b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor final String format = child.getFormat(); 860707dbe9fa3225cc921a2305a611272f0dee1ca8Mady Mellor boolean isNonRowContent = child.hasAnyHints(HINT_ACTIONS, HINT_SEE_MORE, HINT_KEYWORDS, 8763fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor HINT_TTL, HINT_LAST_UPDATED); 8863fb9955b209f1bb9d19e41df9784bfbdf63defeMady Mellor if (!isNonRowContent && (FORMAT_ACTION.equals(format) || FORMAT_SLICE.equals(format))) { 89968346929453133f937381a2e685bc4e47788e2cMady Mellor if (mHeaderItem == null && !child.hasHint(HINT_LIST_ITEM)) { 90968346929453133f937381a2e685bc4e47788e2cMady Mellor mHeaderItem = child; 916b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor mRowItems.add(0, child); 92968346929453133f937381a2e685bc4e47788e2cMady Mellor } else if (child.hasHint(HINT_LIST_ITEM)) { 936b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor mRowItems.add(child); 946b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 956b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 966b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 97968346929453133f937381a2e685bc4e47788e2cMady Mellor // Ensure we have something for the header -- use first row 98968346929453133f937381a2e685bc4e47788e2cMady Mellor if (mHeaderItem == null && mRowItems.size() >= 1) { 99968346929453133f937381a2e685bc4e47788e2cMady Mellor mHeaderItem = mRowItems.get(0); 100968346929453133f937381a2e685bc4e47788e2cMady Mellor } 1016b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return isValid(); 1026b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1036b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 1046b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 1058dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor * Expects the provided list of items to be filtered (i.e. only things that can be turned into 1068dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor * GridContent or RowContent) and in order (i.e. first item could be a header). 1078dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor * 10853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the total height of all the rows contained in the provided list. 1098a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor */ 11053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public static int getListHeight(Context context, List<SliceItem> listItems) { 1118a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor int height = 0; 1128dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor boolean hasRealHeader = false; 1138dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor if (listItems.size() > 0) { 1148dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor SliceItem maybeHeader = listItems.get(0); 1158dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor hasRealHeader = !maybeHeader.hasAnyHints(HINT_LIST_ITEM, HINT_HORIZONTAL); 1168dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor } 11753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor for (int i = 0; i < listItems.size(); i++) { 1188dc56e6039af468e05c213ef6562c9c6624aaf8aMady Mellor height += getHeight(context, listItems.get(i), i == 0 && hasRealHeader /* isHeader */); 11953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 12053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return height; 12153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 12253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 12353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor /** 12453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * Returns a list of items that can be displayed in the provided height. If this list 12553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * has a {@link #getSeeMoreItem()} this will be returned in the list if appropriate. 12653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * 12753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @param height the height to restrict the items, -1 to use default sizings for non-scrolling 12853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * templates. 12953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor * @return the list of items that can be displayed in the provided height. 13053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor */ 13153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor @NonNull 13253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public List<SliceItem> getItemsForNonScrollingList(int height) { 13353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor ArrayList<SliceItem> visibleItems = new ArrayList<>(); 13453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (mRowItems == null || mRowItems.size() == 0) { 13553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return visibleItems; 13653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 13753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor final int idealItemCount = hasHeader() ? 4 : 3; 13853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor final int minItemCount = hasHeader() ? 2 : 1; 13953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor int visibleHeight = 0; 14053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor // Need to show see more 14153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (mSeeMoreItem != null) { 14253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor RowContent rc = new RowContent(mContext, mSeeMoreItem, false /* isHeader */); 14353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor visibleHeight += rc.getActualHeight(); 14453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 1458a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor for (int i = 0; i < mRowItems.size(); i++) { 14653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor int itemHeight = getHeight(mContext, mRowItems.get(i), i == 0 /* isHeader */); 14753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if ((height == -1 && i > idealItemCount) 14853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor || (height > 0 && visibleHeight + itemHeight > height)) { 14953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor break; 1508a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } else { 15153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor visibleHeight += itemHeight; 15253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor visibleItems.add(mRowItems.get(i)); 1538a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 1548a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 15553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (mSeeMoreItem != null && visibleItems.size() >= minItemCount) { 15653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor // Only add see more if we're at least showing one item and it's not the header 15753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor visibleItems.add(mSeeMoreItem); 15853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 15953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (visibleItems.size() == 0) { 16053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor // Didn't have enough space to show anything; should still show something 16153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor visibleItems.add(mRowItems.get(0)); 16253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 16353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return visibleItems; 16453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 16553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 16653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor private static int getHeight(Context context, SliceItem item, boolean isHeader) { 16753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (item.hasHint(HINT_HORIZONTAL)) { 16853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor GridContent gc = new GridContent(context, item); 16953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return gc.getActualHeight(); 17053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } else { 17153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor RowContent rc = new RowContent(context, item, isHeader); 17253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return rc.getActualHeight(); 17353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 1748a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor } 1758a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor 1768a2763f580c71e17a0b13e682c73012e902b4232Mady Mellor /** 1776b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor * @return whether this list has content that is valid to display. 1786b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 1796b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public boolean isValid() { 180968346929453133f937381a2e685bc4e47788e2cMady Mellor return mRowItems.size() > 0; 1816b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1826b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 1836b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 1846b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public SliceItem getColorItem() { 1856b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return mColorItem; 1866b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1876b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 1886b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor @Nullable 189968346929453133f937381a2e685bc4e47788e2cMady Mellor public SliceItem getHeaderItem() { 190968346929453133f937381a2e685bc4e47788e2cMady Mellor return mHeaderItem; 191968346929453133f937381a2e685bc4e47788e2cMady Mellor } 192968346929453133f937381a2e685bc4e47788e2cMady Mellor 193968346929453133f937381a2e685bc4e47788e2cMady Mellor @Nullable 194968346929453133f937381a2e685bc4e47788e2cMady Mellor public List<SliceItem> getSliceActions() { 195968346929453133f937381a2e685bc4e47788e2cMady Mellor return mSliceActions; 1966b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 1976b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 19853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor @Nullable 19953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor public SliceItem getSeeMoreItem() { 20053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return mSeeMoreItem; 20153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 20253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 2036b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public ArrayList<SliceItem> getRowItems() { 2046b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor return mRowItems; 2056b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2066b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 2076b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor /** 208968346929453133f937381a2e685bc4e47788e2cMady Mellor * @return whether this list has an explicit header (i.e. row item without HINT_LIST_ITEM) 2096b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor */ 2106b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor public boolean hasHeader() { 211968346929453133f937381a2e685bc4e47788e2cMady Mellor return mHeaderItem != null && isValidHeader(mHeaderItem); 2126b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2136b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 214c50cc30733ad1058f98523c25f7413745638332aMady Mellor /** 215ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor * @return the type of template that the header represents. 216ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor */ 217ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor public int getHeaderTemplateType() { 2186975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor return getRowType(mContext, mHeaderItem, true, mSliceActions); 2196975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } 2206975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor 2216975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor /** 2226975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * The type of template that the provided row item represents. 2236975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * 2246975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * @param context context used for this slice. 2256975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * @param rowItem the row item to determine the template type of. 2266975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * @param isHeader whether this row item is used as a header. 2276975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * @param actions the actions associated with this slice, only matter if this row is the header. 2286975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor * @return the type of template the provided row item represents. 2296975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor */ 2306975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor public static int getRowType(Context context, SliceItem rowItem, boolean isHeader, 2316975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor List<SliceItem> actions) { 2326975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (rowItem != null) { 2336975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (rowItem.hasHint(HINT_HORIZONTAL)) { 234ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return EventInfo.ROW_TYPE_GRID; 235ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } else { 2366975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor RowContent rc = new RowContent(context, rowItem, isHeader); 237ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor SliceItem actionItem = rc.getPrimaryAction(); 238ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor SliceAction primaryAction = null; 239ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (actionItem != null) { 240ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor primaryAction = new SliceActionImpl(actionItem); 241ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 242ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (rc.getRange() != null) { 243ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return FORMAT_ACTION.equals(rc.getRange().getFormat()) 244ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor ? EventInfo.ROW_TYPE_SLIDER 245ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor : EventInfo.ROW_TYPE_PROGRESS; 246ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } else if (primaryAction != null && primaryAction.isToggle()) { 247ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return EventInfo.ROW_TYPE_TOGGLE; 2486975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor } else if (isHeader && actions != null) { 2496975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor for (int i = 0; i < actions.size(); i++) { 2506975e4e9eba6772c9d7d38374109a90dd4f390cdMady Mellor if (new SliceActionImpl(actions.get(i)).isToggle()) { 251ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return EventInfo.ROW_TYPE_TOGGLE; 252ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 253ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 254ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return EventInfo.ROW_TYPE_LIST; 255ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } else { 256ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return rc.getToggleItems().size() > 0 257ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor ? EventInfo.ROW_TYPE_TOGGLE 258ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor : EventInfo.ROW_TYPE_LIST; 259ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 260ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 261ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 262ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return EventInfo.ROW_TYPE_LIST; 263ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 264ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor 265ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor /** 266c50cc30733ad1058f98523c25f7413745638332aMady Mellor * @return the primary action for this list; i.e. action on the header or first row. 267c50cc30733ad1058f98523c25f7413745638332aMady Mellor */ 268c50cc30733ad1058f98523c25f7413745638332aMady Mellor @Nullable 269c50cc30733ad1058f98523c25f7413745638332aMady Mellor public SliceItem getPrimaryAction() { 270ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (mHeaderItem != null) { 271ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor if (mHeaderItem.hasHint(HINT_HORIZONTAL)) { 272ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor GridContent gc = new GridContent(mContext, mHeaderItem); 273ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return gc.getContentIntent(); 274ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } else { 275ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor RowContent rc = new RowContent(mContext, mHeaderItem, false); 276ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return rc.getPrimaryAction(); 277ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 278ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor } 279ca12087a732c2e40be512a8d9d25e0aec8bf92d8Mady Mellor return null; 280c50cc30733ad1058f98523c25f7413745638332aMady Mellor } 281c50cc30733ad1058f98523c25f7413745638332aMady Mellor 282968346929453133f937381a2e685bc4e47788e2cMady Mellor @Nullable 283968346929453133f937381a2e685bc4e47788e2cMady Mellor private static SliceItem findHeaderItem(@NonNull Slice slice) { 284968346929453133f937381a2e685bc4e47788e2cMady Mellor // See if header is specified 285bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellor String[] nonHints = new String[] {HINT_LIST_ITEM, HINT_SHORTCUT, HINT_ACTIONS, 2860707dbe9fa3225cc921a2305a611272f0dee1ca8Mady Mellor HINT_KEYWORDS, HINT_TTL, HINT_LAST_UPDATED}; 287b794b5b0f4bcd000e098265a6ec63d4b0cf3852fMady Mellor SliceItem header = SliceQuery.find(slice, FORMAT_SLICE, null, nonHints); 288968346929453133f937381a2e685bc4e47788e2cMady Mellor if (header != null && isValidHeader(header)) { 289968346929453133f937381a2e685bc4e47788e2cMady Mellor return header; 2906b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 291968346929453133f937381a2e685bc4e47788e2cMady Mellor return null; 2926b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 2936b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor 29453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor @Nullable 29553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor private static SliceItem getSeeMoreItem(@NonNull Slice slice) { 29653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor SliceItem item = SliceQuery.find(slice, null, HINT_SEE_MORE, null); 29753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (item != null && item.hasHint(HINT_SEE_MORE)) { 29853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (FORMAT_SLICE.equals(item.getFormat())) { 29953380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor List<SliceItem> items = item.getSlice().getItems(); 30053380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor if (items.size() == 1 && FORMAT_ACTION.equals(items.get(0).getFormat())) { 30153380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return items.get(0); 30253380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 30353380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return item; 30453380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 30553380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 30653380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor return null; 30753380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor } 30853380fecd1a1537e913578d1e53aa516d3f6e58eMady Mellor 30992952f5bbd2b743091af437767b0b48e48d292b5Mady Mellor /** 31092952f5bbd2b743091af437767b0b48e48d292b5Mady Mellor * @return whether the provided slice item is a valid header. 31192952f5bbd2b743091af437767b0b48e48d292b5Mady Mellor */ 31292952f5bbd2b743091af437767b0b48e48d292b5Mady Mellor public static boolean isValidHeader(SliceItem sliceItem) { 313bb51b5909dd8d5b233cd675fbc6fe74c42f48d3cMady Mellor if (FORMAT_SLICE.equals(sliceItem.getFormat()) && !sliceItem.hasAnyHints(HINT_LIST_ITEM, 31492952f5bbd2b743091af437767b0b48e48d292b5Mady Mellor HINT_ACTIONS, HINT_KEYWORDS, HINT_SEE_MORE)) { 315968346929453133f937381a2e685bc4e47788e2cMady Mellor // Minimum valid header is a slice with text 316968346929453133f937381a2e685bc4e47788e2cMady Mellor SliceItem item = SliceQuery.find(sliceItem, FORMAT_TEXT, (String) null, null); 317968346929453133f937381a2e685bc4e47788e2cMady Mellor return item != null; 3186b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 319968346929453133f937381a2e685bc4e47788e2cMady Mellor return false; 3206b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor } 3216b5cd6162737bc3a885d58c22549e5b17beded1aMady Mellor} 322