(Re)introducing ContactEntryListConfiguration

Change-Id: Ibddd2d9e76dc2a1bf8259b1f7768d883437b1a5e
diff --git a/src/com/android/contacts/ContactsListActivity.java b/src/com/android/contacts/ContactsListActivity.java
index 5cf8bd5..ccbe0ac 100644
--- a/src/com/android/contacts/ContactsListActivity.java
+++ b/src/com/android/contacts/ContactsListActivity.java
@@ -17,6 +17,8 @@
 package com.android.contacts;
 
 import com.android.contacts.TextHighlightingAnimation.TextWithHighlighting;
+import com.android.contacts.list.ContactEntryListAdapter;
+import com.android.contacts.list.ContactEntryListConfiguration;
 import com.android.contacts.list.ContactItemListAdapter;
 import com.android.contacts.list.ContactsIntentResolver;
 import com.android.contacts.model.ContactsSource;
@@ -101,6 +103,7 @@
 import android.view.View.OnTouchListener;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsListView;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
@@ -108,6 +111,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
+import android.widget.AbsListView.OnScrollListener;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -120,7 +124,7 @@
 @SuppressWarnings("deprecation")
 public class ContactsListActivity extends ListActivity implements View.OnCreateContextMenuListener,
         View.OnClickListener, View.OnKeyListener, TextWatcher, TextView.OnEditorActionListener,
-        OnFocusChangeListener, OnTouchListener {
+        OnFocusChangeListener, OnTouchListener, OnScrollListener {
 
     private static final String TAG = "ContactsListActivity";
 
@@ -365,7 +369,7 @@
 
     static final String KEY_PICKER_MODE = "picker_mode";
 
-    public ContactItemListAdapter mAdapter;
+    public ContactEntryListAdapter mAdapter;
     public ContactListEmptyView mEmptyView;
 
     public int mMode = MODE_DEFAULT;
@@ -502,10 +506,11 @@
         }
     };
 
-    private ContactsIntentResolver mConfig;
+    private ContactsIntentResolver mIntentResolver;
+    private ContactEntryListConfiguration mConfig;
 
     public ContactsListActivity() {
-        mConfig = new ContactsIntentResolver(this);
+        mIntentResolver = new ContactsIntentResolver(this);
     }
 
     /**
@@ -535,36 +540,38 @@
     }
 
     protected void resolveIntent(final Intent intent) {
-        mConfig.setIntent(intent);
+        mIntentResolver.setIntent(intent);
 
-        if (!mConfig.isValid()) {           // Invalid intent
+        if (!mIntentResolver.isValid()) {           // Invalid intent
             setResult(RESULT_CANCELED);
             finish();
             return;
         }
 
-        Intent redirect = mConfig.getRedirectIntent();
+        Intent redirect = mIntentResolver.getRedirectIntent();
         if (redirect != null) {             // Need to start a different activity
             startActivity(redirect);
             finish();
             return;
         }
 
-        setTitle(mConfig.getActivityTitle());
+        setTitle(mIntentResolver.getActivityTitle());
+
+        mConfig = mIntentResolver.getConfiguration();
 
         // This is strictly temporary. Its purpose is to allow us to refactor this class in
         // small increments.  We should expect all of these modes to go away.
-        mMode = mConfig.mMode;
-        mGroupName = mConfig.mGroupName;
-        mQueryMode = mConfig.mQueryMode;
-        mSearchMode = mConfig.mSearchMode;
-        mShowSearchSnippets = mConfig.mShowSearchSnippets;
-        mInitialFilter = mConfig.mInitialFilter;
-        mDisplayOnlyPhones = mConfig.mDisplayOnlyPhones;
-        mShortcutAction = mConfig.mShortcutAction;
-        mSearchResultsMode = mConfig.mSearchResultsMode;
-        mShowNumberOfContacts = mConfig.mShowNumberOfContacts;
-        mGroupName = mConfig.mGroupName;
+        mMode = mIntentResolver.mMode;
+        mGroupName = mIntentResolver.mGroupName;
+        mQueryMode = mIntentResolver.mQueryMode;
+        mSearchMode = mIntentResolver.mSearchMode;
+        mShowSearchSnippets = mIntentResolver.mShowSearchSnippets;
+        mInitialFilter = mIntentResolver.mInitialFilter;
+        mDisplayOnlyPhones = mIntentResolver.mDisplayOnlyPhones;
+        mShortcutAction = mIntentResolver.mShortcutAction;
+        mSearchResultsMode = mIntentResolver.mSearchResultsMode;
+        mShowNumberOfContacts = mIntentResolver.mShowNumberOfContacts;
+        mGroupName = mIntentResolver.mGroupName;
     }
 
     public void initContentView() {
@@ -591,7 +598,8 @@
     }
 
     protected ContactItemListAdapter createListAdapter() {
-        return new ContactItemListAdapter(this);
+        // TODO there should be no need to cast
+        return (ContactItemListAdapter)mConfig.createListAdapter();
     }
 
     /**
@@ -626,7 +634,7 @@
         mAdapter = adapter;
         setListAdapter(mAdapter);
 
-        if (list instanceof PinnedHeaderListView && mAdapter.getDisplaySectionHeadersEnabled()) {
+        if (list instanceof PinnedHeaderListView && mConfig.isSectionHeaderDisplayEnabled()) {
             mPinnedHeaderBackgroundColor =
                     getResources().getColor(R.color.pinned_header_background);
             PinnedHeaderListView pinnedHeaderList = (PinnedHeaderListView)list;
@@ -634,7 +642,7 @@
             pinnedHeaderList.setPinnedHeaderView(pinnedHeader);
         }
 
-        list.setOnScrollListener(mAdapter);
+        list.setOnScrollListener(this);
         list.setOnKeyListener(this);
         list.setOnFocusChangeListener(this);
         list.setOnTouchListener(this);
@@ -643,6 +651,30 @@
         list.setSaveEnabled(false);
     }
 
+    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+            int totalItemCount) {
+        if (view instanceof PinnedHeaderListView) {
+            ((PinnedHeaderListView)view).configureHeaderView(firstVisibleItem);
+        }
+    }
+
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+        if (mHighlightWhenScrolling) {
+            if (scrollState != OnScrollListener.SCROLL_STATE_IDLE) {
+                mHighlightingAnimation.startHighlighting();
+            } else {
+                mHighlightingAnimation.stopHighlighting();
+            }
+        }
+
+        if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
+            mPhotoLoader.pause();
+        } else if (mConfig.isPhotoLoaderEnabled()) {
+            mPhotoLoader.resume();
+        }
+    }
+
+
     /**
      * Configures search UI.
      */
@@ -1484,7 +1516,8 @@
     }
 
     protected void onListItemClick(int position, long id) {
-        if (mSearchMode && mAdapter.isSearchAllContactsItemPosition(position)) {
+        if (mSearchMode &&
+                ((ContactItemListAdapter)(mAdapter)).isSearchAllContactsItemPosition(position)) {
             doSearch();
         } else if (mMode == MODE_INSERT_OR_EDIT_CONTACT || mMode == MODE_QUERY_PICK_TO_EDIT) {
             Intent intent;
@@ -1994,7 +2027,7 @@
             baseUri = Contacts.CONTENT_URI;
         }
 
-        if (mAdapter.getDisplaySectionHeadersEnabled()) {
+        if (mConfig.isSectionHeaderDisplayEnabled()) {
             return buildSectionIndexerUri(baseUri);
         } else {
             return baseUri;
@@ -2044,7 +2077,8 @@
             mEmptyView.hide();
         }
 
-        mAdapter.setLoading(true);
+        // TODO reintroduce the loading state handling
+//        mAdapter.setLoading(true);
 
         // Cancel any pending queries
         mQueryHandler.cancelOperation(QUERY_TOKEN);
diff --git a/src/com/android/contacts/list/ContactEntryListAdapter.java b/src/com/android/contacts/list/ContactEntryListAdapter.java
new file mode 100644
index 0000000..6a45a87
--- /dev/null
+++ b/src/com/android/contacts/list/ContactEntryListAdapter.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 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.contacts.list;
+
+import android.content.Context;
+import android.widget.CursorAdapter;
+
+/**
+ * Common base class for various contact-related lists, e.g. contact list, phone number list
+ * etc.
+ */
+public abstract class ContactEntryListAdapter extends CursorAdapter {
+
+    public ContactEntryListAdapter(Context context) {
+        super(context, null, false);
+    }
+
+    /*
+     * TODO change this method when loaders are introduced.
+     */
+    @Override
+    @Deprecated
+    public void onContentChanged() {
+        super.onContentChanged();
+    }
+}
diff --git a/src/com/android/contacts/list/ContactEntryListConfiguration.java b/src/com/android/contacts/list/ContactEntryListConfiguration.java
new file mode 100644
index 0000000..6caef33
--- /dev/null
+++ b/src/com/android/contacts/list/ContactEntryListConfiguration.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2010 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.contacts.list;
+
+import android.content.Context;
+import android.widget.ListAdapter;
+
+/**
+ * Common base class for configurations of various contact-related lists, e.g.
+ * contact list, phone number list etc.
+ */
+public abstract class ContactEntryListConfiguration {
+
+    private final Context mContext;
+    private boolean mSectionHeaderDisplayEnabled;
+    private boolean mPhotoLoaderEnabled;
+
+    public ContactEntryListConfiguration(Context context) {
+        this.mContext = context;
+    }
+
+    public Context getContext() {
+        return mContext;
+    }
+
+    public abstract ListAdapter createListAdapter();
+
+    public void setSectionHeaderDisplayEnabled(boolean flag) {
+        mSectionHeaderDisplayEnabled = flag;
+    }
+
+    public boolean isSectionHeaderDisplayEnabled() {
+        return mSectionHeaderDisplayEnabled;
+    }
+
+    public void setPhotoLoaderEnabled(boolean flag) {
+        mPhotoLoaderEnabled = flag;
+    }
+
+    public boolean isPhotoLoaderEnabled() {
+        return mPhotoLoaderEnabled;
+    }
+}
diff --git a/src/com/android/contacts/list/ContactEntryListController.java b/src/com/android/contacts/list/ContactEntryListController.java
new file mode 100644
index 0000000..ca8c176
--- /dev/null
+++ b/src/com/android/contacts/list/ContactEntryListController.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 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.contacts.list;
+
+
+/**
+ * Common base class for various contact-related lists, e.g. contact list, phone number list
+ * etc.
+ */
+public abstract class ContactEntryListController {
+
+}
diff --git a/src/com/android/contacts/list/ContactItemListAdapter.java b/src/com/android/contacts/list/ContactItemListAdapter.java
index a968ef0..7437d6a 100644
--- a/src/com/android/contacts/list/ContactItemListAdapter.java
+++ b/src/com/android/contacts/list/ContactItemListAdapter.java
@@ -44,18 +44,15 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.CursorAdapter;
 import android.widget.Filter;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.QuickContactBadge;
 import android.widget.SectionIndexer;
 import android.widget.TextView;
-import android.widget.AbsListView.OnScrollListener;
 
-public class ContactItemListAdapter extends CursorAdapter
-        implements SectionIndexer, OnScrollListener, PinnedHeaderListView.PinnedHeaderAdapter {
+public class ContactItemListAdapter extends ContactEntryListAdapter
+        implements SectionIndexer, PinnedHeaderListView.PinnedHeaderAdapter {
 
     private final ContactsListActivity contactsListActivity;
     private SectionIndexer mIndexer;
@@ -65,27 +62,13 @@
     private boolean mDisplayCallButton = false;
     protected boolean mDisplayAdditionalData = true;
     private int mFrequentSeparatorPos = ListView.INVALID_POSITION;
-    private boolean mDisplaySectionHeaders = true;
+    private boolean mSectionHeaderDisplayEnabled;
 
     public ContactItemListAdapter(ContactsListActivity contactsListActivity) {
-        super(contactsListActivity, null, false);
+        super(contactsListActivity);
         this.contactsListActivity = contactsListActivity;
 
         mUnknownNameText = contactsListActivity.getText(android.R.string.unknownName);
-        switch (contactsListActivity.mMode) {
-            case ContactsListActivity.MODE_LEGACY_PICK_POSTAL:
-            case ContactsListActivity.MODE_PICK_POSTAL:
-            case ContactsListActivity.MODE_LEGACY_PICK_PHONE:
-            case ContactsListActivity.MODE_PICK_PHONE:
-            case ContactsListActivity.MODE_STREQUENT:
-            case ContactsListActivity.MODE_FREQUENT:
-                mDisplaySectionHeaders = false;
-                break;
-        }
-
-        if (contactsListActivity.mSearchMode) {
-            mDisplaySectionHeaders = false;
-        }
 
         // Do not display the second line of text if in a specific SEARCH query mode, usually for
         // matching a specific E-mail or phone number. Any contact details
@@ -105,15 +88,18 @@
                 ContactsListActivity.MODE_MASK_SHOW_CALL_BUTTON) {
             mDisplayCallButton = true;
         }
-
-        if ((contactsListActivity.mMode & ContactsListActivity.MODE_MASK_SHOW_PHOTOS) ==
-                ContactsListActivity.MODE_MASK_SHOW_PHOTOS) {
-            mDisplayPhotos = true;
-        }
     }
 
-    public boolean getDisplaySectionHeadersEnabled() {
-        return mDisplaySectionHeaders;
+    public void setSectionHeaderDisplayEnabled(boolean flag) {
+        mSectionHeaderDisplayEnabled = flag;
+    }
+
+    public boolean isSectionHeaderDisplayEnabled() {
+        return mSectionHeaderDisplayEnabled;
+    }
+
+    public void setDisplayPhotos(boolean flag) {
+        mDisplayPhotos = flag;
     }
 
     /**
@@ -227,7 +213,7 @@
             v = convertView;
         }
         bindView(v, mContext, mCursor);
-        bindSectionHeader(v, realPosition, mDisplaySectionHeaders);
+        bindSectionHeader(v, realPosition, mSectionHeaderDisplayEnabled);
         return v;
     }
 
@@ -754,29 +740,6 @@
         return super.getItemId(realPosition);
     }
 
-    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
-            int totalItemCount) {
-        if (view instanceof PinnedHeaderListView) {
-            ((PinnedHeaderListView)view).configureHeaderView(firstVisibleItem);
-        }
-    }
-
-    public void onScrollStateChanged(AbsListView view, int scrollState) {
-        if (contactsListActivity.mHighlightWhenScrolling) {
-            if (scrollState != OnScrollListener.SCROLL_STATE_IDLE) {
-                contactsListActivity.mHighlightingAnimation.startHighlighting();
-            } else {
-                contactsListActivity.mHighlightingAnimation.stopHighlighting();
-            }
-        }
-
-        if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
-            contactsListActivity.mPhotoLoader.pause();
-        } else if (mDisplayPhotos) {
-            contactsListActivity.mPhotoLoader.resume();
-        }
-    }
-
     /**
      * Computes the state of the pinned header.  It can be invisible, fully
      * visible or partially pushed up out of the view.
diff --git a/src/com/android/contacts/list/ContactsIntentResolver.java b/src/com/android/contacts/list/ContactsIntentResolver.java
index d7469b4..4f06855 100644
--- a/src/com/android/contacts/list/ContactsIntentResolver.java
+++ b/src/com/android/contacts/list/ContactsIntentResolver.java
@@ -471,5 +471,30 @@
         return null;
     }
 
+    public ContactEntryListConfiguration getConfiguration() {
+        ContactEntryListConfiguration config;
+        switch (mMode) {
+            case MODE_LEGACY_PICK_POSTAL:
+            case MODE_PICK_POSTAL:
+            case MODE_LEGACY_PICK_PHONE:
+            case MODE_PICK_PHONE:
+            case MODE_STREQUENT:
+            case MODE_FREQUENT: {
+                config = new DefaultContactListConfiguration(mContext);
+                break;
+            }
+            default: {
+                config = new DefaultContactListConfiguration(mContext);
+                if (!mSearchMode) {
+                    config.setSectionHeaderDisplayEnabled(true);
+                }
+            }
+        }
 
+        if ((mMode & MODE_MASK_SHOW_PHOTOS) == MODE_MASK_SHOW_PHOTOS) {
+            config.setPhotoLoaderEnabled(true);
+        }
+
+        return config;
+    }
 }
diff --git a/src/com/android/contacts/list/DefaultContactListConfiguration.java b/src/com/android/contacts/list/DefaultContactListConfiguration.java
new file mode 100644
index 0000000..455d3e8
--- /dev/null
+++ b/src/com/android/contacts/list/DefaultContactListConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 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.contacts.list;
+
+import com.android.contacts.ContactsListActivity;
+
+import android.content.Context;
+import android.widget.ListAdapter;
+
+/**
+ * Configuration for the default contact list.
+ */
+public class DefaultContactListConfiguration extends ContactEntryListConfiguration {
+
+    public DefaultContactListConfiguration(Context context) {
+        super(context);
+    }
+
+    @Override
+    public ListAdapter createListAdapter() {
+        ContactItemListAdapter adapter =
+                new ContactItemListAdapter((ContactsListActivity)getContext());
+        adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
+        adapter.setDisplayPhotos(isPhotoLoaderEnabled());
+        return adapter;
+    }
+}