1edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng/*
2edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * Copyright (C) 2010 The Android Open Source Project
3edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng *
4edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License");
5edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * you may not use this file except in compliance with the License.
6edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * You may obtain a copy of the License at
7edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng *
8edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng *      http://www.apache.org/licenses/LICENSE-2.0
9edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng *
10edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * Unless required by applicable law or agreed to in writing, software
11edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS,
12edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * See the License for the specific language governing permissions and
14edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * limitations under the License.
15edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng */
16edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
17edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengpackage com.android.contacts.common.list;
18edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
19edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.app.Activity;
20edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.app.Fragment;
21edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.app.LoaderManager;
22edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.app.LoaderManager.LoaderCallbacks;
23edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.content.Context;
24edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.content.CursorLoader;
25edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.content.Intent;
26edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.content.Loader;
27edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.database.Cursor;
28edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.os.Bundle;
29edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.os.Handler;
30edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.os.Message;
31edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.os.Parcelable;
32edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.provider.ContactsContract.Directory;
33edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.text.TextUtils;
34edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.LayoutInflater;
35edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.MotionEvent;
36edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.View;
37edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.View.OnFocusChangeListener;
38edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.View.OnTouchListener;
39edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.ViewGroup;
40edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.view.inputmethod.InputMethodManager;
41edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.widget.AbsListView;
42edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.widget.AbsListView.OnScrollListener;
43edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.widget.AdapterView;
44edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.widget.AdapterView.OnItemClickListener;
45edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport android.widget.ListView;
46edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
47edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport com.android.common.widget.CompositeCursorAdapter.Partition;
48edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport com.android.contacts.common.ContactPhotoManager;
49edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport com.android.contacts.common.R;
50edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengimport com.android.contacts.common.preference.ContactsPreferences;
51edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
529f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglioimport java.util.Locale;
539f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio
54edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng/**
55edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng * Common base class for various contact-related list fragments.
56edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng */
57edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Chengpublic abstract class ContactEntryListFragment<T extends ContactEntryListAdapter>
58edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        extends Fragment
59edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        implements OnItemClickListener, OnScrollListener, OnFocusChangeListener, OnTouchListener,
60edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                LoaderCallbacks<Cursor> {
61edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String TAG = "ContactEntryListFragment";
62edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
63edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    // TODO: Make this protected. This should not be used from the PeopleActivity but
64edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    // instead use the new startActivityWithResultFromFragment API
65edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public static final int ACTIVITY_REQUEST_CODE_PICKER = 1;
66edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
67edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_LIST_STATE = "liststate";
68edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_SECTION_HEADER_DISPLAY_ENABLED = "sectionHeaderDisplayEnabled";
69edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_PHOTO_LOADER_ENABLED = "photoLoaderEnabled";
70edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_QUICK_CONTACT_ENABLED = "quickContactEnabled";
71edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_INCLUDE_PROFILE = "includeProfile";
72edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_SEARCH_MODE = "searchMode";
73edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_VISIBLE_SCROLLBAR_ENABLED = "visibleScrollbarEnabled";
74edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_SCROLLBAR_POSITION = "scrollbarPosition";
75edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_QUERY_STRING = "queryString";
76edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_DIRECTORY_SEARCH_MODE = "directorySearchMode";
77edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_SELECTION_VISIBLE = "selectionVisible";
78edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_REQUEST = "request";
79edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_DARK_THEME = "darkTheme";
80edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_LEGACY_COMPATIBILITY = "legacyCompatibility";
81edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String KEY_DIRECTORY_RESULT_LIMIT = "directoryResultLimit";
82edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
83edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final String DIRECTORY_ID_ARG_KEY = "directoryId";
84edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
85edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int DIRECTORY_LOADER_ID = -1;
86edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
87edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int DIRECTORY_SEARCH_DELAY_MILLIS = 300;
88edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int DIRECTORY_SEARCH_MESSAGE = 1;
89edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
90edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int DEFAULT_DIRECTORY_RESULT_LIMIT = 20;
91edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
92edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mSectionHeaderDisplayEnabled;
93edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mPhotoLoaderEnabled;
94edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mQuickContactEnabled = true;
95edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mIncludeProfile;
96edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mSearchMode;
97edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mVisibleScrollbarEnabled;
989f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio    private int mVerticalScrollbarPosition = getDefaultVerticalScrollbarPosition();
99edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private String mQueryString;
100edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private int mDirectorySearchMode = DirectoryListLoader.SEARCH_MODE_NONE;
101edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mSelectionVisible;
102edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mLegacyCompatibility;
103edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
104edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mEnabled = true;
105edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
106edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private T mAdapter;
107edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private View mView;
108edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private ListView mListView;
109edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
110edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
111edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Used for keeping track of the scroll state of the list.
112edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
113edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private Parcelable mListState;
114edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
115edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private int mDisplayOrder;
116edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private int mSortOrder;
117edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private int mDirectoryResultLimit = DEFAULT_DIRECTORY_RESULT_LIMIT;
118edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
119edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private ContactPhotoManager mPhotoManager;
120edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private ContactsPreferences mContactsPrefs;
121edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
122edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mForceLoad;
123edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
124edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mDarkTheme;
125edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
126edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected boolean mUserProfileExists;
127edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
128edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int STATUS_NOT_LOADED = 0;
129edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int STATUS_LOADING = 1;
130edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private static final int STATUS_LOADED = 2;
131edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
132edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private int mDirectoryListStatus = STATUS_NOT_LOADED;
133edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
134edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
135edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Indicates whether we are doing the initial complete load of data (false) or
136edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * a refresh caused by a change notification (true)
137edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
138edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private boolean mLoadPriorityDirectoriesOnly;
139edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
140edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private Context mContext;
141edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
142edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private LoaderManager mLoaderManager;
143edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
144edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private Handler mDelayedDirectorySearchHandler = new Handler() {
145edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        @Override
146edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        public void handleMessage(Message msg) {
147edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (msg.what == DIRECTORY_SEARCH_MESSAGE) {
148edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                loadDirectoryPartition(msg.arg1, (DirectoryPartition) msg.obj);
149edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
150edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
151edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    };
1529f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio    private int defaultVerticalScrollbarPosition;
153edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
154edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected abstract View inflateView(LayoutInflater inflater, ViewGroup container);
155edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected abstract T createListAdapter();
156edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
157edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
158edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * @param position Please note that the position is already adjusted for
159edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     *            header views, so "0" means the first list item below header
160edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     *            views.
161edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
162edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected abstract void onItemClick(int position, long id);
163edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
164edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
165edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onAttach(Activity activity) {
166edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onAttach(activity);
167edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        setContext(activity);
168edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        setLoaderManager(super.getLoaderManager());
169edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
170edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
171edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
172edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Sets a context for the fragment in the unit test environment.
173edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
174edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setContext(Context context) {
175edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mContext = context;
176edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        configurePhotoLoader();
177edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
178edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
179edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public Context getContext() {
180edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mContext;
181edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
182edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
183edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setEnabled(boolean enabled) {
184edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mEnabled != enabled) {
185edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mEnabled = enabled;
186edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mAdapter != null) {
187edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                if (mEnabled) {
188edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    reloadData();
189edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                } else {
190edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    mAdapter.clearPartitions();
191edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                }
192edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
193edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
194edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
195edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
196edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
197edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Overrides a loader manager for use in unit tests.
198edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
199edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setLoaderManager(LoaderManager loaderManager) {
200edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLoaderManager = loaderManager;
201edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
202edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
203edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
204edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public LoaderManager getLoaderManager() {
205edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mLoaderManager;
206edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
207edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
208edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public T getAdapter() {
209edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mAdapter;
210edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
211edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
212edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
213edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public View getView() {
214edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mView;
215edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
216edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
217edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public ListView getListView() {
218edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mListView;
219edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
220edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
221edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
222edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onSaveInstanceState(Bundle outState) {
223edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onSaveInstanceState(outState);
224edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_SECTION_HEADER_DISPLAY_ENABLED, mSectionHeaderDisplayEnabled);
225edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_PHOTO_LOADER_ENABLED, mPhotoLoaderEnabled);
226edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_QUICK_CONTACT_ENABLED, mQuickContactEnabled);
227edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_INCLUDE_PROFILE, mIncludeProfile);
228edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
229edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_VISIBLE_SCROLLBAR_ENABLED, mVisibleScrollbarEnabled);
230edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putInt(KEY_SCROLLBAR_POSITION, mVerticalScrollbarPosition);
231edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putInt(KEY_DIRECTORY_SEARCH_MODE, mDirectorySearchMode);
232edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_SELECTION_VISIBLE, mSelectionVisible);
233edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_LEGACY_COMPATIBILITY, mLegacyCompatibility);
234edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putString(KEY_QUERY_STRING, mQueryString);
235edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putInt(KEY_DIRECTORY_RESULT_LIMIT, mDirectoryResultLimit);
236edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        outState.putBoolean(KEY_DARK_THEME, mDarkTheme);
237edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
238edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mListView != null) {
239edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            outState.putParcelable(KEY_LIST_STATE, mListView.onSaveInstanceState());
240edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
241edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
242edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
243edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
244edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onCreate(Bundle savedState) {
245edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onCreate(savedState);
246edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mContactsPrefs = new ContactsPreferences(mContext);
247edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        restoreSavedState(savedState);
248edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
249edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
250edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void restoreSavedState(Bundle savedState) {
251edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (savedState == null) {
252edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return;
253edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
254edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
255edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mSectionHeaderDisplayEnabled = savedState.getBoolean(KEY_SECTION_HEADER_DISPLAY_ENABLED);
256edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mPhotoLoaderEnabled = savedState.getBoolean(KEY_PHOTO_LOADER_ENABLED);
257edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mQuickContactEnabled = savedState.getBoolean(KEY_QUICK_CONTACT_ENABLED);
258edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mIncludeProfile = savedState.getBoolean(KEY_INCLUDE_PROFILE);
259edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mSearchMode = savedState.getBoolean(KEY_SEARCH_MODE);
260edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mVisibleScrollbarEnabled = savedState.getBoolean(KEY_VISIBLE_SCROLLBAR_ENABLED);
261edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mVerticalScrollbarPosition = savedState.getInt(KEY_SCROLLBAR_POSITION);
262edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDirectorySearchMode = savedState.getInt(KEY_DIRECTORY_SEARCH_MODE);
263edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mSelectionVisible = savedState.getBoolean(KEY_SELECTION_VISIBLE);
264edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLegacyCompatibility = savedState.getBoolean(KEY_LEGACY_COMPATIBILITY);
265edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mQueryString = savedState.getString(KEY_QUERY_STRING);
266edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDirectoryResultLimit = savedState.getInt(KEY_DIRECTORY_RESULT_LIMIT);
267edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDarkTheme = savedState.getBoolean(KEY_DARK_THEME);
268edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
269edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // Retrieve list state. This will be applied in onLoadFinished
270edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListState = savedState.getParcelable(KEY_LIST_STATE);
271edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
272edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
273edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
274edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onStart() {
275edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onStart();
276edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
277edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mContactsPrefs.registerChangeListener(mPreferencesChangeListener);
278edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
279edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mForceLoad = loadPreferences();
280edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
281edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDirectoryListStatus = STATUS_NOT_LOADED;
282edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLoadPriorityDirectoriesOnly = true;
283edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
284edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        startLoading();
285edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
286edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
287edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void startLoading() {
288edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter == null) {
289edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            // The method was called before the fragment was started
290edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return;
291edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
292edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
293edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        configureAdapter();
294edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        int partitionCount = mAdapter.getPartitionCount();
295edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        for (int i = 0; i < partitionCount; i++) {
296edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            Partition partition = mAdapter.getPartition(i);
297edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (partition instanceof DirectoryPartition) {
298edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                DirectoryPartition directoryPartition = (DirectoryPartition)partition;
299edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                if (directoryPartition.getStatus() == DirectoryPartition.STATUS_NOT_LOADED) {
300edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    if (directoryPartition.isPriorityDirectory() || !mLoadPriorityDirectoriesOnly) {
301edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        startLoadingDirectoryPartition(i);
302edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    }
303edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                }
304edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            } else {
305edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                getLoaderManager().initLoader(i, null, this);
306edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
307edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
308edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
309edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // Next time this method is called, we should start loading non-priority directories
310edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLoadPriorityDirectoriesOnly = false;
311edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
312edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
313edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
314edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
315edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (id == DIRECTORY_LOADER_ID) {
316edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            DirectoryListLoader loader = new DirectoryListLoader(mContext);
317edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            loader.setDirectorySearchMode(mAdapter.getDirectorySearchMode());
318edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            loader.setLocalInvisibleDirectoryEnabled(
319edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    ContactEntryListAdapter.LOCAL_INVISIBLE_DIRECTORY_ENABLED);
320edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return loader;
321edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        } else {
322edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            CursorLoader loader = createCursorLoader();
323edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            long directoryId = args != null && args.containsKey(DIRECTORY_ID_ARG_KEY)
324edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    ? args.getLong(DIRECTORY_ID_ARG_KEY)
325edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    : Directory.DEFAULT;
326edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mAdapter.configureLoader(loader, directoryId);
327edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return loader;
328edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
329edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
330edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
331edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public CursorLoader createCursorLoader() {
332edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return new CursorLoader(mContext, null, null, null, null, null);
333edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
334edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
335edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private void startLoadingDirectoryPartition(int partitionIndex) {
336edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        DirectoryPartition partition = (DirectoryPartition)mAdapter.getPartition(partitionIndex);
337edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        partition.setStatus(DirectoryPartition.STATUS_LOADING);
338edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        long directoryId = partition.getDirectoryId();
339edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mForceLoad) {
340edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (directoryId == Directory.DEFAULT) {
341edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                loadDirectoryPartition(partitionIndex, partition);
342edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            } else {
343edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                loadDirectoryPartitionDelayed(partitionIndex, partition);
344edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
345edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        } else {
346edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            Bundle args = new Bundle();
347edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            args.putLong(DIRECTORY_ID_ARG_KEY, directoryId);
348edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            getLoaderManager().initLoader(partitionIndex, args, this);
349edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
350edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
351edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
352edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
353edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Queues up a delayed request to search the specified directory. Since
354edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * directory search will likely introduce a lot of network traffic, we want
355edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * to wait for a pause in the user's typing before sending a directory request.
356edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
357edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private void loadDirectoryPartitionDelayed(int partitionIndex, DirectoryPartition partition) {
358edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDelayedDirectorySearchHandler.removeMessages(DIRECTORY_SEARCH_MESSAGE, partition);
359edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        Message msg = mDelayedDirectorySearchHandler.obtainMessage(
360edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                DIRECTORY_SEARCH_MESSAGE, partitionIndex, 0, partition);
361edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDelayedDirectorySearchHandler.sendMessageDelayed(msg, DIRECTORY_SEARCH_DELAY_MILLIS);
362edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
363edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
364edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
365edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Loads the directory partition.
366edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
367edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void loadDirectoryPartition(int partitionIndex, DirectoryPartition partition) {
368edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        Bundle args = new Bundle();
369edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        args.putLong(DIRECTORY_ID_ARG_KEY, partition.getDirectoryId());
370edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        getLoaderManager().restartLoader(partitionIndex, args, this);
371edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
372edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
373edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
374edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Cancels all queued directory loading requests.
375edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
376edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private void removePendingDirectorySearchRequests() {
377edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDelayedDirectorySearchHandler.removeMessages(DIRECTORY_SEARCH_MESSAGE);
378edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
379edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
380edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
381edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
382edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (!mEnabled) {
383edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return;
384edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
385edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
386edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        int loaderId = loader.getId();
387edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (loaderId == DIRECTORY_LOADER_ID) {
388edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mDirectoryListStatus = STATUS_LOADED;
389edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mAdapter.changeDirectories(data);
390edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            startLoading();
391edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        } else {
392edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            onPartitionLoaded(loaderId, data);
393edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (isSearchMode()) {
394edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                int directorySearchMode = getDirectorySearchMode();
395edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                if (directorySearchMode != DirectoryListLoader.SEARCH_MODE_NONE) {
396edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    if (mDirectoryListStatus == STATUS_NOT_LOADED) {
397edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        mDirectoryListStatus = STATUS_LOADING;
398edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        getLoaderManager().initLoader(DIRECTORY_LOADER_ID, null, this);
399edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    } else {
400edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        startLoading();
401edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    }
402edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                }
403edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            } else {
404edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mDirectoryListStatus = STATUS_NOT_LOADED;
405edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                getLoaderManager().destroyLoader(DIRECTORY_LOADER_ID);
406edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
407edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
408edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
409edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
410edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onLoaderReset(Loader<Cursor> loader) {
411edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
412edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
413edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void onPartitionLoaded(int partitionIndex, Cursor data) {
414edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (partitionIndex >= mAdapter.getPartitionCount()) {
415edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            // When we get unsolicited data, ignore it.  This could happen
416edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            // when we are switching from search mode to the default mode.
417edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return;
418edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
419edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
420edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.changeCursor(partitionIndex, data);
421edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        setProfileHeader();
422edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        showCount(partitionIndex, data);
423edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
424edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (!isLoading()) {
425edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            completeRestoreInstanceState();
426edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
427edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
428edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
429edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isLoading() {
430edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter != null && mAdapter.isLoading()) {
431edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return true;
432edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
433edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
434edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (isLoadingDirectoryList()) {
435edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return true;
436edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
437edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
438edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return false;
439edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
440edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
441edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isLoadingDirectoryList() {
442edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return isSearchMode() && getDirectorySearchMode() != DirectoryListLoader.SEARCH_MODE_NONE
443edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                && (mDirectoryListStatus == STATUS_NOT_LOADED
444edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        || mDirectoryListStatus == STATUS_LOADING);
445edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
446edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
447edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
448edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onStop() {
449edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onStop();
450edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mContactsPrefs.unregisterChangeListener();
451edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.clearPartitions();
452edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
453edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
454edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void reloadData() {
455edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        removePendingDirectorySearchRequests();
456edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.onDataReload();
457edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLoadPriorityDirectoriesOnly = true;
458edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mForceLoad = true;
459edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        startLoading();
460edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
461edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
462edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
463edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Shows the count of entries included in the list. The default
464edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * implementation does nothing.
465edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
466edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void showCount(int partitionIndex, Cursor data) {
467edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
468edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
469edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
470edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Shows a view at the top of the list with a pseudo local profile prompting the user to add
471edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * a local profile. Default implementation does nothing.
472edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
473edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void setProfileHeader() {
474edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mUserProfileExists = false;
475edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
476edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
477edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
478edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Provides logic that dismisses this fragment. The default implementation
479edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * does nothing.
480edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
481edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void finish() {
482edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
483edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
484edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setSectionHeaderDisplayEnabled(boolean flag) {
485edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mSectionHeaderDisplayEnabled != flag) {
486edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mSectionHeaderDisplayEnabled = flag;
487edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mAdapter != null) {
488edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.setSectionHeaderDisplayEnabled(flag);
489edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
490edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            configureVerticalScrollbar();
491edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
492edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
493edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
494edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isSectionHeaderDisplayEnabled() {
495edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mSectionHeaderDisplayEnabled;
496edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
497edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
498edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setVisibleScrollbarEnabled(boolean flag) {
499edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mVisibleScrollbarEnabled != flag) {
500edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mVisibleScrollbarEnabled = flag;
501edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            configureVerticalScrollbar();
502edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
503edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
504edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
505edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isVisibleScrollbarEnabled() {
506edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mVisibleScrollbarEnabled;
507edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
508edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
509edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setVerticalScrollbarPosition(int position) {
510edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mVerticalScrollbarPosition != position) {
511edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mVerticalScrollbarPosition = position;
512edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            configureVerticalScrollbar();
513edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
514edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
515edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
516edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private void configureVerticalScrollbar() {
517edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        boolean hasScrollbar = isVisibleScrollbarEnabled() && isSectionHeaderDisplayEnabled();
518edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
519edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mListView != null) {
520edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setFastScrollEnabled(hasScrollbar);
521edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setFastScrollAlwaysVisible(hasScrollbar);
522edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setVerticalScrollbarPosition(mVerticalScrollbarPosition);
523edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
524edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            int leftPadding = 0;
525edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            int rightPadding = 0;
526edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mVerticalScrollbarPosition == View.SCROLLBAR_POSITION_LEFT) {
527edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                leftPadding = mContext.getResources().getDimensionPixelOffset(
528edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        R.dimen.list_visible_scrollbar_padding);
529edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            } else {
530edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                rightPadding = mContext.getResources().getDimensionPixelOffset(
531edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                        R.dimen.list_visible_scrollbar_padding);
532edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
533edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setPadding(leftPadding, mListView.getPaddingTop(),
534edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    rightPadding, mListView.getPaddingBottom());
535edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
536edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
537edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
538edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setPhotoLoaderEnabled(boolean flag) {
539edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mPhotoLoaderEnabled = flag;
540edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        configurePhotoLoader();
541edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
542edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
543edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isPhotoLoaderEnabled() {
544edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mPhotoLoaderEnabled;
545edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
546edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
547edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
548edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Returns true if the list is supposed to visually highlight the selected item.
549edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
550edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isSelectionVisible() {
551edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mSelectionVisible;
552edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
553edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
554edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setSelectionVisible(boolean flag) {
555edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        this.mSelectionVisible = flag;
556edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
557edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
558edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setQuickContactEnabled(boolean flag) {
559edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        this.mQuickContactEnabled = flag;
560edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
561edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
562edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setIncludeProfile(boolean flag) {
563edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mIncludeProfile = flag;
564edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if(mAdapter != null) {
565edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mAdapter.setIncludeProfile(flag);
566edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
567edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
568edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
569edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
570edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Enter/exit search mode.  By design, a fragment enters search mode only when it has a
571edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * non-empty query text, so the mode must be tightly related to the current query.
572edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * For this reason this method must only be called by {@link #setQueryString}.
573edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     *
574edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Also note this method doesn't call {@link #reloadData()}; {@link #setQueryString} does it.
575edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
576edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void setSearchMode(boolean flag) {
577edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mSearchMode != flag) {
578edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mSearchMode = flag;
579edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            setSectionHeaderDisplayEnabled(!mSearchMode);
580edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
581edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (!flag) {
582edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mDirectoryListStatus = STATUS_NOT_LOADED;
583edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                getLoaderManager().destroyLoader(DIRECTORY_LOADER_ID);
584edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
585edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
586edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mAdapter != null) {
587edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.setPinnedPartitionHeadersEnabled(flag);
588edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.setSearchMode(flag);
589edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
590edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.clearPartitions();
591edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                if (!flag) {
592edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    // If we are switching from search to regular display, remove all directory
593edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    // partitions after default one, assuming they are remote directories which
594edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    // should be cleaned up on exiting the search mode.
595edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    mAdapter.removeDirectoriesAfterDefault();
596edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                }
597edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.configureDefaultPartition(false, flag);
598edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
599edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
600edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mListView != null) {
601edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mListView.setFastScrollEnabled(!flag);
602edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
603edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
604edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
605edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
606edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public final boolean isSearchMode() {
607edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mSearchMode;
608edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
609edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
610edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public final String getQueryString() {
611edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mQueryString;
612edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
613edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
614edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setQueryString(String queryString, boolean delaySelection) {
615edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // Normalize the empty query.
616edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (TextUtils.isEmpty(queryString)) queryString = null;
617edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
618edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (!TextUtils.equals(mQueryString, queryString)) {
619edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mQueryString = queryString;
620edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            setSearchMode(!TextUtils.isEmpty(mQueryString));
621edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
622edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mAdapter != null) {
623edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.setQueryString(queryString);
624edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                reloadData();
625edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
626edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
627edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
628edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
629edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public int getDirectorySearchMode() {
630edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mDirectorySearchMode;
631edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
632edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
633edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setDirectorySearchMode(int mode) {
634edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDirectorySearchMode = mode;
635edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
636edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
637edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean isLegacyCompatibilityMode() {
638edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mLegacyCompatibility;
639edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
640edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
641edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setLegacyCompatibilityMode(boolean flag) {
642edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mLegacyCompatibility = flag;
643edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
644edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
645edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected int getContactNameDisplayOrder() {
646edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mDisplayOrder;
647edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
648edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
649edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void setContactNameDisplayOrder(int displayOrder) {
650edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDisplayOrder = displayOrder;
651edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter != null) {
652edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mAdapter.setContactNameDisplayOrder(displayOrder);
653edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
654edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
655edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
656edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public int getSortOrder() {
657edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mSortOrder;
658edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
659edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
660edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setSortOrder(int sortOrder) {
661edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mSortOrder = sortOrder;
662edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter != null) {
663edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mAdapter.setSortOrder(sortOrder);
664edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
665edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
666edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
667edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setDirectoryResultLimit(int limit) {
668edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDirectoryResultLimit = limit;
669edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
670edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
671edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected boolean loadPreferences() {
672edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        boolean changed = false;
673edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (getContactNameDisplayOrder() != mContactsPrefs.getDisplayOrder()) {
674edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            setContactNameDisplayOrder(mContactsPrefs.getDisplayOrder());
675edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            changed = true;
676edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
677edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
678edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (getSortOrder() != mContactsPrefs.getSortOrder()) {
679edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            setSortOrder(mContactsPrefs.getSortOrder());
680edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            changed = true;
681edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
682edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
683edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return changed;
684edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
685edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
686edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
687edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public View onCreateView(LayoutInflater inflater, ViewGroup container,
688edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            Bundle savedInstanceState) {
689edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        onCreateView(inflater, container);
690edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
691edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter = createListAdapter();
692edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
693edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        boolean searchMode = isSearchMode();
694edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setSearchMode(searchMode);
695edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.configureDefaultPartition(false, searchMode);
696edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setPhotoLoader(mPhotoManager);
697edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setAdapter(mAdapter);
698edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
699edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (!isSearchMode()) {
700edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setFocusableInTouchMode(true);
701edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.requestFocus();
702edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
703edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
704edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return mView;
705edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
706edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
707edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void onCreateView(LayoutInflater inflater, ViewGroup container) {
708edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mView = inflateView(inflater, container);
709edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
710edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView = (ListView)mView.findViewById(android.R.id.list);
711edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mListView == null) {
712edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            throw new RuntimeException(
713edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    "Your content must have a ListView whose id attribute is " +
714edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                    "'android.R.id.list'");
715edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
716edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
717edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        View emptyView = mView.findViewById(android.R.id.empty);
718edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (emptyView != null) {
719edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.setEmptyView(emptyView);
720edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
721edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
722edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setOnItemClickListener(this);
723edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setOnFocusChangeListener(this);
724edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setOnTouchListener(this);
725edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setFastScrollEnabled(!isSearchMode());
726edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
727edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // Tell list view to not show dividers. We'll do it ourself so that we can *not* show
728edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // them when an A-Z headers is visible.
729edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setDividerHeight(0);
730edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
731edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // We manually save/restore the listview state
732edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mListView.setSaveEnabled(false);
733edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
734edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        configureVerticalScrollbar();
735edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        configurePhotoLoader();
736edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
737edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
738edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void configurePhotoLoader() {
739edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (isPhotoLoaderEnabled() && mContext != null) {
740edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mPhotoManager == null) {
741edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mPhotoManager = ContactPhotoManager.getInstance(mContext);
742edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
743edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mListView != null) {
744edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mListView.setOnScrollListener(this);
745edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
746edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            if (mAdapter != null) {
747edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mAdapter.setPhotoLoader(mPhotoManager);
748edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            }
749edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
750edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
751edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
752edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void configureAdapter() {
753edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter == null) {
754edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            return;
755edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
756edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
757edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setQuickContactEnabled(mQuickContactEnabled);
758edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setIncludeProfile(mIncludeProfile);
759edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setQueryString(mQueryString);
760edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setDirectorySearchMode(mDirectorySearchMode);
761edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setPinnedPartitionHeadersEnabled(mSearchMode);
762edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setContactNameDisplayOrder(mDisplayOrder);
763edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setSortOrder(mSortOrder);
764edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setSectionHeaderDisplayEnabled(mSectionHeaderDisplayEnabled);
765edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setSelectionVisible(mSelectionVisible);
766edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setDirectoryResultLimit(mDirectoryResultLimit);
767edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mAdapter.setDarkTheme(mDarkTheme);
768edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
769edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
770edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
771edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
772edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            int totalItemCount) {
773edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
774edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
775edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
776edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onScrollStateChanged(AbsListView view, int scrollState) {
777edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
778edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mPhotoManager.pause();
779edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        } else if (isPhotoLoaderEnabled()) {
780edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mPhotoManager.resume();
781edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
782edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
783edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
784edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
785edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
786edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        hideSoftKeyboard();
787edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
788edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        int adjPosition = position - mListView.getHeaderViewsCount();
789edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (adjPosition >= 0) {
790edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            onItemClick(adjPosition, id);
791edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
792edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
793edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
794edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private void hideSoftKeyboard() {
795edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        // Hide soft keyboard, if visible
796edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        InputMethodManager inputMethodManager = (InputMethodManager)
797edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng                mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
798edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        inputMethodManager.hideSoftInputFromWindow(mListView.getWindowToken(), 0);
799edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
800edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
801edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
802edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Dismisses the soft keyboard when the list takes focus.
803edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
804edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
805edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onFocusChange(View view, boolean hasFocus) {
806edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (view == mListView && hasFocus) {
807edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            hideSoftKeyboard();
808edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
809edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
810edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
811edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
812edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Dismisses the soft keyboard when the list is touched.
813edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
814edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
815edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public boolean onTouch(View view, MotionEvent event) {
816edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (view == mListView) {
817edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            hideSoftKeyboard();
818edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
819edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        return false;
820edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
821edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
822edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    @Override
823edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onPause() {
824edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        super.onPause();
825edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        removePendingDirectorySearchRequests();
826edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
827edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
828edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
829edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Restore the list state after the adapter is populated.
830edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
831edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    protected void completeRestoreInstanceState() {
832edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mListState != null) {
833edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListView.onRestoreInstanceState(mListState);
834edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            mListState = null;
835edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
836edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
837edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
838edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void setDarkTheme(boolean value) {
839edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        mDarkTheme = value;
840edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        if (mAdapter != null) mAdapter.setDarkTheme(value);
841edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
842edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
843edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    /**
844edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     * Processes a result returned by the contact picker.
845edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng     */
846edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    public void onPickerResult(Intent data) {
847edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        throw new UnsupportedOperationException("Picker result handler is not implemented.");
848edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    }
849edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng
850edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    private ContactsPreferences.ChangeListener mPreferencesChangeListener =
851edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            new ContactsPreferences.ChangeListener() {
852edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        @Override
853edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        public void onChange() {
854edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            loadPreferences();
855edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng            reloadData();
856edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng        }
857edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng    };
8589f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio
8599f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio    private int getDefaultVerticalScrollbarPosition() {
8609f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio        final Locale locale = Locale.getDefault();
8619f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio        final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
8629f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio        switch (layoutDirection) {
8639f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio            case View.LAYOUT_DIRECTION_RTL:
8649f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio                return View.SCROLLBAR_POSITION_LEFT;
8659f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio            case View.LAYOUT_DIRECTION_LTR:
8669f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio            default:
8679f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio                return View.SCROLLBAR_POSITION_RIGHT;
8689f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio        }
8699f0c1621718b382531cbebfe38907e6d3db6ceaeFabrice Di Meglio    }
870edc1cd98e3c3e991dcfb5281a008f7d2cfea1495Chiao Cheng}
871