Add tabs to People app

- Move account filter into overflow menu
- Use action bar in tab and standard mode so the SearchView
is right aligned and part of the options menu instead of the
custom view in the action bar
- Make visibility of action bar home icon a style so the icon
can be hidden on the phone
- TODO: Make physical search button work on the phone so the
search box can be removed from the action bar
- TODO: Fix SearchView focus problems

Change-Id: I7b3ba49f80e1911fb4a096679a00560967584426
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index 1379e08..f537c9e 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -19,7 +19,10 @@
 import com.android.contacts.ContactSaveService;
 import com.android.contacts.ContactsActivity;
 import com.android.contacts.R;
+import com.android.contacts.calllog.CallLogFragment;
 import com.android.contacts.detail.ContactDetailFragment;
+import com.android.contacts.dialpad.DialpadFragment;
+import com.android.contacts.group.GroupBrowseListFragment;
 import com.android.contacts.interactions.ContactDeletionInteraction;
 import com.android.contacts.interactions.GroupDeletionDialogFragment;
 import com.android.contacts.interactions.GroupRenamingDialogFragment;
@@ -34,11 +37,13 @@
 import com.android.contacts.list.ContactsRequest;
 import com.android.contacts.list.ContactsUnavailableFragment;
 import com.android.contacts.list.CustomContactListFilterActivity;
+import com.android.contacts.list.DefaultContactBrowseListFragment;
 import com.android.contacts.list.DirectoryListLoader;
 import com.android.contacts.list.OnContactBrowserActionListener;
 import com.android.contacts.list.OnContactsUnavailableActionListener;
 import com.android.contacts.list.ProviderStatusLoader;
 import com.android.contacts.list.ProviderStatusLoader.ProviderStatusListener;
+import com.android.contacts.list.StrequentContactListFragment;
 import com.android.contacts.model.AccountTypeManager;
 import com.android.contacts.preference.ContactsPreferenceActivity;
 import com.android.contacts.util.AccountSelectionUtil;
@@ -47,12 +52,17 @@
 
 import android.accounts.Account;
 import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
 import android.app.Activity;
 import android.app.Dialog;
 import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
 import android.content.ActivityNotFoundException;
 import android.content.ContentValues;
 import android.content.Intent;
+import android.content.res.TypedArray;
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract;
@@ -68,6 +78,7 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.Window;
+import android.widget.SearchView;
 import android.widget.Toast;
 
 import java.util.ArrayList;
@@ -94,7 +105,6 @@
     private ContactsIntentResolver mIntentResolver;
     private ContactsRequest mRequest;
 
-    private boolean mHasActionBar;
     private ActionBarAdapter mActionBarAdapter;
 
     private boolean mSearchMode;
@@ -126,8 +136,14 @@
     private boolean mOptionsMenuContactsAvailable;
     private boolean mOptionsMenuGroupActionsEnabled;
 
+    private DefaultContactBrowseListFragment mContactsFragment;
+    private StrequentContactListFragment mFavoritesFragment;
+    private GroupBrowseListFragment mGroupsFragment;
+
     public PeopleActivity() {
         mIntentResolver = new ContactsIntentResolver(this);
+        // TODO: Get rid of the ContactListFilterController class because there aren't any
+        // dropdown filters anymore. Just store the selected filter as a member variable.
         mContactListFilterController = new ContactListFilterController(this);
         mContactListFilterController.addListener(this);
         mProviderStatusLoader = new ProviderStatusLoader(this);
@@ -201,6 +217,21 @@
 
         if (createContentView) {
             setContentView(R.layout.people_activity);
+
+            final FragmentManager fragmentManager = getFragmentManager();
+            mFavoritesFragment = (StrequentContactListFragment) fragmentManager
+                    .findFragmentById(R.id.favorites_fragment);
+            mContactsFragment = (DefaultContactBrowseListFragment) fragmentManager
+                    .findFragmentById(R.id.contacts_fragment);
+            mGroupsFragment = (GroupBrowseListFragment) fragmentManager
+                    .findFragmentById(R.id.groups_fragment);
+
+            // Hide all tabs (the current tab will later be reshown once a tab is selected)
+            final FragmentTransaction transaction = fragmentManager.beginTransaction();
+            transaction.hide(mFavoritesFragment);
+            transaction.hide(mContactsFragment);
+            transaction.hide(mGroupsFragment);
+            transaction.commit();
         }
 
         if (mRequest.getActionCode() == ContactsRequest.ACTION_VIEW_CONTACT
@@ -214,21 +245,66 @@
         }
 
         setTitle(mRequest.getActivityTitle());
+        ActionBar actionBar = getActionBar();
+        mActionBarAdapter = new ActionBarAdapter(this);
+        mActionBarAdapter.onCreate(savedState, mRequest, getActionBar());
+        mActionBarAdapter.setContactListFilterController(mContactListFilterController);
 
         if (createContentView) {
-            mHasActionBar = getWindow().hasFeature(Window.FEATURE_ACTION_BAR);
-            if (mHasActionBar) {
-                ActionBar actionBar = getActionBar();
+            actionBar.removeAllTabs();
+            Tab favoritesTab = actionBar.newTab();
+            favoritesTab.setText(getString(R.string.strequentList));
+            favoritesTab.setTabListener(new TabChangeListener(mFavoritesFragment));
+            actionBar.addTab(favoritesTab);
 
-                mActionBarAdapter = new ActionBarAdapter(this);
-                mActionBarAdapter.onCreate(savedState, mRequest, actionBar);
-                mActionBarAdapter.setContactListFilterController(mContactListFilterController);
-            }
+            Tab peopleTab = actionBar.newTab();
+            peopleTab.setText(getString(R.string.people));
+            peopleTab.setTabListener(new TabChangeListener(mContactsFragment));
+            actionBar.addTab(peopleTab);
+
+            Tab groupsTab = actionBar.newTab();
+            groupsTab.setText(getString(R.string.contactsGroupsLabel));
+            groupsTab.setTabListener(new TabChangeListener(mGroupsFragment));
+            actionBar.addTab(groupsTab);
+            actionBar.setDisplayShowTitleEnabled(true);
+
+            TypedArray a = obtainStyledAttributes(null, R.styleable.ActionBarHomeIcon);
+            boolean showHomeIcon = a.getBoolean(R.styleable.ActionBarHomeIcon_show_home_icon, true);
+            actionBar.setDisplayShowHomeEnabled(showHomeIcon);
+
+            invalidateOptionsMenu();
         }
 
         configureFragments(savedState == null);
     }
 
+    /**
+     * Tab change listener that is instantiated once for each tab. Handles showing/hiding fragments.
+     * TODO: Use ViewPager so that tabs can be swiped left and right. Figure out how to use the
+     * support library in our app.
+     */
+    private class TabChangeListener implements TabListener {
+        private final Fragment mFragment;
+
+        public TabChangeListener(Fragment fragment) {
+            mFragment = fragment;
+        }
+
+        @Override
+        public void onTabUnselected(Tab tab, FragmentTransaction ft) {
+            ft.hide(mFragment);
+        }
+
+        @Override
+        public void onTabSelected(Tab tab, FragmentTransaction ft) {
+            ft.show(mFragment);
+        }
+
+        @Override
+        public void onTabReselected(Tab tab, FragmentTransaction ft) {
+        }
+    }
+
     @Override
     protected void onPause() {
         if (mActionBarAdapter != null) {
@@ -259,12 +335,6 @@
         super.onStart();
     }
 
-    @Override
-    protected void onStop() {
-        mContactListFilterController.onStop();
-        super.onStop();
-    }
-
     private void configureFragments(boolean fromRequest) {
         if (fromRequest) {
             ContactListFilter filter = null;
@@ -303,7 +373,7 @@
             mListFragment.setContactsRequest(mRequest);
             configureListFragmentForRequest();
 
-        } else if (mHasActionBar) {
+        } else {
             mSearchMode = mActionBarAdapter.isSearchMode();
         }
 
@@ -348,9 +418,23 @@
      * Handler for action bar actions.
      */
     @Override
-    public void onAction() {
-        configureFragments(false /* from request */);
-        mListFragment.setQueryString(mActionBarAdapter.getQueryString(), true);
+    public void onAction(Action action) {
+        switch (action) {
+            case START_SEARCH_MODE:
+                // Bring the contact list fragment to the front.
+                FragmentTransaction ft = getFragmentManager().beginTransaction();
+                ft.show(mContactsFragment);
+                ft.commit();
+                break;
+            case STOP_SEARCH_MODE:
+            case CHANGE_SEARCH_QUERY:
+                // Refresh the contact list fragment.
+                configureFragments(false /* from request */);
+                mListFragment.setQueryString(mActionBarAdapter.getQueryString(), true);
+                break;
+            default:
+                throw new IllegalStateException("Unkonwn ActionBarAdapter action: " + action);
+        }
     }
 
     private void configureListFragmentForRequest() {
@@ -403,17 +487,13 @@
 
         if (mProviderStatus == ProviderStatus.STATUS_NORMAL) {
             contactsUnavailableView.setVisibility(View.GONE);
-            mainView.setVisibility(View.VISIBLE);
+            if (mainView != null) {
+                mainView.setVisibility(View.VISIBLE);
+            }
             if (mListFragment != null) {
                 mListFragment.setEnabled(true);
             }
-            if (mHasActionBar) {
-                mActionBarAdapter.setEnabled(true);
-            }
         } else {
-            if (mHasActionBar) {
-                mActionBarAdapter.setEnabled(false);
-            }
             if (mListFragment != null) {
                 mListFragment.setEnabled(false);
             }
@@ -429,7 +509,9 @@
                 mContactsUnavailableFragment.update();
             }
             contactsUnavailableView.setVisibility(View.VISIBLE);
-            mainView.setVisibility(View.INVISIBLE);
+            if (mainView != null) {
+                mainView.setVisibility(View.INVISIBLE);
+            }
         }
 
         invalidateOptionsMenu();
@@ -625,27 +707,28 @@
         if (!areContactsAvailable()) {
             return false;
         }
-
         super.onCreateOptionsMenu(menu);
 
         MenuInflater inflater = getMenuInflater();
-        if (mHasActionBar) {
-            inflater.inflate(R.menu.actions, menu);
+        inflater.inflate(R.menu.actions, menu);
+        // TODO: Figure out if R.menu.list or R.menu.search are necessary according to the overflow
+        // menus on the UX mocks.
+        MenuItem searchMenuItem = menu.findItem(R.id.menu_search);
+        if (searchMenuItem != null && searchMenuItem.getActionView() instanceof SearchView) {
+            SearchView searchView = (SearchView) searchMenuItem.getActionView();
+            searchView.setQueryHint(getString(R.string.hint_findContacts));
+            searchView.setIconifiedByDefault(false);
 
-            // Change add contact button to button with a custom view
-            final MenuItem addContact = menu.findItem(R.id.menu_add);
-            addContact.setActionView(mAddContactImageView);
-            return true;
-        } else if (mRequest.getActionCode() == ContactsRequest.ACTION_ALL_CONTACTS ||
-                mRequest.getActionCode() == ContactsRequest.ACTION_STREQUENT) {
-            inflater.inflate(R.menu.list, menu);
-            return true;
-        } else if (!mListFragment.isSearchMode()) {
-            inflater.inflate(R.menu.search, menu);
-            return true;
-        } else {
-            return false;
+            if (mActionBarAdapter != null) {
+                mActionBarAdapter.setSearchView(searchView);
+            }
         }
+
+        // TODO: Can remove this as a custom view because the account selector is in the editor now.
+        // Change add contact button to button with a custom view
+        final MenuItem addContact = menu.findItem(R.id.menu_add);
+        addContact.setActionView(mAddContactImageView);
+        return true;
     }
 
     @Override
@@ -723,6 +806,11 @@
                 startActivity(intent);
                 return true;
             }
+            case R.id.menu_contacts_filter: {
+                final Intent intent = new Intent(this, CustomContactListFilterActivity.class);
+                startActivityForResult(intent, SUBACTIVITY_CUSTOMIZE_FILTER);
+                return true;
+            }
             case R.id.menu_search: {
                 onSearchRequested();
                 return true;
@@ -865,12 +953,10 @@
                 final int unicodeChar = event.getUnicodeChar();
                 if (unicodeChar != 0 && !Character.isWhitespace(unicodeChar)) {
                     String query = new String(new int[]{ unicodeChar }, 0, 1);
-                    if (mHasActionBar) {
-                        if (!mActionBarAdapter.isSearchMode()) {
-                            mActionBarAdapter.setQueryString(query);
-                            mActionBarAdapter.setSearchMode(true);
-                            return true;
-                        }
+                    if (!mActionBarAdapter.isSearchMode()) {
+                        mActionBarAdapter.setQueryString(query);
+                        mActionBarAdapter.setSearchMode(true);
+                        return true;
                     } else if (!mRequest.isSearchMode()) {
                         if (!mSearchInitiated) {
                             mSearchInitiated = true;