1/*
2 * Copyright (C) 2010 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 */
16package com.android.contacts.common.list;
17
18import android.content.CursorLoader;
19import android.content.Intent;
20import android.content.Loader;
21import android.database.Cursor;
22import android.net.Uri;
23import android.os.Bundle;
24import android.text.TextUtils;
25import android.util.Log;
26import android.view.LayoutInflater;
27import android.view.MenuItem;
28import android.view.View;
29import android.view.View.OnClickListener;
30import android.view.ViewGroup;
31
32import com.android.contacts.common.R;
33import com.android.contacts.common.list.ShortcutIntentBuilder.OnShortcutIntentCreatedListener;
34import com.android.contacts.common.util.AccountFilterUtil;
35
36/**
37 * Fragment containing a phone number list for picking.
38 */
39public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactEntryListAdapter>
40        implements OnShortcutIntentCreatedListener {
41    private static final String TAG = PhoneNumberPickerFragment.class.getSimpleName();
42
43    private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
44
45    private static final String KEY_SHORTCUT_ACTION = "shortcutAction";
46
47    private OnPhoneNumberPickerActionListener mListener;
48    private String mShortcutAction;
49
50    private ContactListFilter mFilter;
51
52    private View mAccountFilterHeader;
53    /**
54     * Lives as ListView's header and is shown when {@link #mAccountFilterHeader} is set
55     * to View.GONE.
56     */
57    private View mPaddingView;
58
59    private static final String KEY_FILTER = "filter";
60
61    /** true if the loader has started at least once. */
62    private boolean mLoaderStarted;
63
64    private boolean mUseCallableUri;
65
66    private ContactListItemView.PhotoPosition mPhotoPosition =
67            ContactListItemView.getDefaultPhotoPosition(false /* normal/non opposite */);
68
69    private class FilterHeaderClickListener implements OnClickListener {
70        @Override
71        public void onClick(View view) {
72            AccountFilterUtil.startAccountFilterActivityForResult(
73                    PhoneNumberPickerFragment.this,
74                    REQUEST_CODE_ACCOUNT_FILTER,
75                    mFilter);
76        }
77    }
78    private OnClickListener mFilterHeaderClickListener = new FilterHeaderClickListener();
79
80    public PhoneNumberPickerFragment() {
81        setQuickContactEnabled(false);
82        setPhotoLoaderEnabled(true);
83        setSectionHeaderDisplayEnabled(true);
84        setDirectorySearchMode(DirectoryListLoader.SEARCH_MODE_NONE);
85
86        // Show nothing instead of letting caller Activity show something.
87        setHasOptionsMenu(true);
88    }
89
90    public void setDirectorySearchEnabled(boolean flag) {
91        setDirectorySearchMode(flag ? DirectoryListLoader.SEARCH_MODE_DEFAULT
92                : DirectoryListLoader.SEARCH_MODE_NONE);
93    }
94
95    public void setOnPhoneNumberPickerActionListener(OnPhoneNumberPickerActionListener listener) {
96        this.mListener = listener;
97    }
98
99    public OnPhoneNumberPickerActionListener getOnPhoneNumberPickerListener() {
100        return mListener;
101    }
102
103    @Override
104    protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
105        super.onCreateView(inflater, container);
106
107        View paddingView = inflater.inflate(R.layout.contact_detail_list_padding, null, false);
108        mPaddingView = paddingView.findViewById(R.id.contact_detail_list_padding);
109        getListView().addHeaderView(paddingView);
110
111        mAccountFilterHeader = getView().findViewById(R.id.account_filter_header_container);
112        mAccountFilterHeader.setOnClickListener(mFilterHeaderClickListener);
113        updateFilterHeaderView();
114
115        setVisibleScrollbarEnabled(getVisibleScrollbarEnabled());
116    }
117
118    protected boolean getVisibleScrollbarEnabled() {
119        return true;
120    }
121
122    @Override
123    protected void setSearchMode(boolean flag) {
124        super.setSearchMode(flag);
125        updateFilterHeaderView();
126    }
127
128    private void updateFilterHeaderView() {
129        final ContactListFilter filter = getFilter();
130        if (mAccountFilterHeader == null || filter == null) {
131            return;
132        }
133        final boolean shouldShowHeader =
134                !isSearchMode() &&
135                AccountFilterUtil.updateAccountFilterTitleForPhone(
136                        mAccountFilterHeader, filter, false);
137        if (shouldShowHeader) {
138            mPaddingView.setVisibility(View.GONE);
139            mAccountFilterHeader.setVisibility(View.VISIBLE);
140        } else {
141            mPaddingView.setVisibility(View.VISIBLE);
142            mAccountFilterHeader.setVisibility(View.GONE);
143        }
144    }
145
146    @Override
147    public void restoreSavedState(Bundle savedState) {
148        super.restoreSavedState(savedState);
149
150        if (savedState == null) {
151            return;
152        }
153
154        mFilter = savedState.getParcelable(KEY_FILTER);
155        mShortcutAction = savedState.getString(KEY_SHORTCUT_ACTION);
156    }
157
158    @Override
159    public void onSaveInstanceState(Bundle outState) {
160        super.onSaveInstanceState(outState);
161        outState.putParcelable(KEY_FILTER, mFilter);
162        outState.putString(KEY_SHORTCUT_ACTION, mShortcutAction);
163    }
164
165    @Override
166    public boolean onOptionsItemSelected(MenuItem item) {
167        final int itemId = item.getItemId();
168        if (itemId == android.R.id.home) {  // See ActionBar#setDisplayHomeAsUpEnabled()
169            if (mListener != null) {
170                mListener.onHomeInActionBarSelected();
171            }
172            return true;
173        }
174        return super.onOptionsItemSelected(item);
175    }
176
177    /**
178     * @param shortcutAction either {@link Intent#ACTION_CALL} or
179     *            {@link Intent#ACTION_SENDTO} or null.
180     */
181    public void setShortcutAction(String shortcutAction) {
182        this.mShortcutAction = shortcutAction;
183    }
184
185    @Override
186    protected void onItemClick(int position, long id) {
187        final Uri phoneUri = getPhoneUri(position);
188
189        if (phoneUri != null) {
190            pickPhoneNumber(phoneUri);
191        } else {
192            final String number = getPhoneNumber(position);
193            if (!TextUtils.isEmpty(number)) {
194                cacheContactInfo(position);
195                mListener.onCallNumberDirectly(number);
196            } else {
197                Log.w(TAG, "Item at " + position + " was clicked before"
198                        + " adapter is ready. Ignoring");
199            }
200        }
201    }
202
203    protected void cacheContactInfo(int position) {
204        // Not implemented. Hook for child classes
205    }
206
207    protected String getPhoneNumber(int position) {
208        final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter();
209        return adapter.getPhoneNumber(position);
210    }
211
212    protected Uri getPhoneUri(int position) {
213        final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter();
214        return adapter.getDataUri(position);
215    }
216
217    @Override
218    protected void startLoading() {
219        mLoaderStarted = true;
220        super.startLoading();
221    }
222
223    @Override
224    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
225        super.onLoadFinished(loader, data);
226
227        // disable scroll bar if there is no data
228        setVisibleScrollbarEnabled(data != null && data.getCount() > 0);
229    }
230
231    public void setUseCallableUri(boolean useCallableUri) {
232        mUseCallableUri = useCallableUri;
233    }
234
235    public boolean usesCallableUri() {
236        return mUseCallableUri;
237    }
238
239    @Override
240    protected ContactEntryListAdapter createListAdapter() {
241        PhoneNumberListAdapter adapter = new PhoneNumberListAdapter(getActivity());
242        adapter.setDisplayPhotos(true);
243        adapter.setUseCallableUri(mUseCallableUri);
244        return adapter;
245    }
246
247    @Override
248    protected void configureAdapter() {
249        super.configureAdapter();
250
251        final ContactEntryListAdapter adapter = getAdapter();
252        if (adapter == null) {
253            return;
254        }
255
256        if (!isSearchMode() && mFilter != null) {
257            adapter.setFilter(mFilter);
258        }
259
260        setPhotoPosition(adapter);
261    }
262
263    protected void setPhotoPosition(ContactEntryListAdapter adapter) {
264        ((PhoneNumberListAdapter) adapter).setPhotoPosition(mPhotoPosition);
265    }
266
267    @Override
268    protected View inflateView(LayoutInflater inflater, ViewGroup container) {
269        return inflater.inflate(R.layout.contact_list_content, null);
270    }
271
272    public void pickPhoneNumber(Uri uri) {
273        if (mShortcutAction == null) {
274            mListener.onPickPhoneNumberAction(uri);
275        } else {
276            startPhoneNumberShortcutIntent(uri);
277        }
278    }
279
280    protected void startPhoneNumberShortcutIntent(Uri uri) {
281        ShortcutIntentBuilder builder = new ShortcutIntentBuilder(getActivity(), this);
282        builder.createPhoneNumberShortcutIntent(uri, mShortcutAction);
283    }
284
285    public void onShortcutIntentCreated(Uri uri, Intent shortcutIntent) {
286        mListener.onShortcutIntentCreated(shortcutIntent);
287    }
288
289    @Override
290    public void onPickerResult(Intent data) {
291        mListener.onPickPhoneNumberAction(data.getData());
292    }
293
294    @Override
295    public void onActivityResult(int requestCode, int resultCode, Intent data) {
296        if (requestCode == REQUEST_CODE_ACCOUNT_FILTER) {
297            if (getActivity() != null) {
298                AccountFilterUtil.handleAccountFilterResult(
299                        ContactListFilterController.getInstance(getActivity()), resultCode, data);
300            } else {
301                Log.e(TAG, "getActivity() returns null during Fragment#onActivityResult()");
302            }
303        }
304    }
305
306    public ContactListFilter getFilter() {
307        return mFilter;
308    }
309
310    public void setFilter(ContactListFilter filter) {
311        if ((mFilter == null && filter == null) ||
312                (mFilter != null && mFilter.equals(filter))) {
313            return;
314        }
315
316        mFilter = filter;
317        if (mLoaderStarted) {
318            reloadData();
319        }
320        updateFilterHeaderView();
321    }
322
323    public void setPhotoPosition(ContactListItemView.PhotoPosition photoPosition) {
324        mPhotoPosition = photoPosition;
325
326        final PhoneNumberListAdapter adapter = (PhoneNumberListAdapter) getAdapter();
327        if (adapter != null) {
328            adapter.setPhotoPosition(photoPosition);
329        }
330    }
331}
332