1 /* 2 * Copyright (C) 2014 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.settings.connectivity; 18 19 import android.app.Fragment; 20 import android.app.FragmentManager; 21 import android.app.FragmentTransaction; 22 import android.content.Context; 23 import android.os.Bundle; 24 import android.text.TextUtils; 25 import android.util.Log; 26 27 import com.android.tv.settings.connectivity.setup.MessageWizardFragment; 28 import com.android.tv.settings.connectivity.setup.PasswordInputWizardFragment; 29 import com.android.tv.settings.connectivity.setup.SelectFromListWizardFragment; 30 import com.android.tv.settings.connectivity.setup.SelectFromListWizardFragment.ListItem; 31 import com.android.tv.settings.connectivity.setup.TextInputWizardFragment; 32 import com.android.tv.settings.form.FormPage; 33 import com.android.tv.settings.form.FormPageResultListener; 34 35 import java.util.ArrayList; 36 37 /** 38 * Displays form pages. 39 */ 40 public class FormPageDisplayer 41 implements TextInputWizardFragment.Listener, SelectFromListWizardFragment.Listener, 42 PasswordInputWizardFragment.Listener { 43 44 public static final int DISPLAY_TYPE_TEXT_INPUT = 1; 45 public static final int DISPLAY_TYPE_LIST_CHOICE = 2; 46 public static final int DISPLAY_TYPE_LOADING = 3; 47 // Minimum 8 characters 48 public static final int DISPLAY_TYPE_PSK_INPUT = 4; 49 50 private static final int PSK_MIN_LENGTH = 8; 51 52 public interface FormPageInfo { 53 /** 54 * @return the resource id of the title for this page. 55 */ 56 int getTitleResourceId(); 57 58 /** 59 * @return the resource id of the description for this page. 0 if no description. 60 */ 61 int getDescriptionResourceId(); 62 63 /** 64 * @return the input type for the editable text field for this page. 65 */ 66 int getInputType(); 67 68 /** 69 * @return the way this form page should be displayed. 70 */ 71 int getDisplayType(); 72 73 /** 74 * @return the default value for this input 75 */ 76 int getDefaultPrefillResourceId(); 77 78 /** 79 * @return the set of choices for this form page. 80 */ 81 ArrayList<SelectFromListWizardFragment.ListItem> getChoices(Context context, 82 ArrayList<SelectFromListWizardFragment.ListItem> extraChoices); 83 } 84 85 public interface UserActivityListener { 86 void onUserActivity(); 87 } 88 89 private static final String TAG = "FormPageDisplayer"; 90 private static final boolean DEBUG = false; 91 private static final String RESULT_LIST_ITEM = "result_list_item"; 92 93 private final Context mContext; 94 private final FragmentManager mFragmentManager; 95 private TextInputWizardFragment.Listener mTextInputWizardFragmentListener; 96 private PasswordInputWizardFragment.Listener mPasswordInputWizardFragmentListener; 97 private SelectFromListWizardFragment.Listener mSelectFromListWizardFragmentListener; 98 private final int mContentViewId; 99 100 public FormPageDisplayer(Context context, FragmentManager fragmentManager, int contentViewId) { 101 mContext = context; 102 mFragmentManager = fragmentManager; 103 mContentViewId = contentViewId; 104 } 105 106 @Override 107 public boolean onTextInputComplete(String text) { 108 if (mTextInputWizardFragmentListener != null) { 109 return mTextInputWizardFragmentListener.onTextInputComplete(text); 110 } 111 return true; 112 } 113 114 @Override 115 public boolean onPasswordInputComplete(String text, boolean obfuscate) { 116 if (mPasswordInputWizardFragmentListener != null) { 117 return mPasswordInputWizardFragmentListener.onPasswordInputComplete(text, obfuscate); 118 } 119 return true; 120 } 121 122 @Override 123 public void onListSelectionComplete(ListItem listItem) { 124 if (mSelectFromListWizardFragmentListener != null) { 125 mSelectFromListWizardFragmentListener.onListSelectionComplete(listItem); 126 } 127 } 128 129 @Override 130 public void onListFocusChanged(ListItem listItem) { 131 if (mSelectFromListWizardFragmentListener != null) { 132 mSelectFromListWizardFragmentListener.onListFocusChanged(listItem); 133 } 134 } 135 136 public Fragment displayPage(FormPageInfo formPageInfo, String titleArgument, 137 String descriptionArgument, 138 ArrayList<SelectFromListWizardFragment.ListItem> extraChoices, 139 FormPage previousFormPage, UserActivityListener userActivityListener, 140 boolean showProgress, FormPage currentFormPage, 141 FormPageResultListener formPageResultListener, boolean forward, boolean emptyAllowed) { 142 if (DEBUG) { 143 Log.d(TAG, "Displaying: " + currentFormPage.getTitle()); 144 } 145 switch (formPageInfo.getDisplayType()) { 146 case DISPLAY_TYPE_LIST_CHOICE: 147 return displayList(formPageInfo, titleArgument, descriptionArgument, extraChoices, 148 currentFormPage, formPageResultListener, previousFormPage, 149 userActivityListener, forward); 150 151 case DISPLAY_TYPE_TEXT_INPUT: 152 return displayTextInput(formPageInfo, titleArgument, descriptionArgument, 153 currentFormPage, formPageResultListener, previousFormPage, forward, 154 emptyAllowed); 155 156 case DISPLAY_TYPE_PSK_INPUT: 157 return displayPskInput(formPageInfo, titleArgument, descriptionArgument, 158 currentFormPage, formPageResultListener, previousFormPage, forward); 159 160 case DISPLAY_TYPE_LOADING: 161 return displayLoading(formPageInfo, titleArgument, showProgress, forward); 162 163 default: 164 return null; 165 } 166 } 167 168 public ListItem getListItem(FormPage formPage) { 169 return formPage.getData().getParcelable(RESULT_LIST_ITEM); 170 } 171 172 public void displayFragment(Fragment fragment, boolean forward) { 173 FragmentTransaction transaction = mFragmentManager.beginTransaction(); 174 if (forward) { 175 transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 176 } else { 177 transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); 178 } 179 transaction.replace(mContentViewId, fragment).commit(); 180 } 181 182 private Fragment displayList(final FormPageInfo formPageInfo, String titleArgument, 183 String descriptionArgument, 184 ArrayList<SelectFromListWizardFragment.ListItem> extraChoices, final FormPage formPage, 185 final FormPageResultListener formPageResultListener, FormPage lastPage, 186 final UserActivityListener userActivityListener, boolean forward) { 187 Fragment fragment = SelectFromListWizardFragment.newInstance( 188 getTitle(formPageInfo, titleArgument), 189 getDescription(formPageInfo, descriptionArgument), 190 formPageInfo.getChoices(mContext, extraChoices), lastPage == null ? null 191 : (ListItem) lastPage.getData().getParcelable(RESULT_LIST_ITEM)); 192 displayFragment(fragment, forward); 193 mSelectFromListWizardFragmentListener = new SelectFromListWizardFragment.Listener() { 194 @Override 195 public void onListSelectionComplete(ListItem selection) { 196 Bundle result = new Bundle(); 197 result.putParcelable(RESULT_LIST_ITEM, selection); 198 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, selection.getName()); 199 formPageResultListener.onBundlePageResult(formPage, result); 200 } 201 202 @Override 203 public void onListFocusChanged(ListItem listItem) { 204 if (userActivityListener != null) { 205 userActivityListener.onUserActivity(); 206 } 207 } 208 }; 209 return fragment; 210 } 211 212 private Fragment displayTextInput(FormPageInfo formPageInfo, String titleArgument, 213 String descriptionArgument, final FormPage formPage, 214 final FormPageResultListener listener, FormPage lastPage, boolean forward, 215 final boolean emptyAllowed) { 216 final String prefill = lastPage != null && !TextUtils.isEmpty(lastPage.getDataSummary()) 217 ? lastPage.getDataSummary() : getDefaultPrefill(formPageInfo); 218 Fragment fragment = TextInputWizardFragment.newInstance( 219 getTitle(formPageInfo, titleArgument), 220 getDescription(formPageInfo, descriptionArgument), 221 formPageInfo.getInputType(), 222 prefill); 223 displayFragment(fragment, forward); 224 225 mTextInputWizardFragmentListener = new TextInputWizardFragment.Listener() { 226 @Override 227 public boolean onTextInputComplete(String text) { 228 if (!TextUtils.isEmpty(text) || emptyAllowed) { 229 Bundle result = new Bundle(); 230 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, text); 231 listener.onBundlePageResult(formPage, result); 232 return true; 233 } 234 return false; 235 } 236 }; 237 return fragment; 238 } 239 240 private Fragment displayPskInput(FormPageInfo formPageInfo, String titleArgument, 241 String descriptionArgument, final FormPage formPage, 242 final FormPageResultListener listener, FormPage lastPage, boolean forward) { 243 boolean obfuscate = lastPage != null 244 ? TextUtils.equals( 245 lastPage.getDataSecondary(), PasswordInputWizardFragment.OPTION_OBFUSCATE) 246 : false; 247 Fragment fragment = 248 PasswordInputWizardFragment.newInstance(getTitle(formPageInfo, titleArgument), 249 getDescription(formPageInfo, descriptionArgument), 250 lastPage == null ? null : lastPage.getDataSummary(), obfuscate); 251 displayFragment(fragment, forward); 252 253 mPasswordInputWizardFragmentListener = new PasswordInputWizardFragment.Listener() { 254 @Override 255 public boolean onPasswordInputComplete(String text, boolean obfuscate) { 256 if (!TextUtils.isEmpty(text) && text.length() >= PSK_MIN_LENGTH) { 257 Bundle result = new Bundle(); 258 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, text); 259 if (obfuscate) { 260 result.putString(FormPage.DATA_KEY_SECONDARY_STRING, 261 PasswordInputWizardFragment.OPTION_OBFUSCATE); 262 } 263 listener.onBundlePageResult(formPage, result); 264 return true; 265 } 266 return false; 267 } 268 }; 269 return fragment; 270 } 271 272 private Fragment displayLoading(FormPageInfo formPageInfo, String argument, 273 boolean showProgress, boolean forward) { 274 Fragment fragment = MessageWizardFragment.newInstance( 275 getTitle(formPageInfo, argument), showProgress); 276 displayFragment(fragment, forward); 277 return fragment; 278 } 279 280 private String getTitle(FormPageInfo formPageInfo, String argument) { 281 return mContext.getString(formPageInfo.getTitleResourceId(), argument); 282 } 283 284 private String getDescription(FormPageInfo formPageInfo, String argument) { 285 int descriptionResourceId = formPageInfo.getDescriptionResourceId(); 286 return (descriptionResourceId != 0) ? mContext.getString(descriptionResourceId, argument) 287 : null; 288 } 289 290 private String getDefaultPrefill(FormPageInfo formPageInfo) { 291 int defaultPrefillResourceId = formPageInfo.getDefaultPrefillResourceId(); 292 return (defaultPrefillResourceId != 0) 293 ? mContext.getString(defaultPrefillResourceId) : null; 294 } 295 } 296