Show sources / Hide sources UI in the view card.

Change-Id: Iee14c66c0b9b065403778c6b8e4cb1273a02ee65
diff --git a/src/com/android/contacts/ViewContactActivity.java b/src/com/android/contacts/ViewContactActivity.java
index 9b22b4b..1b2ee23 100644
--- a/src/com/android/contacts/ViewContactActivity.java
+++ b/src/com/android/contacts/ViewContactActivity.java
@@ -73,9 +73,14 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.view.animation.TranslateAnimation;
+import android.view.animation.Animation.AnimationListener;
 import android.widget.AdapterView;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
@@ -87,8 +92,8 @@
  */
 public class ViewContactActivity extends Activity
         implements View.OnCreateContextMenuListener, DialogInterface.OnClickListener,
-        AdapterView.OnItemClickListener, NotifyingAsyncQueryHandler.AsyncQueryListener {
-//        OnTabSelectionChangedListener {
+        AdapterView.OnItemClickListener, NotifyingAsyncQueryHandler.AsyncQueryListener,
+        OnTabSelectionChangedListener {
     private static final String TAG = "ViewContact";
 
     public static final String RAW_CONTACT_ID_EXTRA = "rawContactIdExtra";
@@ -98,18 +103,17 @@
     private static final int DIALOG_CONFIRM_DELETE = 1;
 
     private static final int REQUEST_JOIN_CONTACT = 1;
-    private static final int REQUEST_EDIT_CONTACT = 2;
 
     public static final int MENU_ITEM_MAKE_DEFAULT = 3;
 
+    private static final String SPLIT_MIMETYPE = "split_mimetype";
+
     protected Uri mLookupUri;
     private Uri mUri;
     private ContentResolver mResolver;
     private ViewAdapter mAdapter;
     private int mNumPhoneNumbers = 0;
 
-    private static final long ALL_CONTACTS_ID = -100;
-
     /**
      * A list of distinct contact IDs included in the current contact.
      */
@@ -123,6 +127,7 @@
     /* package */ ArrayList<ViewEntry> mOrganizationEntries = new ArrayList<ViewEntry>();
     /* package */ ArrayList<ViewEntry> mGroupEntries = new ArrayList<ViewEntry>();
     /* package */ ArrayList<ViewEntry> mOtherEntries = new ArrayList<ViewEntry>();
+    /* package */ ArrayList<ViewEntry> mSplitEntry = new ArrayList<ViewEntry>();
     /* package */ ArrayList<ArrayList<ViewEntry>> mSections = new ArrayList<ArrayList<ViewEntry>>();
 
     private Cursor mCursor;
@@ -130,6 +135,8 @@
     private SparseArray<Long> mTabRawContactIdMap;
     protected ScrollingTabWidget mTabWidget;
     protected ContactHeaderWidget mContactHeaderWidget;
+    protected View mBelowHeader;
+    protected View mBufferView;
     private NotifyingAsyncQueryHandler mHandler;
 
     protected LayoutInflater mInflater;
@@ -174,6 +181,8 @@
     private boolean mShowSmsLinksForAllPhones;
     private ArrayList<Entity> mEntities = null;
 
+    private boolean mTabsVisible;
+
     @Override
     protected void onCreate(Bundle icicle) {
         super.onCreate(icicle);
@@ -201,8 +210,11 @@
         });
 
         mTabWidget = (ScrollingTabWidget) findViewById(R.id.tab_widget);
-//        mTabWidget.setTabSelectionListener(this);
+        mTabWidget.setTabSelectionListener(this);
         mTabWidget.setVisibility(View.GONE);
+        mTabsVisible = false;
+
+        mBelowHeader = findViewById(R.id.below_header);
 
         mTabRawContactIdMap = new SparseArray<Long>();
 
@@ -228,6 +240,7 @@
         mSections.add(mOrganizationEntries);
         mSections.add(mGroupEntries);
         mSections.add(mOtherEntries);
+        mSections.add(mSplitEntry);
 
         //TODO Read this value from a preference
         mShowSmsLinksForAllPhones = true;
@@ -236,6 +249,7 @@
     @Override
     protected void onResume() {
         super.onResume();
+        showTabs(false, false /*no animation*/);
         startEntityQuery();
     }
 
@@ -252,20 +266,6 @@
     }
 
     @Override
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
-        super.onRestoreInstanceState(savedInstanceState);
-//        mSelectedRawContactId = savedInstanceState.getLong(SELECTED_RAW_CONTACT_ID_KEY);
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-	if (mSelectedRawContactId != null) {
-            outState.putLong(SELECTED_RAW_CONTACT_ID_KEY, mSelectedRawContactId);
-        }
-    }
-
-    @Override
     protected Dialog onCreateDialog(int id) {
         switch (id) {
             case DIALOG_CONFIRM_DELETE:
@@ -288,101 +288,165 @@
      * Override this method if you want to additional tabs and/or different
      * tabs for your activity.
      */
-//    protected void bindTabs() {
-//        if (mEntities.size() > 1) {
-//            addAllTab();
-//        }
-//
-//        final Sources sources = Sources.getInstance(this);
-//
-//        for (Entity entity : mEntities) {
-//            final String accountType = entity.getEntityValues().
-//                    getAsString(RawContacts.ACCOUNT_TYPE);
-//            final Long rawContactId = entity.getEntityValues().
-//                    getAsLong(RawContacts._ID);
-//
-//            // TODO: ensure inflation on background task so we don't block UI thread here
-//            final ContactsSource source = sources.getInflatedSource(accountType,
-//                    ContactsSource.LEVEL_SUMMARY);
-//            addTab(rawContactId, ContactsUtils.createTabIndicatorView(mTabWidget.getTabParent(),
-//                    source));
-//        }
-//    }
-//
-//    /**
-//     * Add a tab to be displayed in the {@link ScrollingTabWidget}.
-//     *
-//     * @param rawContactId The contact id associated with the tab.
-//     * @param view A view to use as the tab indicator.
-//     */
-//    protected void addTab(long rawContactId, View view) {
-//        mTabRawContactIdMap.put(mTabWidget.getTabCount(), rawContactId);
-//        mTabWidget.addTab(view);
-//    }
-//
-//
-//    protected void clearCurrentTabs() {
-//        mTabRawContactIdMap.clear();
-//        mTabWidget.removeAllTabs();
-//    }
-//
-//    protected void selectInitialTab() {
-//        int selectedTabIndex = 0;
-//
-//        if (mSelectedRawContactId != null) {
-//            selectedTabIndex = getTabIndexForRawContactId(mSelectedRawContactId);
-//            if (selectedTabIndex == -1) {
-//                // If there was no matching tab, just select the first;
-//                selectedTabIndex = 0;
-//            }
-//        }
-//
-////        mTabWidget.setCurrentTab(selectedTabIndex);
-//        onTabSelectionChanged(selectedTabIndex, false);
-////        mTabWidget.setVisibility(View.VISIBLE);
-////        mTabWidget.postInvalidate();
-//    }
-//
-//    private void addAllTab() {
-//        View allTabIndicator = mInflater.inflate(R.layout.all_tab_indicator,
-//                mTabWidget.getTabParent(), false);
-//        allTabIndicator.getBackground().setDither(true);
-//        addTab(ALL_CONTACTS_ID, allTabIndicator);
-//    }
-//
-//    public void onTabSelectionChanged(int tabIndex, boolean clicked) {
-//        Long rawContactId = getTabRawContactId(tabIndex);
-//        if (rawContactId != null) {
-//            mSelectedRawContactId = rawContactId;
-//            bindData();
-//        }
-//    }
-//
-//    /**
-//     * Return the RawContact id associated with the tab at an index.
-//     *
-//     * @param index The index of the tab in question.
-//     * @return The contactId associated with the tab at the specified index.
-//     */
-//    protected Long getTabRawContactId(int index) {
-//        return mTabRawContactIdMap.get(index);
-//    }
-//
-//    /**
-//     * Return the tab index associated with the RawContact id.
-//     *
-//     * @param index The index of the tab in question.
-//     * @return The contactId associated with the tab at the specified index.
-//     */
-//    protected int getTabIndexForRawContactId(long rawContactId) {
-//        int numTabs = mTabRawContactIdMap.size();
-//        for (int i=0; i < numTabs; i++) {
-//            if (mTabRawContactIdMap.get(i) == rawContactId) {
-//                return i;
-//            }
-//        }
-//        return -1;
-//    }
+    protected void bindTabs() {
+        final Sources sources = Sources.getInstance(this);
+
+        for (Entity entity : mEntities) {
+            final String accountType = entity.getEntityValues().
+                    getAsString(RawContacts.ACCOUNT_TYPE);
+            final Long rawContactId = entity.getEntityValues().
+                    getAsLong(RawContacts._ID);
+
+            // TODO: ensure inflation on background task so we don't block UI thread here
+            final ContactsSource source = sources.getInflatedSource(accountType,
+                    ContactsSource.LEVEL_SUMMARY);
+            addTab(rawContactId, ContactsUtils.createTabIndicatorView(mTabWidget.getTabParent(),
+                    source));
+        }
+    }
+
+    /**
+     * Add a tab to be displayed in the {@link ScrollingTabWidget}.
+     *
+     * @param rawContactId The contact id associated with the tab.
+     * @param view A view to use as the tab indicator.
+     */
+    protected void addTab(long rawContactId, View view) {
+        mTabRawContactIdMap.put(mTabWidget.getTabCount(), rawContactId);
+        mTabWidget.addTab(view);
+    }
+
+
+    protected void clearCurrentTabs() {
+        mTabRawContactIdMap.clear();
+        mTabWidget.removeAllTabs();
+    }
+
+    protected void selectInitialTab() {
+        int selectedTabIndex = 0;
+
+        if (mSelectedRawContactId != null) {
+            selectedTabIndex = getTabIndexForRawContactId(mSelectedRawContactId);
+            if (selectedTabIndex == -1) {
+                // If there was no matching tab, just select the first;
+                selectedTabIndex = 0;
+            }
+        }
+
+        mTabWidget.setCurrentTab(selectedTabIndex);
+        onTabSelectionChanged(selectedTabIndex, false);
+    }
+
+    public void onTabSelectionChanged(int tabIndex, boolean clicked) {
+        Long rawContactId = getTabRawContactId(tabIndex);
+        if (rawContactId != null) {
+            mSelectedRawContactId = rawContactId;
+            bindData();
+        }
+    }
+
+    /**
+     * Return the RawContact id associated with the tab at an index.
+     *
+     * @param index The index of the tab in question.
+     * @return The contactId associated with the tab at the specified index.
+     */
+    protected Long getTabRawContactId(int index) {
+        return mTabRawContactIdMap.get(index);
+    }
+
+    /**
+     * Return the tab index associated with the RawContact id.
+     *
+     * @param index The index of the tab in question.
+     * @return The contactId associated with the tab at the specified index.
+     */
+    protected int getTabIndexForRawContactId(long rawContactId) {
+        int numTabs = mTabRawContactIdMap.size();
+        for (int i=0; i < numTabs; i++) {
+            if (mTabRawContactIdMap.get(i) == rawContactId) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    protected void showTabs(boolean show, boolean animate) {
+        if (mTabsVisible == show) {
+            return;
+        }
+
+        float tabHeight = getResources().getDimension(R.dimen.tab_height);
+        if (show) {
+            if (animate) {
+                TranslateAnimation showAnimation = new TranslateAnimation(
+                        Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
+                        Animation.ABSOLUTE, -tabHeight, Animation.ABSOLUTE, 0);
+                showAnimation.setDuration(getResources().getInteger(
+                        android.R.integer.config_longAnimTime));
+
+                showAnimation.setAnimationListener(new AnimationListener() {
+                    public void onAnimationEnd(Animation animation) {
+                        selectInitialTab();
+                        bindData();
+                    }
+
+                    public void onAnimationRepeat(Animation animation) {
+                    }
+
+                    public void onAnimationStart(Animation animation) {
+                    }
+
+                });
+
+                mBelowHeader.startAnimation(showAnimation);
+            }
+            mTabWidget.setVisibility(View.VISIBLE);
+            mTabsVisible = true;
+            clearCurrentTabs();
+            bindTabs();
+            if (!animate) {
+                selectInitialTab();
+                bindData();
+            }
+        } else {
+            if (animate) {
+                TranslateAnimation hideTabsAnimation = new TranslateAnimation(
+                        Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
+                        Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -tabHeight);
+                hideTabsAnimation.setDuration(getResources().getInteger(
+                        android.R.integer.config_longAnimTime));
+                hideTabsAnimation.setAnimationListener(new AnimationListener() {
+                    public void onAnimationEnd(Animation animation) {
+                        bindData();
+                    }
+
+                    public void onAnimationRepeat(Animation animation) {
+                    }
+
+                    public void onAnimationStart(Animation animation) {
+                    }
+
+                });
+
+                TranslateAnimation hideListAnimation = new TranslateAnimation(
+                        Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 0,
+                        Animation.ABSOLUTE, tabHeight, Animation.ABSOLUTE, 0);
+                hideListAnimation.setDuration(getResources().getInteger(
+                        android.R.integer.config_longAnimTime));
+
+
+                mTabWidget.startAnimation(hideTabsAnimation);
+                mTabContentLayout.startAnimation(hideListAnimation);
+            }
+            mTabWidget.setVisibility(View.GONE);
+            mTabsVisible = false;
+            mSelectedRawContactId = null;
+            if (!animate) {
+                bindData();
+            }
+        }
+    }
 
 
     // QUERY CODE //
@@ -390,13 +454,15 @@
     public void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
         try{
             if (token == TOKEN_QUERY) {
-//                clearCurrentTabs();
                 mEntities = readEntities(iterator);
                 // Show the aggregate badge if this contact is aggregated.
                 boolean isAggregate = mEntities.size() > 1;
                 mContactHeaderWidget.showAggregateBadge(isAggregate);
-//                bindTabs();
-//                selectInitialTab();
+                if (mTabsVisible) {
+                    clearCurrentTabs();
+                    bindTabs();
+                    selectInitialTab();
+                }
                 bindData();
             }
         } finally {
@@ -495,13 +561,19 @@
     public boolean onPrepareOptionsMenu(Menu menu) {
         super.onPrepareOptionsMenu(menu);
 
+        // If tabWidget is not shown enable "show sources", otherwise
+        // enable "hide sources"
+        if (mTabsVisible) {
+            menu.findItem(R.id.menu_show_sources).setVisible(false);
+            menu.findItem(R.id.menu_hide_sources).setVisible(true);
+        } else {
+            menu.findItem(R.id.menu_show_sources).setVisible(true);
+            menu.findItem(R.id.menu_hide_sources).setVisible(false);
+        }
+
         // Only allow edit when we have at least one raw_contact id
         final boolean hasRawContact = (mRawContactIds.size() > 0);
-        menu.findItem(R.id.menu_split).setEnabled(hasRawContact);
-
-        // Only allow split when more than one contact
-        final boolean isAggregate = (mRawContactIds.size() > 1);
-        menu.findItem(R.id.menu_split).setEnabled(isAggregate);
+        menu.findItem(R.id.menu_edit).setEnabled(hasRawContact);
 
         return true;
     }
@@ -546,28 +618,27 @@
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
+            case R.id.menu_show_sources: {
+                showTabs(true, true /*animate*/);
+                break;
+            }
+            case R.id.menu_hide_sources: {
+                showTabs(false, true /*animate*/);
+                break;
+            }
             case R.id.menu_edit: {
-//                Long rawContactIdToEdit = mSelectedRawContactId;
-//                if (rawContactIdToEdit == null) {
-//                    // This shouldn't be possible. We only show the edit option if
-//                    // this value is non-null.
-//                    break;
-//                }
-//                if (rawContactIdToEdit == ALL_CONTACTS_ID) {
-//                    // If the "all" tab is selected, edit the next tab.
-//                    rawContactIdToEdit = getTabRawContactId(mTabWidget.getCurrentTab() + 1);
-//                }
-//                Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
-//                        rawContactIdToEdit);
-//                startActivityForResult(new Intent(Intent.ACTION_EDIT, rawContactUri),
-//                        REQUEST_EDIT_CONTACT);
-                if (mRawContactIds.size() > 0) {
-                    long rawContactIdToEdit = mRawContactIds.get(0);
-                    Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
-                            rawContactIdToEdit);
-                    startActivityForResult(new Intent(Intent.ACTION_EDIT, rawContactUri),
-                            REQUEST_EDIT_CONTACT);
+                Long rawContactIdToEdit = mSelectedRawContactId;
+                if (rawContactIdToEdit == null) {
+                    if (mRawContactIds.size() > 0) {
+                        rawContactIdToEdit = mRawContactIds.get(0);
+                    } else {
+                        // There is no rawContact to edit.
+                        break;
+                    }
                 }
+                Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI,
+                        rawContactIdToEdit);
+                startActivity(new Intent(Intent.ACTION_EDIT, rawContactUri));
                 break;
             }
             case R.id.menu_delete: {
@@ -575,14 +646,6 @@
                 showDialog(DIALOG_CONFIRM_DELETE);
                 return true;
             }
-            case R.id.menu_split: {
-                if (mRawContactIds.size() == 2) {
-                    splitContact(mRawContactIds.get(1));
-                } else {
-                    showSplitAggregateDialog();
-                }
-                return true;
-            }
             case R.id.menu_join: {
                 showJoinAggregateActivity();
                 return true;
@@ -686,23 +749,11 @@
 
     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
-        switch (requestCode) {
-            case REQUEST_JOIN_CONTACT: {
-                if (resultCode == RESULT_OK && intent != null) {
-                    final long contactId = ContentUris.parseId(intent.getData());
-                    joinAggregate(contactId);
-                }
-                break;
+        if (requestCode == REQUEST_JOIN_CONTACT) {
+            if (resultCode == RESULT_OK && intent != null) {
+                final long contactId = ContentUris.parseId(intent.getData());
+                joinAggregate(contactId);
             }
-//            case REQUEST_EDIT_CONTACT: {
-//                if (resultCode == RESULT_OK && intent != null) {
-//                    long newInitialSelectedRawContactId = intent.getLongExtra(
-//                            RAW_CONTACT_ID_EXTRA, ALL_CONTACTS_ID);
-//                    if (newInitialSelectedRawContactId != mSelectedRawContactId) {
-//                        mSelectedRawContactId = newInitialSelectedRawContactId;
-//                    }
-//                }
-//            }
         }
     }
 
@@ -808,7 +859,9 @@
         ViewEntry entry = ViewAdapter.getEntry(mSections, position, SHOW_SEPARATORS);
         if (entry != null) {
             Intent intent = entry.intent;
-            if (intent != null) {
+            if (entry.mimetype == SPLIT_MIMETYPE) {
+                splitContact(entry.id);
+            } else if (intent != null) {
                 try {
                     startActivity(intent);
                 } catch (ActivityNotFoundException e) {
@@ -866,13 +919,10 @@
                     mRawContactIds.add(rawContactId);
                 }
 
-
-//                // This performs the tab filtering
-//                if (mSelectedRawContactId != null
-//                        && mSelectedRawContactId != rawContactId
-//                        && mSelectedRawContactId != ALL_CONTACTS_ID) {
-//                    continue;
-//                }
+                // This performs the tab filtering
+                if (mSelectedRawContactId != null && mSelectedRawContactId != rawContactId) {
+                    continue;
+                }
 
                 for (NamedContentValues subValue : entity.getSubValues()) {
                     ViewEntry entry = new ViewEntry();
@@ -1004,6 +1054,19 @@
                         mOtherEntries.add(entry);
                     }
 
+                }
+
+                if (mSelectedRawContactId != null &&
+                        mSelectedRawContactId == rawContactId
+                        && mEntities.size() > 1) {
+                    ViewEntry entry = new ViewEntry();
+                    entry.mimetype = SPLIT_MIMETYPE;
+                    entry.id = rawContactId;
+                    entry.label = getString(R.string.split_label);
+                    entry.data = getString(R.string.split_explanation);
+                    entry.actionIcon = R.drawable.ic_list_split;
+                    mSplitEntry.add(entry);
+                }
                     // TODO(emillar) Add group entries
                     //              // Build the group entries
                     //              final Uri groupsUri = Uri.withAppendedPath(mUri, GroupMembership.CONTENT_DIRECTORY);
@@ -1046,7 +1109,6 @@
                     //                      groupCursor.close();
                     //                  }
                     //              }
-                }
 
             }
         }