1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tv.twopanelsettings.slices.compat.builders; 18 19 import android.app.PendingIntent; 20 import android.os.Parcelable; 21 import androidx.annotation.NonNull; 22 import androidx.annotation.Nullable; 23 import androidx.collection.ArraySet; 24 import androidx.core.util.Pair; 25 import androidx.remotecallback.RemoteCallback; 26 import java.util.ArrayList; 27 import java.util.List; 28 import java.util.Set; 29 30 /** 31 * Builder to construct a selection which can be added to a {@link ListBuilder}. 32 * 33 * <p>A selection presents a list of options to the user and allows the user to select exactly one 34 * option. 35 * 36 * <p>Slice framework has been deprecated, it will not receive any updates moving forward. If you 37 * are looking for a framework that handles communication across apps, consider using {@link 38 * android.app.appsearch.AppSearchManager}. 39 */ 40 // @Deprecated // Supported for TV 41 public class SelectionBuilder { 42 private final List<Pair<String, CharSequence>> mOptions; 43 private final Set<String> mOptionKeys; 44 private String mSelectedOption; 45 private SliceAction mPrimaryAction; 46 private Parcelable mInputAction; 47 48 private CharSequence mTitle; 49 private CharSequence mSubtitle; 50 private CharSequence mContentDescription; 51 private int mLayoutDirection; 52 53 /** Creates a SelectionBuilder with no options. */ SelectionBuilder()54 public SelectionBuilder() { 55 mOptions = new ArrayList<>(); 56 mOptionKeys = new ArraySet<>(); 57 mSelectedOption = null; 58 mLayoutDirection = -1; 59 } 60 61 /** 62 * Adds an option to this SelectionBuilder. 63 * 64 * <p>The new option will be appended to the list of options. 65 * 66 * @param optionKey the key that will be returned if the user selects this option 67 * @param optionText the text that will be displayed to the user for this option 68 * @return this SelectionBuilder 69 */ addOption(String optionKey, CharSequence optionText)70 public SelectionBuilder addOption(String optionKey, CharSequence optionText) { 71 if (mOptionKeys.contains(optionKey)) { 72 throw new IllegalArgumentException("optionKey " + optionKey + " is a duplicate"); 73 } 74 75 mOptions.add(new Pair<>(optionKey, optionText)); 76 mOptionKeys.add(optionKey); 77 return this; 78 } 79 80 /** 81 * Sets the primary action for the selection slice. 82 * 83 * <p>The action specified here will be sent when the whole slice is clicked, or when the app 84 * presenting the slice is not capable of rendering a selection interface. 85 * 86 * @param primaryAction the action to trigger when the user clicks the whole slice 87 * @return this SelectionBuilder 88 */ setPrimaryAction(@onNull SliceAction primaryAction)89 public SelectionBuilder setPrimaryAction(@NonNull SliceAction primaryAction) { 90 mPrimaryAction = primaryAction; 91 return this; 92 } 93 94 /** 95 * Sets the {@link PendingIntent} to send when the selection is made or changed. 96 * 97 * <p>The intent will include an extra with the key {@link 98 * com.android.tv.twopanelsettings.slices.compat.Slice#EXTRA_SELECTION} and a {@link String} value 99 * containing the key of the key of the selected option. 100 * 101 * @param inputAction the intent to send when the user makes or changes the selection 102 * @return this SelectionBuilder 103 */ setInputAction(@onNull PendingIntent inputAction)104 public SelectionBuilder setInputAction(@NonNull PendingIntent inputAction) { 105 mInputAction = inputAction; 106 return this; 107 } 108 109 /** 110 * Sets the {@link RemoteCallback} to send when the selection is made or changed. 111 * 112 * <p>The intent will include an extra with the key {@link 113 * com.android.tv.twopanelsettings.slices.compat.Slice#EXTRA_SELECTION} and a {@link String} value 114 * containing the key of the key of the selected option. 115 * 116 * @param inputAction the intent to send when the user makes or changes the selection 117 * @return this SelectionBuilder 118 */ setInputAction(@onNull RemoteCallback inputAction)119 public SelectionBuilder setInputAction(@NonNull RemoteCallback inputAction) { 120 mInputAction = inputAction.toPendingIntent(); 121 return this; 122 } 123 124 /** 125 * Sets which option is selected by default. 126 * 127 * @param selectedOption the key of the selected option 128 * @return this SelectionBuilder 129 */ setSelectedOption(String selectedOption)130 public SelectionBuilder setSelectedOption(String selectedOption) { 131 mSelectedOption = selectedOption; 132 return this; 133 } 134 135 /** 136 * Sets the title. 137 * 138 * @param title the title 139 * @return this SelectionBuilder 140 */ setTitle(@ullable CharSequence title)141 public SelectionBuilder setTitle(@Nullable CharSequence title) { 142 mTitle = title; 143 return this; 144 } 145 146 /** 147 * Sets the subtitle. 148 * 149 * @param subtitle the subtitle 150 * @return this SelectionBuilder 151 */ setSubtitle(@ullable CharSequence subtitle)152 public SelectionBuilder setSubtitle(@Nullable CharSequence subtitle) { 153 mSubtitle = subtitle; 154 return this; 155 } 156 157 /** 158 * Sets the content description. 159 * 160 * @param contentDescription the content description 161 * @return this SelectionBuilder 162 */ setContentDescription(@ullable CharSequence contentDescription)163 public SelectionBuilder setContentDescription(@Nullable CharSequence contentDescription) { 164 mContentDescription = contentDescription; 165 return this; 166 } 167 168 /** 169 * Sets the layout direction. 170 * 171 * @param layoutDirection the layout direction 172 * @return this SelectionBuilder 173 */ setLayoutDirection( @om.android.tv.twopanelsettings.slices.compat.builders.ListBuilder.LayoutDirection int layoutDirection)174 public SelectionBuilder setLayoutDirection( 175 @com.android.tv.twopanelsettings.slices.compat.builders.ListBuilder.LayoutDirection 176 int layoutDirection) { 177 mLayoutDirection = layoutDirection; 178 return this; 179 } 180 181 /** */ 182 // @RestrictTo(LIBRARY) getOptions()183 public List<Pair<String, CharSequence>> getOptions() { 184 return mOptions; 185 } 186 187 /** */ 188 // @RestrictTo(LIBRARY) getPrimaryAction()189 public SliceAction getPrimaryAction() { 190 return mPrimaryAction; 191 } 192 193 /** */ 194 // @RestrictTo(LIBRARY) getInputAction()195 public Parcelable getInputAction() { 196 return mInputAction; 197 } 198 199 /** */ 200 // @RestrictTo(LIBRARY) getSelectedOption()201 public String getSelectedOption() { 202 return mSelectedOption; 203 } 204 205 /** */ 206 // @RestrictTo(LIBRARY) getTitle()207 public CharSequence getTitle() { 208 return mTitle; 209 } 210 211 /** */ 212 // @RestrictTo(LIBRARY) getSubtitle()213 public CharSequence getSubtitle() { 214 return mSubtitle; 215 } 216 217 /** */ 218 // @RestrictTo(LIBRARY) getContentDescription()219 public CharSequence getContentDescription() { 220 return mContentDescription; 221 } 222 223 /** */ 224 // @RestrictTo(LIBRARY) getLayoutDirection()225 public int getLayoutDirection() { 226 return mLayoutDirection; 227 } 228 229 /** */ 230 // @RestrictTo(LIBRARY) check()231 public void check() { 232 if (getPrimaryAction() == null) { 233 throw new IllegalArgumentException("primaryAction must be set"); 234 } 235 if (getInputAction() == null) { 236 throw new IllegalArgumentException("inputAction must be set"); 237 } 238 if (mSelectedOption != null && !mOptionKeys.contains(mSelectedOption)) { 239 throw new IllegalArgumentException("selectedOption must be present in options"); 240 } 241 } 242 } 243