From 8898cd0577d41cfa4e6acf785c9e904bd71fbdfd Mon Sep 17 00:00:00 2001 From: Yorke Lee Date: Thu, 8 Aug 2013 10:24:27 -0700 Subject: Removing and renaming classes from Dialer * No code was changed, just either removed or renamed * Reshuffled a couple of ids around in dialpad_fragment to fix some compile time errors that somehow weren't caught before Change-Id: I9e2381edfb14b0940015deb8cbd94786a1242f43 --- src/com/android/dialer/DialtactsActivity.java | 26 +- src/com/android/dialer/NewSearchFragment.java | 75 ----- src/com/android/dialer/SearchFragment.java | 75 +++++ .../android/dialer/calllog/CallLogActivity.java | 2 +- .../android/dialer/dialpad/DialpadFragment.java | 4 +- src/com/android/dialer/dialpad/SmartDialEntry.java | 44 --- .../dialer/dialpad/SmartDialLoaderTask.java | 107 ------- .../android/dialer/dialpad/SmartDialTextView.java | 76 ----- .../dialer/list/NewPhoneFavoriteFragment.java | 341 --------------------- .../dialer/list/NewPhoneFavoriteMergedAdapter.java | 204 ------------ .../android/dialer/list/PhoneFavoriteFragment.java | 340 ++++++++++++++++++++ .../dialer/list/PhoneFavoriteMergedAdapter.java | 301 ++++++------------ 12 files changed, 530 insertions(+), 1065 deletions(-) delete mode 100644 src/com/android/dialer/NewSearchFragment.java create mode 100644 src/com/android/dialer/SearchFragment.java delete mode 100644 src/com/android/dialer/dialpad/SmartDialEntry.java delete mode 100644 src/com/android/dialer/dialpad/SmartDialLoaderTask.java delete mode 100644 src/com/android/dialer/dialpad/SmartDialTextView.java delete mode 100644 src/com/android/dialer/list/NewPhoneFavoriteFragment.java delete mode 100644 src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java create mode 100644 src/com/android/dialer/list/PhoneFavoriteFragment.java (limited to 'src') diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java index 89e5b5a6b..726c17687 100644 --- a/src/com/android/dialer/DialtactsActivity.java +++ b/src/com/android/dialer/DialtactsActivity.java @@ -71,7 +71,7 @@ import com.android.dialer.calllog.CallLogActivity; import com.android.dialer.dialpad.DialpadFragment; import com.android.dialer.dialpad.SmartDialNameMatcher; import com.android.dialer.interactions.PhoneNumberInteraction; -import com.android.dialer.list.NewPhoneFavoriteFragment; +import com.android.dialer.list.PhoneFavoriteFragment; import com.android.dialer.list.OnListFragmentScrolledListener; import com.android.dialer.list.ShowAllContactsFragment; import com.android.dialer.list.SmartDialSearchFragment; @@ -88,7 +88,7 @@ import java.util.ArrayList; public class DialtactsActivity extends TransactionSafeActivity implements View.OnClickListener, DialpadFragment.OnDialpadQueryChangedListener, PopupMenu.OnMenuItemClickListener, OnListFragmentScrolledListener, - NewPhoneFavoriteFragment.OnPhoneFavoriteFragmentStartedListener, + PhoneFavoriteFragment.OnPhoneFavoriteFragmentStartedListener, DialpadFragment.OnDialpadFragmentStartedListener { private static final String TAG = "DialtactsActivity"; @@ -124,7 +124,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O /** * The main fragment displaying the user's favorites and frequent contacts */ - private NewPhoneFavoriteFragment mPhoneFavoriteFragment; + private PhoneFavoriteFragment mPhoneFavoriteFragment; /** * Fragment containing the dialpad that slides into view @@ -134,7 +134,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O /** * Fragment for searching phone numbers using the alphanumeric keyboard. */ - private NewSearchFragment mRegularSearchFragment; + private SearchFragment mRegularSearchFragment; /** * Fragment for searching phone numbers using the dialpad. @@ -246,15 +246,15 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O final Intent intent = getIntent(); fixIntent(intent); - setContentView(R.layout.new_dialtacts_activity); + setContentView(R.layout.dialtacts_activity); getActionBar().hide(); if (savedInstanceState == null) { - mPhoneFavoriteFragment = new NewPhoneFavoriteFragment(); + mPhoneFavoriteFragment = new PhoneFavoriteFragment(); mPhoneFavoriteFragment.setListener(mPhoneFavoriteListener); - mRegularSearchFragment = new NewSearchFragment(); + mRegularSearchFragment = new SearchFragment(); mSmartDialSearchFragment = new SmartDialSearchFragment(); mDialpadFragment = new DialpadFragment(); mShowAllContactsFragment = new ShowAllContactsFragment(); @@ -284,11 +284,11 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O protected void onResume() { super.onResume(); final FragmentManager fm = getFragmentManager(); - mPhoneFavoriteFragment = (NewPhoneFavoriteFragment) fm.findFragmentByTag( + mPhoneFavoriteFragment = (PhoneFavoriteFragment) fm.findFragmentByTag( TAG_FAVORITES_FRAGMENT); mDialpadFragment = (DialpadFragment) fm.findFragmentByTag(TAG_DIALPAD_FRAGMENT); - mRegularSearchFragment = (NewSearchFragment) fm.findFragmentByTag( + mRegularSearchFragment = (SearchFragment) fm.findFragmentByTag( TAG_REGULAR_SEARCH_FRAGMENT); mRegularSearchFragment.setOnPhoneNumberPickerActionListener( mPhoneNumberPickerActionListener); @@ -311,7 +311,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O @Override public void onAttachFragment(Fragment fragment) { - if (fragment instanceof DialpadFragment || fragment instanceof NewSearchFragment + if (fragment instanceof DialpadFragment || fragment instanceof SearchFragment || fragment instanceof SmartDialSearchFragment || fragment instanceof ShowAllContactsFragment) { final FragmentTransaction transaction = getFragmentManager().beginTransaction(); @@ -369,7 +369,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O case R.id.overflow_menu: { final PopupMenu popupMenu = new PopupMenu(DialtactsActivity.this, view); final Menu menu = popupMenu.getMenu(); - popupMenu.inflate(R.menu.dialtacts_options_new); + popupMenu.inflate(R.menu.dialtacts_options); popupMenu.setOnMenuItemClickListener(this); popupMenu.show(); break; @@ -704,8 +704,8 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O } } - private final NewPhoneFavoriteFragment.Listener mPhoneFavoriteListener = - new NewPhoneFavoriteFragment.Listener() { + private final PhoneFavoriteFragment.Listener mPhoneFavoriteListener = + new PhoneFavoriteFragment.Listener() { @Override public void onContactSelected(Uri contactUri) { PhoneNumberInteraction.startInteractionForPhoneCall( diff --git a/src/com/android/dialer/NewSearchFragment.java b/src/com/android/dialer/NewSearchFragment.java deleted file mode 100644 index e8e40d6aa..000000000 --- a/src/com/android/dialer/NewSearchFragment.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.dialer; - -import android.app.Activity; -import android.view.LayoutInflater; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AbsListView.OnScrollListener; - -import com.android.contacts.common.list.ContactListItemView; -import com.android.contacts.common.list.PhoneNumberPickerFragment; -import com.android.dialer.list.OnListFragmentScrolledListener; - -public class NewSearchFragment extends PhoneNumberPickerFragment { - - private OnListFragmentScrolledListener mActivityScrollListener; - - public NewSearchFragment() { - setDirectorySearchEnabled(true); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - - setQuickContactEnabled(true); - setDarkTheme(false); - setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(true /* opposite */)); - setUseCallableUri(true); - - try { - mActivityScrollListener = (OnListFragmentScrolledListener) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnListFragmentScrolledListener"); - } - } - - @Override - public void onStart() { - super.onStart(); - getListView().setOnScrollListener(new OnScrollListener() { - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - mActivityScrollListener.onListFragmentScrollStateChange(scrollState); - } - - @Override - public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, - int totalItemCount) { - } - }); - } - - @Override - protected void setSearchMode(boolean flag) { - super.setSearchMode(flag); - // This hides the "All contacts with phone numbers" header in the search fragment - getAdapter().setHasHeader(0, false); - } -} diff --git a/src/com/android/dialer/SearchFragment.java b/src/com/android/dialer/SearchFragment.java new file mode 100644 index 000000000..54d29d43f --- /dev/null +++ b/src/com/android/dialer/SearchFragment.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.dialer; + +import android.app.Activity; +import android.view.LayoutInflater; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AbsListView.OnScrollListener; + +import com.android.contacts.common.list.ContactListItemView; +import com.android.contacts.common.list.PhoneNumberPickerFragment; +import com.android.dialer.list.OnListFragmentScrolledListener; + +public class SearchFragment extends PhoneNumberPickerFragment { + + private OnListFragmentScrolledListener mActivityScrollListener; + + public SearchFragment() { + setDirectorySearchEnabled(true); + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + + setQuickContactEnabled(true); + setDarkTheme(false); + setPhotoPosition(ContactListItemView.getDefaultPhotoPosition(true /* opposite */)); + setUseCallableUri(true); + + try { + mActivityScrollListener = (OnListFragmentScrolledListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnListFragmentScrolledListener"); + } + } + + @Override + public void onStart() { + super.onStart(); + getListView().setOnScrollListener(new OnScrollListener() { + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + mActivityScrollListener.onListFragmentScrollStateChange(scrollState); + } + + @Override + public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, + int totalItemCount) { + } + }); + } + + @Override + protected void setSearchMode(boolean flag) { + super.setSearchMode(flag); + // This hides the "All contacts with phone numbers" header in the search fragment + getAdapter().setHasHeader(0, false); + } +} diff --git a/src/com/android/dialer/calllog/CallLogActivity.java b/src/com/android/dialer/calllog/CallLogActivity.java index 39909a1f8..662614f95 100644 --- a/src/com/android/dialer/calllog/CallLogActivity.java +++ b/src/com/android/dialer/calllog/CallLogActivity.java @@ -151,7 +151,7 @@ public class CallLogActivity extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { final MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.call_log_options_new, menu); + inflater.inflate(R.menu.call_log_options, menu); return true; } diff --git a/src/com/android/dialer/dialpad/DialpadFragment.java b/src/com/android/dialer/dialpad/DialpadFragment.java index 76cca3362..3052c67f0 100644 --- a/src/com/android/dialer/dialpad/DialpadFragment.java +++ b/src/com/android/dialer/dialpad/DialpadFragment.java @@ -346,7 +346,7 @@ public class DialpadFragment extends Fragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { - final View fragmentView = inflater.inflate(R.layout.new_dialpad_fragment, container, + final View fragmentView = inflater.inflate(R.layout.dialpad_fragment, container, false); fragmentView.buildLayer(); @@ -938,7 +938,7 @@ public class DialpadFragment extends Fragment case R.id.overflow_menu_on_dialpad: { final PopupMenu popupMenu = new PopupMenu(getActivity(), view); final Menu menu = popupMenu.getMenu(); - popupMenu.inflate(R.menu.dialpad_options_new); + popupMenu.inflate(R.menu.dialpad_options); popupMenu.setOnMenuItemClickListener(this); setupMenuItems(menu); popupMenu.show(); diff --git a/src/com/android/dialer/dialpad/SmartDialEntry.java b/src/com/android/dialer/dialpad/SmartDialEntry.java deleted file mode 100644 index 9ff491293..000000000 --- a/src/com/android/dialer/dialpad/SmartDialEntry.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer.dialpad; - -import android.net.Uri; - -import java.util.ArrayList; - -public class SmartDialEntry { - /** Display name for the contact. */ - public final CharSequence displayName; - public final Uri contactUri; - public final CharSequence phoneNumber; - - public final ArrayList matchPositions; - public final SmartDialMatchPosition phoneNumberMatchPosition; - - public static final SmartDialEntry NULL = new SmartDialEntry("", Uri.EMPTY, "", - new ArrayList(), null); - - public SmartDialEntry(CharSequence displayName, Uri contactUri, CharSequence phoneNumber, - ArrayList matchPositions, - SmartDialMatchPosition phoneNumberMatchPosition) { - this.displayName = displayName; - this.contactUri = contactUri; - this.matchPositions = matchPositions; - this.phoneNumber = phoneNumber; - this.phoneNumberMatchPosition = phoneNumberMatchPosition; - } -} diff --git a/src/com/android/dialer/dialpad/SmartDialLoaderTask.java b/src/com/android/dialer/dialpad/SmartDialLoaderTask.java deleted file mode 100644 index 38a04ad8f..000000000 --- a/src/com/android/dialer/dialpad/SmartDialLoaderTask.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer.dialpad; - -import android.content.Context; -import android.os.AsyncTask; -import android.provider.ContactsContract; -import android.provider.ContactsContract.Contacts; -import android.telephony.PhoneNumberUtils; - -import com.android.contacts.common.preference.ContactsPreferences; -import com.android.contacts.common.util.StopWatch; -import com.android.dialer.database.DialerDatabaseHelper; -import com.android.dialer.database.DialerDatabaseHelper.ContactNumber; - -import com.google.common.collect.Lists; - -import java.util.ArrayList; -import java.util.List; - -/** - * This task searches through the provided cache to return the top 3 contacts(ranked by confidence) - * that match the query, then passes it back to the {@link SmartDialLoaderCallback} through a - * callback function. - */ -public class SmartDialLoaderTask extends AsyncTask> { - private final String TAG = SmartDialLoaderTask.class.getSimpleName(); - - public interface SmartDialLoaderCallback { - void setSmartDialAdapterEntries(List list, String query); - } - - static private final boolean DEBUG = false; - - private final SmartDialLoaderCallback mCallback; - - private final DialerDatabaseHelper mDialerDatabaseHelper; - - private final String mQuery; - - private final SmartDialNameMatcher mNameMatcher; - - public SmartDialLoaderTask(SmartDialLoaderCallback callback, String query, Context context) { - this.mCallback = callback; - mDialerDatabaseHelper = DialerDatabaseHelper.getInstance(context); - this.mQuery = query; - this.mNameMatcher = new SmartDialNameMatcher(PhoneNumberUtils.normalizeNumber(query), - SmartDialPrefix.getMap()); - } - - @Override - protected List doInBackground(String... params) { - return getContactMatches(); - } - - @Override - protected void onPostExecute(List result) { - if (mCallback != null) { - mCallback.setSmartDialAdapterEntries(result, mQuery); - } - } - - /** - * Loads top visible contacts with phone numbers and check if their display names match the - * query. - */ - private ArrayList getContactMatches() { - - final StopWatch stopWatch = DEBUG ? StopWatch.start("Start Match") : null; - - final ArrayList allMatches = mDialerDatabaseHelper.getLooseMatches(mQuery, - mNameMatcher); - if (DEBUG) { - stopWatch.lap("Find matches"); - } - - final ArrayList candidates = Lists.newArrayList(); - for (ContactNumber contact : allMatches) { - final boolean matches = mNameMatcher.matches(contact.displayName); - candidates.add(new SmartDialEntry( - contact.displayName, - Contacts.getLookupUri(contact.id, contact.lookupKey), - contact.phoneNumber, - mNameMatcher.getMatchPositions(), - mNameMatcher.matchesNumber(contact.phoneNumber, mNameMatcher.getQuery()) - )); - } - if (DEBUG) { - stopWatch.stopAndLog(TAG + " Match Complete", 0); - } - return candidates; - } -} diff --git a/src/com/android/dialer/dialpad/SmartDialTextView.java b/src/com/android/dialer/dialpad/SmartDialTextView.java deleted file mode 100644 index 398f99ba5..000000000 --- a/src/com/android/dialer/dialpad/SmartDialTextView.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.dialer.dialpad; - -import android.content.Context; -import android.graphics.Paint; -import android.text.TextUtils; -import android.util.AttributeSet; -import android.widget.TextView; - -import com.android.dialer.R; - -public class SmartDialTextView extends TextView { - - private final float mPadding; - private final float mExtraPadding; - - public SmartDialTextView(Context context) { - this(context, null); - } - - public SmartDialTextView(Context context, AttributeSet attrs) { - super(context, attrs); - mPadding = getResources().getDimension(R.dimen.smartdial_suggestions_padding); - mExtraPadding = getResources().getDimension(R.dimen.smartdial_suggestions_extra_padding); - } - - @Override - protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { - super.onTextChanged(text, start, lengthBefore, lengthAfter); - rescaleText(getWidth()); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - rescaleText(w); - } - - private void rescaleText(int w) { - if (w == 0) { - return; - } - setTextScaleX(1); - final Paint paint = getPaint(); - float width = w - 2 * mPadding - 2 * mExtraPadding; - - float ratio = width / paint.measureText(getText().toString()); - TextUtils.TruncateAt ellipsizeAt = null; - if (ratio < 1.0f) { - if (ratio < 0.8f) { - // If the text is too big to fit even after scaling to 80%, just ellipsize it - // instead. - ellipsizeAt = TextUtils.TruncateAt.END; - setTextScaleX(0.8f); - } else { - setTextScaleX(ratio); - } - } - setEllipsize(ellipsizeAt); - } -} diff --git a/src/com/android/dialer/list/NewPhoneFavoriteFragment.java b/src/com/android/dialer/list/NewPhoneFavoriteFragment.java deleted file mode 100644 index 58dac2fb6..000000000 --- a/src/com/android/dialer/list/NewPhoneFavoriteFragment.java +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.dialer.list; - -import android.app.Activity; -import android.app.Fragment; -import android.app.LoaderManager; -import android.content.CursorLoader; -import android.content.Loader; -import android.database.Cursor; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.AbsListView; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.FrameLayout; -import android.widget.ListView; -import android.widget.TextView; - -import com.android.contacts.common.ContactPhotoManager; -import com.android.contacts.common.ContactTileLoaderFactory; -import com.android.contacts.common.GeoUtil; -import com.android.contacts.common.list.ContactTileView; -import com.android.contacts.common.list.PhoneNumberListAdapter; -import com.android.dialer.DialtactsActivity; -import com.android.dialer.R; -import com.android.dialer.calllog.ContactInfoHelper; -import com.android.dialer.calllog.CallLogAdapter; -import com.android.dialer.calllog.CallLogQueryHandler; - -/** - * Fragment for Phone UI's favorite screen. - * - * This fragment contains three kinds of contacts in one screen: "starred", "frequent", and "all" - * contacts. To show them at once, this merges results from {@link com.android.contacts.common.list.ContactTileAdapter} and - * {@link com.android.contacts.common.list.PhoneNumberListAdapter} into one unified list using {@link PhoneFavoriteMergedAdapter}. - * A contact filter header is also inserted between those adapters' results. - */ -public class NewPhoneFavoriteFragment extends Fragment implements OnItemClickListener, - CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher { - private static final String TAG = NewPhoneFavoriteFragment.class.getSimpleName(); - private static final boolean DEBUG = false; - - /** - * Used with LoaderManager. - */ - private static int LOADER_ID_CONTACT_TILE = 1; - private static int LOADER_ID_ALL_CONTACTS = 2; - - public interface OnPhoneFavoriteFragmentStartedListener { - public void onPhoneFavoriteFragmentStarted(); - } - - public interface Listener { - public void onContactSelected(Uri contactUri); - public void onCallNumberDirectly(String phoneNumber); - } - - private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks { - @Override - public CursorLoader onCreateLoader(int id, Bundle args) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); - return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); - mContactTileAdapter.setContactCursor(data); - - // Show the filter header with "loading" state. - mAccountFilterHeader.setVisibility(View.VISIBLE); - } - - @Override - public void onLoaderReset(Loader loader) { - if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); - } - } - - private class ContactTileAdapterListener implements ContactTileView.Listener { - @Override - public void onContactSelected(Uri contactUri, Rect targetRect) { - if (mListener != null) { - mListener.onContactSelected(contactUri); - } - } - - @Override - public void onCallNumberDirectly(String phoneNumber) { - if (mListener != null) { - mListener.onCallNumberDirectly(phoneNumber); - } - } - - @Override - public int getApproximateTileWidth() { - return getView().getWidth() / mContactTileAdapter.getColumnCount(); - } - } - - private class ScrollListener implements ListView.OnScrollListener { - @Override - public void onScroll(AbsListView view, - int firstVisibleItem, int visibleItemCount, int totalItemCount) { - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - mActivityScrollListener.onListFragmentScrollStateChange(scrollState); - } - } - - private Listener mListener; - - private OnListFragmentScrolledListener mActivityScrollListener; - private NewPhoneFavoriteMergedAdapter mAdapter; - private PhoneFavoritesTileAdapter mContactTileAdapter; - private PhoneNumberListAdapter mAllContactsAdapter; - - private CallLogAdapter mCallLogAdapter; - private CallLogQueryHandler mCallLogQueryHandler; - - private TextView mEmptyView; - private ListView mListView; - private View mShowAllContactsButton; - /** - * Layout containing {@link #mAccountFilterHeader}. Used to limit area being "pressed". - */ - private FrameLayout mAccountFilterHeaderContainer; - private View mAccountFilterHeader; - - /** - * Layout used when contacts load is slower than expected and thus "loading" view should be - * shown. - */ - private View mLoadingView; - - private final ContactTileView.Listener mContactTileAdapterListener = - new ContactTileAdapterListener(); - private final LoaderManager.LoaderCallbacks mContactTileLoaderListener = - new ContactTileLoaderListener(); - private final ScrollListener mScrollListener = new ScrollListener(); - - private boolean mOptionsMenuHasFrequents; - - @Override - public void onAttach(Activity activity) { - if (DEBUG) Log.d(TAG, "onAttach()"); - super.onAttach(activity); - - // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. - // We don't construct the resultant adapter at this moment since it requires LayoutInflater - // that will be available on onCreateView(). - - mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener, - getResources().getInteger(R.integer.contact_tile_column_count_in_favorites_new), - 1); - mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); - } - - @Override - public void onCreate(Bundle savedState) { - if (DEBUG) Log.d(TAG, "onCreate()"); - super.onCreate(savedState); - - mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), - this, 1); - final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); - mCallLogAdapter = new CallLogAdapter(getActivity(), this, - new ContactInfoHelper(getActivity(), currentCountryIso)); - setHasOptionsMenu(true); - } - - @Override - public void onResume() { - super.onResume(); - mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL); - mCallLogAdapter.setLoading(true); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - final View listLayout = inflater.inflate( - R.layout.new_phone_favorites_fragment, container, false); - - mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list); - mListView.setItemsCanFocus(true); - mListView.setOnItemClickListener(this); - mListView.setVerticalScrollBarEnabled(false); - mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); - mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); - - // TODO krelease: Don't show this header anymore - // Create the account filter header but keep it hidden until "all" contacts are loaded. - mAccountFilterHeaderContainer = new FrameLayout(getActivity(), null); - mAccountFilterHeader = inflater.inflate(R.layout.account_filter_header_for_phone_favorite, - mListView, false); - mAccountFilterHeaderContainer.addView(mAccountFilterHeader); - - mLoadingView = inflater.inflate(R.layout.phone_loading_contacts, mListView, false); - mShowAllContactsButton = inflater.inflate(R.layout.show_all_contact_button, mListView, - false); - mShowAllContactsButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - showAllContacts(); - } - }); - - mAdapter = new NewPhoneFavoriteMergedAdapter(getActivity(), mContactTileAdapter, - mAccountFilterHeaderContainer, mCallLogAdapter, mLoadingView, - mShowAllContactsButton); - - mListView.setAdapter(mAdapter); - - mListView.setOnScrollListener(mScrollListener); - mListView.setFastScrollEnabled(false); - mListView.setFastScrollAlwaysVisible(false); - - mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty); - mEmptyView.setText(getString(R.string.listTotalAllContactsZero)); - mListView.setEmptyView(mEmptyView); - - return listLayout; - } - - - // TODO krelease: update the options menu when displaying the popup menu instead. We could - // possibly get rid of this method entirely. - private boolean isOptionsMenuChanged() { - return mOptionsMenuHasFrequents != hasFrequents(); - } - - // TODO krelease: Configure the menu items properly. Since the menu items show up as a PopupMenu - // rather than a normal actionbar menu, the initialization should be done there. - /* - @Override - public void onPrepareOptionsMenu(Menu menu) { - final MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents); - mOptionsMenuHasFrequents = hasFrequents(); - clearFrequents.setVisible(mOptionsMenuHasFrequents); - }*/ - - private boolean hasFrequents() { - return mContactTileAdapter.getNumFrequents() > 0; - } - - @Override - public void onStart() { - super.onStart(); - - final Activity activity = getActivity(); - - try { - ((OnPhoneFavoriteFragmentStartedListener) activity).onPhoneFavoriteFragmentStarted(); - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnPhoneFavoriteFragmentStartedListener"); - } - - try { - mActivityScrollListener = (OnListFragmentScrolledListener) activity; - } catch (ClassCastException e) { - throw new ClassCastException(activity.toString() - + " must implement OnListFragmentScrolledListener"); - } - - // Use initLoader() instead of restartLoader() to refraining unnecessary reload. - // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will - // be called, on which we'll check if "all" contacts should be reloaded again or not. - getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); - } - - /** - * {@inheritDoc} - * - * This is only effective for elements provided by {@link #mContactTileAdapter}. - * {@link #mContactTileAdapter} has its own logic for click events. - */ - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - if (position <= contactTileAdapterCount) { - Log.e(TAG, "onItemClick() event for unexpected position. " - + "The position " + position + " is before \"all\" section. Ignored."); - } - } - - /** - * Gets called when user click on the show all contacts button. - */ - private void showAllContacts() { - // TODO {klp} Use interface for the fragment to communicate with the activity - if (getActivity() instanceof DialtactsActivity) { - ((DialtactsActivity) getActivity()).showAllContactsFragment(); - } - } - - public void setListener(Listener listener) { - mListener = listener; - } - - // TODO krelease: Implement this - @Override - public void onVoicemailStatusFetched(Cursor statusCursor) { - } - - @Override - public void onCallsFetched(Cursor cursor) { - mCallLogAdapter.setLoading(false); - mCallLogAdapter.changeCursor(cursor); - mAdapter.notifyDataSetChanged(); - } - - // TODO krelease: Implement this - @Override - public void fetchCalls() { - } -} diff --git a/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java deleted file mode 100644 index 3c3200407..000000000 --- a/src/com/android/dialer/list/NewPhoneFavoriteMergedAdapter.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. - * Licensed to The Android Open Source Project. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.dialer.list; - -import android.content.Context; -import android.content.res.Resources; -import android.database.DataSetObserver; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.FrameLayout; - -import com.android.dialer.R; -import com.android.dialer.calllog.CallLogAdapter; - -/** - * An adapter that combines items from {@link com.android.contacts.common.list.ContactTileAdapter} - * and {@link com.android.dialer.calllog.CallLogAdapter} into a single list. - */ -public class NewPhoneFavoriteMergedAdapter extends BaseAdapter { - - private class CustomDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - notifyDataSetChanged(); - } - } - - private static final String TAG = NewPhoneFavoriteMergedAdapter.class.getSimpleName(); - - private final PhoneFavoritesTileAdapter mContactTileAdapter; - private final CallLogAdapter mCallLogAdapter; - private final View mLoadingView; - private final View mShowAllContactsButton; - - private final int mCallLogPadding; - - private final Context mContext; - - private final DataSetObserver mObserver; - - public NewPhoneFavoriteMergedAdapter(Context context, - PhoneFavoritesTileAdapter contactTileAdapter, - View accountFilterHeaderContainer, - CallLogAdapter callLogAdapter, - View loadingView, - View showAllContactsButton) { - final Resources resources = context.getResources(); - mContext = context; - mCallLogPadding = resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding); - mContactTileAdapter = contactTileAdapter; - mCallLogAdapter = callLogAdapter; - - mObserver = new CustomDataSetObserver(); - mContactTileAdapter.registerDataSetObserver(mObserver); - mLoadingView = loadingView; - mShowAllContactsButton = showAllContactsButton; - } - - @Override - public boolean isEmpty() { - // This adapter will always contain at least the all contacts button - return false; - } - - @Override - public int getCount() { - return mContactTileAdapter.getCount() + mCallLogAdapter.getCount() + 1; - } - - @Override - public Object getItem(int position) { - final int callLogAdapterCount = mCallLogAdapter.getCount(); - - if (callLogAdapterCount > 0) { - if (position < callLogAdapterCount) { - return mCallLogAdapter.getItem(position); - } - // Set position to the position of the actual favorite contact in the favorites adapter - position = getAdjustedFavoritePosition(position, callLogAdapterCount); - } - return mContactTileAdapter.getItem(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getViewTypeCount() { - return (mContactTileAdapter.getViewTypeCount() + mCallLogAdapter.getViewTypeCount() + 1); - } - - @Override - public int getItemViewType(int position) { - final int callLogAdapterCount = mCallLogAdapter.getCount(); - - if (position < callLogAdapterCount) { - // View type of the call log adapter is the last view type of the contact tile adapter - // + 1 - return mContactTileAdapter.getViewTypeCount(); - } else if (position < getCount() - 1) { - return mContactTileAdapter.getItemViewType( - getAdjustedFavoritePosition(position, callLogAdapterCount)); - } else { - // View type of the show all contact button is the last view type of the contact tile - // adapter + 2 - return mContactTileAdapter.getViewTypeCount() + 1; - } - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - final int callLogAdapterCount = mCallLogAdapter.getCount(); - - if (position == getCount() - 1) { - return mShowAllContactsButton; - } - - if (callLogAdapterCount > 0) { - if (position == 0) { - final FrameLayout wrapper; - if (convertView == null) { - wrapper = new FrameLayout(mContext); - } else { - wrapper = (FrameLayout) convertView; - } - - // Special case wrapper view for the most recent call log item. This allows - // us to create a card-like effect for the more recent call log item in - // the PhoneFavoriteMergedAdapter, but keep the original look of the item in - // the CallLogAdapter. - final View view = mCallLogAdapter.getView(position, convertView == null ? - null : wrapper.getChildAt(0), parent); - wrapper.removeAllViews(); - view.setBackgroundResource(R.drawable.dialer_recent_card_bg); - - final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT); - - params.setMarginsRelative(mCallLogPadding, mCallLogPadding, mCallLogPadding, - mCallLogPadding); - view.setLayoutParams(params); - wrapper.addView(view); - - return wrapper; - } - // Set position to the position of the actual favorite contact in the - // favorites adapter - position = getAdjustedFavoritePosition(position, callLogAdapterCount); - } - - // Favorites section - final View view = mContactTileAdapter.getView(position, convertView, parent); - if (position >= mContactTileAdapter.getMaxTiledRows()) { - final FrameLayout frameLayout = (FrameLayout) view; - final View child = frameLayout.getChildAt(0); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT); - child.setLayoutParams(params); - } - return view; - } - - @Override - public boolean areAllItemsEnabled() { - // If "all" section is being loaded we'll show mLoadingView, which is not enabled. - // Otherwise check the all the other components in the ListView and return appropriate - // result. - return mCallLogAdapter.areAllItemsEnabled() && mContactTileAdapter.areAllItemsEnabled(); - } - - @Override - public boolean isEnabled(int position) { - final int callLogAdapterCount = mCallLogAdapter.getCount(); - if (position < callLogAdapterCount) { - return mCallLogAdapter.isEnabled(position); - } else { // For favorites section - return mContactTileAdapter.isEnabled( - getAdjustedFavoritePosition(position, callLogAdapterCount)); - } - } - - private int getAdjustedFavoritePosition(int position, int callLogAdapterCount) { - return position - callLogAdapterCount; - } -} diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java new file mode 100644 index 000000000..64a9b84d2 --- /dev/null +++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.dialer.list; + +import android.app.Activity; +import android.app.Fragment; +import android.app.LoaderManager; +import android.content.CursorLoader; +import android.content.Loader; +import android.database.Cursor; +import android.graphics.Rect; +import android.net.Uri; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.AbsListView; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.FrameLayout; +import android.widget.ListView; +import android.widget.TextView; + +import com.android.contacts.common.ContactPhotoManager; +import com.android.contacts.common.ContactTileLoaderFactory; +import com.android.contacts.common.GeoUtil; +import com.android.contacts.common.list.ContactTileView; +import com.android.contacts.common.list.PhoneNumberListAdapter; +import com.android.dialer.DialtactsActivity; +import com.android.dialer.R; +import com.android.dialer.calllog.ContactInfoHelper; +import com.android.dialer.calllog.CallLogAdapter; +import com.android.dialer.calllog.CallLogQueryHandler; + +/** + * Fragment for Phone UI's favorite screen. + * + * This fragment contains three kinds of contacts in one screen: "starred", "frequent", and "all" + * contacts. To show them at once, this merges results from {@link com.android.contacts.common.list.ContactTileAdapter} and + * {@link com.android.contacts.common.list.PhoneNumberListAdapter} into one unified list using {@link PhoneFavoriteMergedAdapter}. + * A contact filter header is also inserted between those adapters' results. + */ +public class PhoneFavoriteFragment extends Fragment implements OnItemClickListener, + CallLogQueryHandler.Listener, CallLogAdapter.CallFetcher { + private static final String TAG = PhoneFavoriteFragment.class.getSimpleName(); + private static final boolean DEBUG = false; + + /** + * Used with LoaderManager. + */ + private static int LOADER_ID_CONTACT_TILE = 1; + + public interface OnPhoneFavoriteFragmentStartedListener { + public void onPhoneFavoriteFragmentStarted(); + } + + public interface Listener { + public void onContactSelected(Uri contactUri); + public void onCallNumberDirectly(String phoneNumber); + } + + private class ContactTileLoaderListener implements LoaderManager.LoaderCallbacks { + @Override + public CursorLoader onCreateLoader(int id, Bundle args) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onCreateLoader."); + return ContactTileLoaderFactory.createStrequentPhoneOnlyLoader(getActivity()); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoadFinished"); + mContactTileAdapter.setContactCursor(data); + + // Show the filter header with "loading" state. + mAccountFilterHeader.setVisibility(View.VISIBLE); + } + + @Override + public void onLoaderReset(Loader loader) { + if (DEBUG) Log.d(TAG, "ContactTileLoaderListener#onLoaderReset. "); + } + } + + private class ContactTileAdapterListener implements ContactTileView.Listener { + @Override + public void onContactSelected(Uri contactUri, Rect targetRect) { + if (mListener != null) { + mListener.onContactSelected(contactUri); + } + } + + @Override + public void onCallNumberDirectly(String phoneNumber) { + if (mListener != null) { + mListener.onCallNumberDirectly(phoneNumber); + } + } + + @Override + public int getApproximateTileWidth() { + return getView().getWidth() / mContactTileAdapter.getColumnCount(); + } + } + + private class ScrollListener implements ListView.OnScrollListener { + @Override + public void onScroll(AbsListView view, + int firstVisibleItem, int visibleItemCount, int totalItemCount) { + } + + @Override + public void onScrollStateChanged(AbsListView view, int scrollState) { + mActivityScrollListener.onListFragmentScrollStateChange(scrollState); + } + } + + private Listener mListener; + + private OnListFragmentScrolledListener mActivityScrollListener; + private PhoneFavoriteMergedAdapter mAdapter; + private PhoneFavoritesTileAdapter mContactTileAdapter; + private PhoneNumberListAdapter mAllContactsAdapter; + + private CallLogAdapter mCallLogAdapter; + private CallLogQueryHandler mCallLogQueryHandler; + + private TextView mEmptyView; + private ListView mListView; + private View mShowAllContactsButton; + /** + * Layout containing {@link #mAccountFilterHeader}. Used to limit area being "pressed". + */ + private FrameLayout mAccountFilterHeaderContainer; + private View mAccountFilterHeader; + + /** + * Layout used when contacts load is slower than expected and thus "loading" view should be + * shown. + */ + private View mLoadingView; + + private final ContactTileView.Listener mContactTileAdapterListener = + new ContactTileAdapterListener(); + private final LoaderManager.LoaderCallbacks mContactTileLoaderListener = + new ContactTileLoaderListener(); + private final ScrollListener mScrollListener = new ScrollListener(); + + private boolean mOptionsMenuHasFrequents; + + @Override + public void onAttach(Activity activity) { + if (DEBUG) Log.d(TAG, "onAttach()"); + super.onAttach(activity); + + // Construct two base adapters which will become part of PhoneFavoriteMergedAdapter. + // We don't construct the resultant adapter at this moment since it requires LayoutInflater + // that will be available on onCreateView(). + + mContactTileAdapter = new PhoneFavoritesTileAdapter(activity, mContactTileAdapterListener, + getResources().getInteger(R.integer.contact_tile_column_count_in_favorites_new), + 1); + mContactTileAdapter.setPhotoLoader(ContactPhotoManager.getInstance(activity)); + } + + @Override + public void onCreate(Bundle savedState) { + if (DEBUG) Log.d(TAG, "onCreate()"); + super.onCreate(savedState); + + mCallLogQueryHandler = new CallLogQueryHandler(getActivity().getContentResolver(), + this, 1); + final String currentCountryIso = GeoUtil.getCurrentCountryIso(getActivity()); + mCallLogAdapter = new CallLogAdapter(getActivity(), this, + new ContactInfoHelper(getActivity(), currentCountryIso)); + setHasOptionsMenu(true); + } + + @Override + public void onResume() { + super.onResume(); + mCallLogQueryHandler.fetchCalls(CallLogQueryHandler.CALL_TYPE_ALL); + mCallLogAdapter.setLoading(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View listLayout = inflater.inflate( + R.layout.phone_favorites_fragment, container, false); + + mListView = (ListView) listLayout.findViewById(R.id.contact_tile_list); + mListView.setItemsCanFocus(true); + mListView.setOnItemClickListener(this); + mListView.setVerticalScrollBarEnabled(false); + mListView.setVerticalScrollbarPosition(View.SCROLLBAR_POSITION_RIGHT); + mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY); + + // TODO krelease: Don't show this header anymore + // Create the account filter header but keep it hidden until "all" contacts are loaded. + mAccountFilterHeaderContainer = new FrameLayout(getActivity(), null); + mAccountFilterHeader = inflater.inflate(R.layout.account_filter_header_for_phone_favorite, + mListView, false); + mAccountFilterHeaderContainer.addView(mAccountFilterHeader); + + mLoadingView = inflater.inflate(R.layout.phone_loading_contacts, mListView, false); + mShowAllContactsButton = inflater.inflate(R.layout.show_all_contact_button, mListView, + false); + mShowAllContactsButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View view) { + showAllContacts(); + } + }); + + mAdapter = new PhoneFavoriteMergedAdapter(getActivity(), mContactTileAdapter, + mAccountFilterHeaderContainer, mCallLogAdapter, mLoadingView, + mShowAllContactsButton); + + mListView.setAdapter(mAdapter); + + mListView.setOnScrollListener(mScrollListener); + mListView.setFastScrollEnabled(false); + mListView.setFastScrollAlwaysVisible(false); + + mEmptyView = (TextView) listLayout.findViewById(R.id.contact_tile_list_empty); + mEmptyView.setText(getString(R.string.listTotalAllContactsZero)); + mListView.setEmptyView(mEmptyView); + + return listLayout; + } + + + // TODO krelease: update the options menu when displaying the popup menu instead. We could + // possibly get rid of this method entirely. + private boolean isOptionsMenuChanged() { + return mOptionsMenuHasFrequents != hasFrequents(); + } + + // TODO krelease: Configure the menu items properly. Since the menu items show up as a PopupMenu + // rather than a normal actionbar menu, the initialization should be done there. + /* + @Override + public void onPrepareOptionsMenu(Menu menu) { + final MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents); + mOptionsMenuHasFrequents = hasFrequents(); + clearFrequents.setVisible(mOptionsMenuHasFrequents); + }*/ + + private boolean hasFrequents() { + return mContactTileAdapter.getNumFrequents() > 0; + } + + @Override + public void onStart() { + super.onStart(); + + final Activity activity = getActivity(); + + try { + ((OnPhoneFavoriteFragmentStartedListener) activity).onPhoneFavoriteFragmentStarted(); + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnPhoneFavoriteFragmentStartedListener"); + } + + try { + mActivityScrollListener = (OnListFragmentScrolledListener) activity; + } catch (ClassCastException e) { + throw new ClassCastException(activity.toString() + + " must implement OnListFragmentScrolledListener"); + } + + // Use initLoader() instead of restartLoader() to refraining unnecessary reload. + // This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will + // be called, on which we'll check if "all" contacts should be reloaded again or not. + getLoaderManager().initLoader(LOADER_ID_CONTACT_TILE, null, mContactTileLoaderListener); + } + + /** + * {@inheritDoc} + * + * This is only effective for elements provided by {@link #mContactTileAdapter}. + * {@link #mContactTileAdapter} has its own logic for click events. + */ + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + final int contactTileAdapterCount = mContactTileAdapter.getCount(); + if (position <= contactTileAdapterCount) { + Log.e(TAG, "onItemClick() event for unexpected position. " + + "The position " + position + " is before \"all\" section. Ignored."); + } + } + + /** + * Gets called when user click on the show all contacts button. + */ + private void showAllContacts() { + // TODO {klp} Use interface for the fragment to communicate with the activity + if (getActivity() instanceof DialtactsActivity) { + ((DialtactsActivity) getActivity()).showAllContactsFragment(); + } + } + + public void setListener(Listener listener) { + mListener = listener; + } + + // TODO krelease: Implement this + @Override + public void onVoicemailStatusFetched(Cursor statusCursor) { + } + + @Override + public void onCallsFetched(Cursor cursor) { + mCallLogAdapter.setLoading(false); + mCallLogAdapter.changeCursor(cursor); + mAdapter.notifyDataSetChanged(); + } + + // TODO krelease: Implement this + @Override + public void fetchCalls() { + } +} diff --git a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java index ba291a00f..0e5594ee5 100644 --- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java +++ b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java @@ -23,19 +23,15 @@ import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.FrameLayout; -import android.widget.SectionIndexer; -import com.android.contacts.common.list.ContactEntryListAdapter; -import com.android.contacts.common.list.ContactListItemView; -import com.android.contacts.common.list.ContactTileAdapter; import com.android.dialer.R; +import com.android.dialer.calllog.CallLogAdapter; /** - * An adapter that combines items from {@link com.android.contacts.common.list.ContactTileAdapter} and - * {@link com.android.contacts.common.list.ContactEntryListAdapter} into a single list. In between those two results, - * an account filter header will be inserted. + * An adapter that combines items from {@link com.android.contacts.common.list.ContactTileAdapter} + * and {@link com.android.dialer.calllog.CallLogAdapter} into a single list. */ -public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIndexer { +public class PhoneFavoriteMergedAdapter extends BaseAdapter { private class CustomDataSetObserver extends DataSetObserver { @Override @@ -44,80 +40,60 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn } } - private final ContactTileAdapter mContactTileAdapter; - private final ContactEntryListAdapter mContactEntryListAdapter; - private final View mAccountFilterHeaderContainer; + private static final String TAG = PhoneFavoriteMergedAdapter.class.getSimpleName(); + + private final PhoneFavoritesTileAdapter mContactTileAdapter; + private final CallLogAdapter mCallLogAdapter; private final View mLoadingView; + private final View mShowAllContactsButton; - private final int mItemPaddingLeft; - private final int mItemPaddingRight; + private final int mCallLogPadding; - // Make frequent header consistent with account filter header. - private final int mFrequentHeaderPaddingTop; + private final Context mContext; private final DataSetObserver mObserver; public PhoneFavoriteMergedAdapter(Context context, - ContactTileAdapter contactTileAdapter, + PhoneFavoritesTileAdapter contactTileAdapter, View accountFilterHeaderContainer, - ContactEntryListAdapter contactEntryListAdapter, - View loadingView) { - Resources resources = context.getResources(); - mItemPaddingLeft = resources.getDimensionPixelSize(R.dimen.detail_item_side_margin); - mItemPaddingRight = resources.getDimensionPixelSize(R.dimen.list_visible_scrollbar_padding); - mFrequentHeaderPaddingTop = resources.getDimensionPixelSize( - R.dimen.contact_browser_list_top_margin); + CallLogAdapter callLogAdapter, + View loadingView, + View showAllContactsButton) { + final Resources resources = context.getResources(); + mContext = context; + mCallLogPadding = resources.getDimensionPixelSize(R.dimen.recent_call_log_item_padding); mContactTileAdapter = contactTileAdapter; - mContactEntryListAdapter = contactEntryListAdapter; - - mAccountFilterHeaderContainer = accountFilterHeaderContainer; + mCallLogAdapter = callLogAdapter; mObserver = new CustomDataSetObserver(); mContactTileAdapter.registerDataSetObserver(mObserver); - mContactEntryListAdapter.registerDataSetObserver(mObserver); - mLoadingView = loadingView; + mShowAllContactsButton = showAllContactsButton; } @Override public boolean isEmpty() { - // Cannot use the super's method here because we add extra rows in getCount() to account - // for headers - return mContactTileAdapter.getCount() + mContactEntryListAdapter.getCount() == 0; + // This adapter will always contain at least the all contacts button + return false; } @Override public int getCount() { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount(); - if (mContactEntryListAdapter.isLoading()) { - // Hide "all" contacts during its being loaded. Instead show "loading" view. - // - // "+2" for mAccountFilterHeaderContainer and mLoadingView - return contactTileAdapterCount + 2; - } else { - // "+1" for mAccountFilterHeaderContainer - return contactTileAdapterCount + contactEntryListAdapterCount + 1; - } + return mContactTileAdapter.getCount() + mCallLogAdapter.getCount() + 1; } @Override public Object getItem(int position) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount(); - if (position < contactTileAdapterCount) { // For "tile" and "frequent" sections - return mContactTileAdapter.getItem(position); - } else if (position == contactTileAdapterCount) { // For "all" section's account header - return mAccountFilterHeaderContainer; - } else { // For "all" section - if (mContactEntryListAdapter.isLoading()) { // "All" section is being loaded. - return mLoadingView; - } else { - // "-1" for mAccountFilterHeaderContainer - final int localPosition = position - contactTileAdapterCount - 1; - return mContactTileAdapter.getItem(localPosition); + final int callLogAdapterCount = mCallLogAdapter.getCount(); + + if (callLogAdapterCount > 0) { + if (position < callLogAdapterCount) { + return mCallLogAdapter.getItem(position); } + // Set position to the position of the actual favorite contact in the favorites adapter + position = getAdjustedFavoritePosition(position, callLogAdapterCount); } + return mContactTileAdapter.getItem(position); } @Override @@ -127,122 +103,80 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn @Override public int getViewTypeCount() { - // "+2" for mAccountFilterHeaderContainer and mLoadingView - return (mContactTileAdapter.getViewTypeCount() - + mContactEntryListAdapter.getViewTypeCount() - + 2); + return (mContactTileAdapter.getViewTypeCount() + mCallLogAdapter.getViewTypeCount() + 1); } @Override public int getItemViewType(int position) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount(); - // There should be four kinds of types that are usually used, and one more exceptional - // type (IGNORE_ITEM_VIEW_TYPE), which sometimes comes from mContactTileAdapter. - // - // The four ordinary view types have the index equal to or more than 0, and less than - // mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount() + 2. - // (See also this class's getViewTypeCount()) - // - // We have those values for: - // - The view types mContactTileAdapter originally has - // - The view types mContactEntryListAdapter originally has - // - mAccountFilterHeaderContainer ("all" section's account header), and - // - mLoadingView - // - // Those types should not be mixed, so we have a different range for each kinds of types: - // - Types for mContactTileAdapter ("tile" and "frequent" sections) - // They should have the index, >=0 and =mContactTileAdapter.getViewTypeCount() and - // <(mContactTileAdapter.getViewTypeCount() + mContactEntryListAdapter.getViewTypeCount()) - // - // - Type for "all" section's account header - // It should have the exact index - // mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount() - // - // - Type for "loading" view used during "all" section is being loaded. - // It should have the exact index - // mContactTileAdapter.getViewTypeCount()+ mContactEntryListAdapter.getViewTypeCount() + 1 - // - // As an exception, IGNORE_ITEM_VIEW_TYPE (-1) will be remained as is, which will be used - // by framework's Adapter implementation and thus should be left as is. - if (position < contactTileAdapterCount) { // For "tile" and "frequent" sections - return mContactTileAdapter.getItemViewType(position); - } else if (position == contactTileAdapterCount) { // For "all" section's account header - return mContactTileAdapter.getViewTypeCount() - + mContactEntryListAdapter.getViewTypeCount(); - } else { // For "all" section - if (mContactEntryListAdapter.isLoading()) { // "All" section is being loaded. - return mContactTileAdapter.getViewTypeCount() - + mContactEntryListAdapter.getViewTypeCount() + 1; - } else { - // "-1" for mAccountFilterHeaderContainer - final int localPosition = position - contactTileAdapterCount - 1; - final int type = mContactEntryListAdapter.getItemViewType(localPosition); - // IGNORE_ITEM_VIEW_TYPE must be handled differently. - return (type < 0) ? type : type + mContactTileAdapter.getViewTypeCount(); - } + final int callLogAdapterCount = mCallLogAdapter.getCount(); + + if (position < callLogAdapterCount) { + // View type of the call log adapter is the last view type of the contact tile adapter + // + 1 + return mContactTileAdapter.getViewTypeCount(); + } else if (position < getCount() - 1) { + return mContactTileAdapter.getItemViewType( + getAdjustedFavoritePosition(position, callLogAdapterCount)); + } else { + // View type of the show all contact button is the last view type of the contact tile + // adapter + 2 + return mContactTileAdapter.getViewTypeCount() + 1; } } @Override public View getView(int position, View convertView, ViewGroup parent) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount(); + final int callLogAdapterCount = mCallLogAdapter.getCount(); + + if (position == getCount() - 1) { + return mShowAllContactsButton; + } - // Obtain a View relevant for that position, and adjust its horizontal padding. Each - // View has different implementation, so we use different way to control those padding. - if (position < contactTileAdapterCount) { // For "tile" and "frequent" sections - final View view = mContactTileAdapter.getView(position, convertView, parent); - final int frequentHeaderPosition = mContactTileAdapter.getFrequentHeaderPosition(); - if (position < frequentHeaderPosition) { // "starred" contacts - // No padding adjustment. - } else if (position == frequentHeaderPosition) { - view.setPadding(mItemPaddingLeft, mFrequentHeaderPaddingTop, - mItemPaddingRight, view.getPaddingBottom()); - } else { - // Views for "frequent" contacts use FrameLayout's margins instead of padding. - final FrameLayout frameLayout = (FrameLayout) view; - final View child = frameLayout.getChildAt(0); - FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + if (callLogAdapterCount > 0) { + if (position == 0) { + final FrameLayout wrapper; + if (convertView == null) { + wrapper = new FrameLayout(mContext); + } else { + wrapper = (FrameLayout) convertView; + } + + // Special case wrapper view for the most recent call log item. This allows + // us to create a card-like effect for the more recent call log item in + // the PhoneFavoriteMergedAdapter, but keep the original look of the item in + // the CallLogAdapter. + final View view = mCallLogAdapter.getView(position, convertView == null ? + null : wrapper.getChildAt(0), parent); + wrapper.removeAllViews(); + view.setBackgroundResource(R.drawable.dialer_recent_card_bg); + + final FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT); - params.setMargins(mItemPaddingLeft, 0, mItemPaddingRight, 0); - child.setLayoutParams(params); - } - return view; - } else if (position == contactTileAdapterCount) { // For "all" section's account header - mAccountFilterHeaderContainer.setPadding(mItemPaddingLeft, - mAccountFilterHeaderContainer.getPaddingTop(), - mItemPaddingRight, - mAccountFilterHeaderContainer.getPaddingBottom()); - // Show a single "No Contacts" label under the "all" section account header - // if no contacts are displayed. - mAccountFilterHeaderContainer.findViewById( - R.id.contact_list_all_empty).setVisibility( - contactEntryListAdapterCount == 0 ? View.VISIBLE : View.GONE); - return mAccountFilterHeaderContainer; - } else { // For "all" section - if (mContactEntryListAdapter.isLoading()) { // "All" section is being loaded. - mLoadingView.setPadding(mItemPaddingLeft, - mLoadingView.getPaddingTop(), - mItemPaddingRight, - mLoadingView.getPaddingBottom()); - return mLoadingView; - } else { - // "-1" for mAccountFilterHeaderContainer - final int localPosition = position - contactTileAdapterCount - 1; - final ContactListItemView itemView = (ContactListItemView) - mContactEntryListAdapter.getView(localPosition, convertView, null); - itemView.setPadding(mItemPaddingLeft, itemView.getPaddingTop(), - mItemPaddingRight, itemView.getPaddingBottom()); - itemView.setSelectionBoundsHorizontalMargin(mItemPaddingLeft, mItemPaddingRight); - return itemView; + params.setMarginsRelative(mCallLogPadding, mCallLogPadding, mCallLogPadding, + mCallLogPadding); + view.setLayoutParams(params); + wrapper.addView(view); + + return wrapper; } + // Set position to the position of the actual favorite contact in the + // favorites adapter + position = getAdjustedFavoritePosition(position, callLogAdapterCount); + } + + // Favorites section + final View view = mContactTileAdapter.getView(position, convertView, parent); + if (position >= mContactTileAdapter.getMaxTiledRows()) { + final FrameLayout frameLayout = (FrameLayout) view; + final View child = frameLayout.getChildAt(0); + FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT); + child.setLayoutParams(params); } + return view; } @Override @@ -250,58 +184,21 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter implements SectionIn // If "all" section is being loaded we'll show mLoadingView, which is not enabled. // Otherwise check the all the other components in the ListView and return appropriate // result. - return !mContactEntryListAdapter.isLoading() - && (mContactTileAdapter.areAllItemsEnabled() - && mAccountFilterHeaderContainer.isEnabled() - && mContactEntryListAdapter.areAllItemsEnabled()); + return mCallLogAdapter.areAllItemsEnabled() && mContactTileAdapter.areAllItemsEnabled(); } @Override public boolean isEnabled(int position) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int contactEntryListAdapterCount = mContactEntryListAdapter.getCount(); - if (position < contactTileAdapterCount) { // For "tile" and "frequent" sections - return mContactTileAdapter.isEnabled(position); - } else if (position == contactTileAdapterCount) { // For "all" section's account header - // This will be handled by View's onClick event instead of ListView's onItemClick event. - return false; - } else { // For "all" section - if (mContactEntryListAdapter.isLoading()) { // "All" section is being loaded. - return false; - } else { - // "-1" for mAccountFilterHeaderContainer - final int localPosition = position - contactTileAdapterCount - 1; - return mContactEntryListAdapter.isEnabled(localPosition); - } + final int callLogAdapterCount = mCallLogAdapter.getCount(); + if (position < callLogAdapterCount) { + return mCallLogAdapter.isEnabled(position); + } else { // For favorites section + return mContactTileAdapter.isEnabled( + getAdjustedFavoritePosition(position, callLogAdapterCount)); } } - @Override - public int getPositionForSection(int sectionIndex) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - final int localPosition = mContactEntryListAdapter.getPositionForSection(sectionIndex); - return contactTileAdapterCount + 1 + localPosition; - } - - @Override - public int getSectionForPosition(int position) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - if (position <= contactTileAdapterCount) { - return 0; - } else { - // "-1" for mAccountFilterHeaderContainer - final int localPosition = position - contactTileAdapterCount - 1; - return mContactEntryListAdapter.getSectionForPosition(localPosition); - } - } - - @Override - public Object[] getSections() { - return mContactEntryListAdapter.getSections(); - } - - public boolean shouldShowFirstScroller(int firstVisibleItem) { - final int contactTileAdapterCount = mContactTileAdapter.getCount(); - return firstVisibleItem > contactTileAdapterCount; + private int getAdjustedFavoritePosition(int position, int callLogAdapterCount) { + return position - callLogAdapterCount; } } -- cgit v1.2.3