Home | History | Annotate | Download | only in widget
      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.contacts.common.widget;
     18 
     19 import android.telecom.PhoneAccount;
     20 import android.telecom.PhoneAccountHandle;
     21 import android.app.AlertDialog;
     22 import android.app.Dialog;
     23 import android.app.DialogFragment;
     24 import android.content.Context;
     25 import android.content.DialogInterface;
     26 import android.os.Bundle;
     27 import android.os.Handler;
     28 import android.os.ResultReceiver;
     29 import android.telecom.TelecomManager;
     30 import android.telephony.PhoneNumberUtils;
     31 import android.text.TextUtils;
     32 import android.view.LayoutInflater;
     33 import android.view.View;
     34 import android.view.ViewGroup;
     35 import android.widget.ArrayAdapter;
     36 import android.widget.CheckBox;
     37 import android.widget.CompoundButton;
     38 import android.widget.ImageView;
     39 import android.widget.LinearLayout;
     40 import android.widget.ListAdapter;
     41 import android.widget.TextView;
     42 
     43 import com.android.contacts.common.R;
     44 
     45 import java.util.ArrayList;
     46 import java.util.List;
     47 
     48 /**
     49  * Dialog that allows the user to select a phone accounts for a given action. Optionally provides
     50  * the choice to set the phone account as default.
     51  */
     52 public class SelectPhoneAccountDialogFragment extends DialogFragment {
     53     private static final String ARG_TITLE_RES_ID = "title_res_id";
     54     private static final String ARG_CAN_SET_DEFAULT = "can_set_default";
     55     private static final String ARG_ACCOUNT_HANDLES = "account_handles";
     56     private static final String ARG_IS_DEFAULT_CHECKED = "is_default_checked";
     57     private static final String ARG_LISTENER = "listener";
     58 
     59     private int mTitleResId;
     60     private boolean mCanSetDefault;
     61     private List<PhoneAccountHandle> mAccountHandles;
     62     private boolean mIsSelected;
     63     private boolean mIsDefaultChecked;
     64     private TelecomManager mTelecomManager;
     65     private SelectPhoneAccountListener mListener;
     66 
     67     /**
     68      * Create new fragment instance with default title and no option to set as default.
     69      *
     70      * @param accountHandles The {@code PhoneAccountHandle}s available to select from.
     71      * @param listener The listener for the results of the account selection.
     72      */
     73     public static SelectPhoneAccountDialogFragment newInstance(
     74             List<PhoneAccountHandle> accountHandles, SelectPhoneAccountListener listener) {
     75         return newInstance(R.string.select_account_dialog_title, false,
     76                 accountHandles, listener);
     77     }
     78 
     79     /**
     80      * Create new fragment instance.
     81      * This method also allows specifying a custom title and "set default" checkbox.
     82      *
     83      * @param titleResId The resource ID for the string to use in the title of the dialog.
     84      * @param canSetDefault {@code true} if the dialog should include an option to set the selection
     85      * as the default. False otherwise.
     86      * @param accountHandles The {@code PhoneAccountHandle}s available to select from.
     87      * @param listener The listener for the results of the account selection.
     88      */
     89     public static SelectPhoneAccountDialogFragment newInstance(int titleResId,
     90             boolean canSetDefault, List<PhoneAccountHandle> accountHandles,
     91             SelectPhoneAccountListener listener) {
     92         ArrayList<PhoneAccountHandle> accountHandlesCopy = new ArrayList<PhoneAccountHandle>();
     93         if (accountHandles != null) {
     94             accountHandlesCopy.addAll(accountHandles);
     95         }
     96         SelectPhoneAccountDialogFragment fragment = new SelectPhoneAccountDialogFragment();
     97         final Bundle args = new Bundle();
     98         args.putInt(ARG_TITLE_RES_ID, titleResId);
     99         args.putBoolean(ARG_CAN_SET_DEFAULT, canSetDefault);
    100         args.putParcelableArrayList(ARG_ACCOUNT_HANDLES, accountHandlesCopy);
    101         args.putParcelable(ARG_LISTENER, listener);
    102         fragment.setArguments(args);
    103         fragment.setListener(listener);
    104         return fragment;
    105     }
    106 
    107     public SelectPhoneAccountDialogFragment() {
    108     }
    109 
    110     public void setListener(SelectPhoneAccountListener listener) {
    111         mListener = listener;
    112     }
    113 
    114     public static class SelectPhoneAccountListener extends ResultReceiver {
    115         static final int RESULT_SELECTED = 1;
    116         static final int RESULT_DISMISSED = 2;
    117 
    118         static final String EXTRA_SELECTED_ACCOUNT_HANDLE = "extra_selected_account_handle";
    119         static final String EXTRA_SET_DEFAULT = "extra_set_default";
    120 
    121         public SelectPhoneAccountListener() {
    122             super(new Handler());
    123         }
    124 
    125         @Override
    126         protected void onReceiveResult(int resultCode, Bundle resultData) {
    127             if (resultCode == RESULT_SELECTED) {
    128                 onPhoneAccountSelected(
    129                         (PhoneAccountHandle) resultData.getParcelable(
    130                                 EXTRA_SELECTED_ACCOUNT_HANDLE),
    131                         resultData.getBoolean(EXTRA_SET_DEFAULT));
    132             } else if (resultCode == RESULT_DISMISSED) {
    133                 onDialogDismissed();
    134             }
    135         }
    136 
    137         public void onPhoneAccountSelected(PhoneAccountHandle selectedAccountHandle,
    138                 boolean setDefault) {}
    139 
    140         public void onDialogDismissed() {}
    141     }
    142 
    143     @Override
    144     public void onSaveInstanceState(Bundle outState) {
    145         super.onSaveInstanceState(outState);
    146         outState.putBoolean(ARG_IS_DEFAULT_CHECKED, mIsDefaultChecked);
    147     }
    148 
    149     @Override
    150     public Dialog onCreateDialog(Bundle savedInstanceState) {
    151         mTitleResId = getArguments().getInt(ARG_TITLE_RES_ID);
    152         mCanSetDefault = getArguments().getBoolean(ARG_CAN_SET_DEFAULT);
    153         mAccountHandles = getArguments().getParcelableArrayList(ARG_ACCOUNT_HANDLES);
    154         mListener = getArguments().getParcelable(ARG_LISTENER);
    155         if (savedInstanceState != null) {
    156             mIsDefaultChecked = savedInstanceState.getBoolean(ARG_IS_DEFAULT_CHECKED);
    157         }
    158         mIsSelected = false;
    159         mTelecomManager =
    160                 (TelecomManager) getActivity().getSystemService(Context.TELECOM_SERVICE);
    161 
    162         final DialogInterface.OnClickListener selectionListener =
    163                 new DialogInterface.OnClickListener() {
    164             @Override
    165             public void onClick(DialogInterface dialog, int which) {
    166                 mIsSelected = true;
    167                 PhoneAccountHandle selectedAccountHandle = mAccountHandles.get(which);
    168                 final Bundle result = new Bundle();
    169                 result.putParcelable(SelectPhoneAccountListener.EXTRA_SELECTED_ACCOUNT_HANDLE,
    170                         selectedAccountHandle);
    171                 result.putBoolean(SelectPhoneAccountListener.EXTRA_SET_DEFAULT,
    172                         mIsDefaultChecked);
    173                 if (mListener != null) {
    174                     mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_SELECTED, result);
    175                 }
    176             }
    177         };
    178 
    179         final CompoundButton.OnCheckedChangeListener checkListener =
    180                 new CompoundButton.OnCheckedChangeListener() {
    181             @Override
    182             public void onCheckedChanged(CompoundButton check, boolean isChecked) {
    183                 mIsDefaultChecked = isChecked;
    184             }
    185         };
    186 
    187         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    188         ListAdapter selectAccountListAdapter = new SelectAccountListAdapter(
    189                 builder.getContext(),
    190                 R.layout.select_account_list_item,
    191                 mAccountHandles);
    192 
    193         AlertDialog dialog = builder.setTitle(mTitleResId)
    194                 .setAdapter(selectAccountListAdapter, selectionListener)
    195                 .create();
    196 
    197         if (mCanSetDefault) {
    198             // Generate custom checkbox view
    199             LinearLayout checkboxLayout = (LinearLayout) getActivity()
    200                     .getLayoutInflater()
    201                     .inflate(R.layout.default_account_checkbox, null);
    202 
    203             CheckBox cb =
    204                     (CheckBox) checkboxLayout.findViewById(R.id.default_account_checkbox_view);
    205             cb.setOnCheckedChangeListener(checkListener);
    206             cb.setChecked(mIsDefaultChecked);
    207 
    208             dialog.getListView().addFooterView(checkboxLayout);
    209         }
    210 
    211         return dialog;
    212     }
    213 
    214     private class SelectAccountListAdapter extends ArrayAdapter<PhoneAccountHandle> {
    215         private int mResId;
    216 
    217         public SelectAccountListAdapter(
    218                 Context context, int resource, List<PhoneAccountHandle> accountHandles) {
    219             super(context, resource, accountHandles);
    220             mResId = resource;
    221         }
    222 
    223         @Override
    224         public View getView(int position, View convertView, ViewGroup parent) {
    225             LayoutInflater inflater = (LayoutInflater)
    226                     getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    227 
    228             View rowView;
    229             final ViewHolder holder;
    230 
    231             if (convertView == null) {
    232                 // Cache views for faster scrolling
    233                 rowView = inflater.inflate(mResId, null);
    234                 holder = new ViewHolder();
    235                 holder.labelTextView = (TextView) rowView.findViewById(R.id.label);
    236                 holder.numberTextView = (TextView) rowView.findViewById(R.id.number);
    237                 holder.imageView = (ImageView) rowView.findViewById(R.id.icon);
    238                 rowView.setTag(holder);
    239             }
    240             else {
    241                 rowView = convertView;
    242                 holder = (ViewHolder) rowView.getTag();
    243             }
    244 
    245             PhoneAccountHandle accountHandle = getItem(position);
    246             PhoneAccount account = mTelecomManager.getPhoneAccount(accountHandle);
    247             if (account == null) {
    248                 return rowView;
    249             }
    250             holder.labelTextView.setText(account.getLabel());
    251             if (account.getAddress() == null ||
    252                     TextUtils.isEmpty(account.getAddress().getSchemeSpecificPart())) {
    253                 holder.numberTextView.setVisibility(View.GONE);
    254             } else {
    255                 holder.numberTextView.setVisibility(View.VISIBLE);
    256                 holder.numberTextView.setText(
    257                         PhoneNumberUtils.createTtsSpannable(
    258                                 account.getAddress().getSchemeSpecificPart()));
    259             }
    260             holder.imageView.setImageDrawable(account.getIcon() != null
    261                     ? account.getIcon().loadDrawable(getContext()) : null);
    262             return rowView;
    263         }
    264 
    265         private class ViewHolder {
    266             TextView labelTextView;
    267             TextView numberTextView;
    268             ImageView imageView;
    269         }
    270     }
    271 
    272     @Override
    273     public void onStop() {
    274         if (!mIsSelected && mListener != null) {
    275             mListener.onReceiveResult(SelectPhoneAccountListener.RESULT_DISMISSED, null);
    276         }
    277         super.onStop();
    278     }
    279 }
    280