History UI update

Change-Id: If4af6e37252f297bc1744af65df4bc2f123f41dd
diff --git a/src/com/android/browser/BookmarkItem.java b/src/com/android/browser/BookmarkItem.java
index fbb362e..4e60073 100644
--- a/src/com/android/browser/BookmarkItem.java
+++ b/src/com/android/browser/BookmarkItem.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.ImageView;
@@ -94,6 +95,10 @@
         }
     }
 
+    void setFaviconBackground(Drawable d) {
+        mImageView.setBackgroundDrawable(d);
+    }
+
     /**
      *  Set the new name for the bookmark item.
      *
diff --git a/src/com/android/browser/BookmarkUtils.java b/src/com/android/browser/BookmarkUtils.java
index 27d3310..379b22d 100644
--- a/src/com/android/browser/BookmarkUtils.java
+++ b/src/com/android/browser/BookmarkUtils.java
@@ -22,6 +22,7 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -32,12 +33,13 @@
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.PaintDrawable;
 import android.net.Uri;
 import android.os.Message;
 import android.preference.PreferenceManager;
 import android.provider.Browser;
 import android.provider.BrowserContract;
-import android.text.TextUtils;
 
 public class BookmarkUtils {
     private final static String LOGTAG = "BookmarkUtils";
@@ -64,13 +66,16 @@
         return createIcon(context, touchIcon, favicon, type, iconDimension);
     }
 
-    public static Bitmap createListWidgetIcon(Context context, Bitmap touchIcon,
-            Bitmap favicon) {
-        int iconDimension = context.getResources().getDimensionPixelSize(
-                R.dimen.bookmark_widget_favicon_size);
-
-        return createIcon(context, touchIcon, favicon,
-                BookmarkIconType.ICON_WIDGET, iconDimension);
+    static Drawable createListFaviconBackground(Context context) {
+        PaintDrawable faviconBackground = new PaintDrawable();
+        Resources res = context.getResources();
+        int padding = res.getDimensionPixelSize(R.dimen.list_favicon_padding);
+        faviconBackground.setPadding(padding, padding, padding, padding);
+        faviconBackground.getPaint().setColor(context.getResources()
+                .getColor(R.color.bookmarkListFaviconBackground));
+        faviconBackground.setCornerRadius(
+                res.getDimension(R.dimen.list_favicon_corner_radius));
+        return faviconBackground;
     }
 
     private static Bitmap createIcon(Context context, Bitmap touchIcon,
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index 26ba62c..ccd2fbc 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -20,7 +20,7 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
-import android.graphics.drawable.PaintDrawable;
+import android.graphics.drawable.Drawable;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -31,7 +31,7 @@
 class BrowserBookmarksAdapter extends CursorAdapter {
     LayoutInflater mInflater;
     int mCurrentView;
-    PaintDrawable mFaviconBackground;
+    Drawable mFaviconBackground;
 
     /**
      *  Create a new BrowserBookmarksAdapter.
@@ -43,12 +43,7 @@
         mInflater = LayoutInflater.from(context);
         selectView(defaultView);
         float density = context.getResources().getDisplayMetrics().density;
-        mFaviconBackground = new PaintDrawable();
-        int padding = (int) (5 * density);
-        mFaviconBackground.setPadding(padding, padding, padding, padding);
-        mFaviconBackground.getPaint().setColor(context.getResources()
-                .getColor(R.color.bookmarkListFaviconBackground));
-        mFaviconBackground.setCornerRadius(3 * density);
+        mFaviconBackground = BookmarkUtils.createListFaviconBackground(context);
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index dfb0b77..cbaad2b 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -19,16 +19,13 @@
 import com.android.browser.BreadCrumbView.Crumb;
 
 import android.app.Activity;
-import android.app.AlertDialog;
 import android.app.Fragment;
 import android.app.LoaderManager;
 import android.content.ClipData;
 import android.content.ClipboardManager;
-import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.Context;
 import android.content.CursorLoader;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.Loader;
 import android.content.SharedPreferences;
@@ -97,6 +94,7 @@
     static final String PREF_SELECTED_VIEW = "bookmarks_view";
 
     BookmarksPageCallbacks mCallbacks;
+    View mRoot;
     GridView mGrid;
     ListView mList;
     BrowserBookmarksAdapter mAdapter;
@@ -417,20 +415,20 @@
             Bundle savedInstanceState) {
         Context context = getActivity();
 
-        View root = inflater.inflate(R.layout.bookmarks, container, false);
-        mEmptyView = root.findViewById(android.R.id.empty);
+        mRoot = inflater.inflate(R.layout.bookmarks, container, false);
+        mEmptyView = mRoot.findViewById(android.R.id.empty);
 
-        mGrid = (GridView) root.findViewById(R.id.grid);
+        mGrid = (GridView) mRoot.findViewById(R.id.grid);
         mGrid.setOnItemClickListener(this);
         mGrid.setColumnWidth(Controller.getDesiredThumbnailWidth(getActivity()));
-        mList = (ListView) root.findViewById(R.id.list);
+        mList = (ListView) mRoot.findViewById(R.id.list);
         mList.setOnItemClickListener(this);
         setEnableContextMenu(mEnableContextMenu);
 
         // Prep the header
         ViewGroup hc = mHeaderContainer;
         if (hc == null) {
-            hc = (ViewGroup) root.findViewById(R.id.header_container);
+            hc = (ViewGroup) mRoot.findViewById(R.id.header_container);
             hc.setVisibility(View.VISIBLE);
         }
         mHeader = inflater.inflate(R.layout.bookmarks_header, hc, false);
@@ -471,7 +469,7 @@
         // Add our own listener in case there are favicons that have yet to be loaded.
         CombinedBookmarkHistoryView.getIconListenerSet().addListener(this);
 
-        return root;
+        return mRoot;
     }
 
     @Override
@@ -669,6 +667,10 @@
         Resources res = getActivity().getResources();
         int horizontalSpacing = (int) res.getDimension(R.dimen.combo_horizontalSpacing);
         mGrid.setHorizontalSpacing(horizontalSpacing);
+        int paddingLeftRight = (int) res.getDimension(R.dimen.combo_paddingLeftRight);
+        int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop);
+        mRoot.setPadding(paddingLeftRight, paddingTop,
+                paddingLeftRight, 0);
     }
 
     @Override
diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java
index 87649d4..f3c7a7f 100644
--- a/src/com/android/browser/BrowserHistoryPage.java
+++ b/src/com/android/browser/BrowserHistoryPage.java
@@ -20,6 +20,7 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.Fragment;
+import android.app.FragmentBreadCrumbs;
 import android.app.LoaderManager.LoaderCallbacks;
 import android.content.ClipboardManager;
 import android.content.ContentResolver;
@@ -32,8 +33,10 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.Cursor;
+import android.database.DataSetObserver;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
@@ -49,10 +52,15 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.ViewStub;
 import android.webkit.WebIconDatabase.IconListener;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.BaseAdapter;
 import android.widget.ExpandableListView;
 import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
 import android.widget.ExpandableListView.OnChildClickListener;
+import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -67,12 +75,14 @@
     static final int LOADER_MOST_VISITED = 2;
 
     BookmarksHistoryCallbacks mCallbacks;
-    ExpandableListView mList;
-    View mEmptyView;
     HistoryAdapter mAdapter;
+    HistoryChildWrapper mChildWrapper;
     boolean mDisableNewWindow;
     HistoryItem mContextHeader;
     String mMostVisitsLimit;
+    ListView mGroupList, mChildList;
+    private ViewGroup mPrefsContainer;
+    private FragmentBreadCrumbs mFragmentBreadCrumbs;
 
     // Implementation of WebIconDatabase.IconListener
     class IconReceiver implements IconListener {
@@ -84,6 +94,7 @@
 
     // Instance of IconReceiver
     final IconReceiver mIconReceiver = new IconReceiver();
+    private View mRoot;
 
     static interface HistoryQuery {
         static final String[] PROJECTION = new String[] {
@@ -153,24 +164,48 @@
         }
     }
 
+    void selectGroup(int position) {
+        mGroupItemClickListener.onItemClick(null,
+                mAdapter.getGroupView(position, false, null, null),
+                position, position);
+    }
+
+    void checkIfEmpty() {
+        if (mAdapter.mMostVisited != null && mAdapter.mHistoryCursor != null) {
+            // Both cursors have loaded - check to see if we have data
+            if (mAdapter.isEmpty()) {
+                mRoot.findViewById(R.id.history).setVisibility(View.GONE);
+                mRoot.findViewById(android.R.id.empty).setVisibility(View.VISIBLE);
+            } else {
+                mRoot.findViewById(R.id.history).setVisibility(View.VISIBLE);
+                mRoot.findViewById(android.R.id.empty).setVisibility(View.GONE);
+            }
+        }
+    }
+
     @Override
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
         switch (loader.getId()) {
             case LOADER_HISTORY: {
                 mAdapter.changeCursor(data);
+                if (mAdapter.getGroupCount() > 0) {
+                    selectGroup(0);
+                }
 
-                // Add an empty view late, so it does not claim an empty
-                // history before the adapter is present
-                mList.setEmptyView(mEmptyView);
+                checkIfEmpty();
                 break;
             }
 
             case LOADER_MOST_VISITED: {
+                int preCount = mAdapter.getGroupCount();
                 mAdapter.changeMostVisitedCursor(data);
+                if (mAdapter.mHistoryCursor != null
+                        && preCount == 0
+                        && mAdapter.getGroupCount() > 0) {
+                    selectGroup(0);
+                }
 
-                // Add an empty view late, so it does not claim an empty
-                // history before the adapter is present
-                mList.setEmptyView(mEmptyView);
+                checkIfEmpty();
                 break;
             }
 
@@ -180,6 +215,7 @@
         }
     }
 
+    @Override
     public void onLoaderReset(Loader<Cursor> loader) {
     }
 
@@ -198,25 +234,44 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        View root = inflater.inflate(R.layout.history, container, false);
-        mList = (ExpandableListView) root.findViewById(android.R.id.list);
-        mList.setCacheColorHint(0);
-        mList.setOnCreateContextMenuListener(this);
-        mList.setOnChildClickListener(this);
+        mRoot = inflater.inflate(R.layout.history, container, false);
+        ViewStub stub = (ViewStub) mRoot.findViewById(R.id.pref_stub);
+        stub.setLayoutResource(com.android.internal.R.layout.preference_list_content);
+        stub.inflate();
+        mGroupList = (ListView) mRoot.findViewById(android.R.id.list);
+        mPrefsContainer = (ViewGroup) mRoot.findViewById(com.android.internal.R.id.prefs_frame);
+        mFragmentBreadCrumbs = (FragmentBreadCrumbs) mRoot.findViewById(android.R.id.title);
+        mFragmentBreadCrumbs.setMaxVisible(1);
+        mFragmentBreadCrumbs.setActivity(getActivity());
+        mPrefsContainer.setVisibility(View.VISIBLE);
         mAdapter = new HistoryAdapter(getActivity());
-        mList.setAdapter(mAdapter);
+        mGroupList.setAdapter(new HistoryGroupWrapper(mAdapter));
+        mGroupList.setOnItemClickListener(mGroupItemClickListener);
+        mChildWrapper = new HistoryChildWrapper(mAdapter);
+        mChildList = new ListView(getActivity());
+        mChildList.setAdapter(mChildWrapper);
+        ViewGroup prefs = (ViewGroup) mRoot.findViewById(com.android.internal.R.id.prefs);
+        prefs.addView(mChildList);
 
-        mEmptyView = root.findViewById(android.R.id.empty);
-
-        // Start the loader
+        // Start the loaders
         getLoaderManager().restartLoader(LOADER_HISTORY, null, this);
         getLoaderManager().restartLoader(LOADER_MOST_VISITED, null, this);
 
         // Register to receive icons in case they haven't all been loaded.
         CombinedBookmarkHistoryView.getIconListenerSet().addListener(mIconReceiver);
-        return root;
+        return mRoot;
     }
 
+    private OnItemClickListener mGroupItemClickListener = new OnItemClickListener() {
+        @Override
+        public void onItemClick(
+                AdapterView<?> parent, View view, int position, long id) {
+            CharSequence title = ((TextView) view).getText();
+            mFragmentBreadCrumbs.setTitle(title, title);
+            mChildWrapper.setSelectedGroup(position);
+        }
+    };
+
     @Override
     public void onDestroy() {
         super.onDestroy();
@@ -231,12 +286,6 @@
     }
 
     @Override
-    public void onPrepareOptionsMenu(Menu menu) {
-        menu.findItem(R.id.clear_history_menu_id).setVisible(
-                mAdapter != null && !mAdapter.isEmpty());
-    }
-
-    @Override
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case R.id.clear_history_menu_id:
@@ -385,11 +434,101 @@
         return false;
     }
 
+    private static abstract class HistoryWrapper extends BaseAdapter {
+
+        protected HistoryAdapter mAdapter;
+        private DataSetObserver mObserver = new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                super.onChanged();
+                notifyDataSetChanged();
+            }
+
+            @Override
+            public void onInvalidated() {
+                super.onInvalidated();
+                notifyDataSetInvalidated();
+            }
+        };
+
+        public HistoryWrapper(HistoryAdapter adapter) {
+            mAdapter = adapter;
+            mAdapter.registerDataSetObserver(mObserver);
+        }
+
+    }
+    private static class HistoryGroupWrapper extends HistoryWrapper {
+
+        public HistoryGroupWrapper(HistoryAdapter adapter) {
+            super(adapter);
+        }
+
+        @Override
+        public int getCount() {
+            return mAdapter.getGroupCount();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            return mAdapter.getGroupView(position, false, convertView, parent);
+        }
+
+    }
+
+    private static class HistoryChildWrapper extends HistoryWrapper {
+
+        private int mSelectedGroup;
+
+        public HistoryChildWrapper(HistoryAdapter adapter) {
+            super(adapter);
+        }
+
+        void setSelectedGroup(int groupPosition) {
+            mSelectedGroup = groupPosition;
+            notifyDataSetChanged();
+        }
+
+        @Override
+        public int getCount() {
+            return mAdapter.getChildrenCount(mSelectedGroup);
+        }
+
+        @Override
+        public Object getItem(int position) {
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return position;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            return mAdapter.getChildView(mSelectedGroup, position,
+                    false, convertView, parent);
+        }
+
+    }
+
     private class HistoryAdapter extends DateSortedExpandableListAdapter {
+
         private Cursor mMostVisited, mHistoryCursor;
+        Drawable mFaviconBackground;
 
         HistoryAdapter(Context context) {
             super(context, HistoryQuery.INDEX_DATE_LAST_VISITED);
+            mFaviconBackground = BookmarkUtils.createListFaviconBackground(context);
         }
 
         @Override
@@ -430,6 +569,9 @@
         @Override
         public int getChildrenCount(int groupPosition) {
             if (groupPosition >= super.getGroupCount()) {
+                if (mMostVisited == null) {
+                    return 0;
+                }
                 return mMostVisited.getCount();
             }
             return super.getChildrenCount(groupPosition);
@@ -497,6 +639,7 @@
                         item.getPaddingTop(),
                         item.getPaddingRight(),
                         item.getPaddingBottom());
+                item.setFaviconBackground(mFaviconBackground);
             } else {
                 item = (HistoryItem) convertView;
             }
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index 5731c37..8b58d2e 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -174,12 +174,13 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-
-        Resources res = mContext.getResources();
-        int paddingLeftRight = (int) res.getDimension(R.dimen.combo_paddingLeftRight);
-        int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop);
-        findViewById(R.id.fragment).setPadding(paddingLeftRight, paddingTop,
-                paddingLeftRight, 0);
+        if (mCurrentFragment == FRAGMENT_ID_HISTORY) {
+            // Warning, ugly hack below
+            // This is done because history uses orientation-specific padding
+            FragmentManager fm = mActivity.getFragmentManager();
+            mHistory = BrowserHistoryPage.newInstance(mUiController, mHistory.getArguments());
+            fm.openTransaction().replace(R.id.fragment, mHistory).commit();
+        }
     }
 
     private BookmarksPageCallbacks mBookmarkCallbackWrapper = new BookmarksPageCallbacks() {