Adds a list view option for viewing bookmarks

 Bug: 3166319
 This adds a popup menu option to the combined view that allows a
 user to switch between viewing their bookmarks as a grid of thumbnails
 or as a list of bookmarks with favicons.

Change-Id: I6729d477f574a46847dff4b69c1b32d9f63fb37f
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index a5d51dd..6478b10 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -20,42 +20,97 @@
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CursorAdapter;
 import android.widget.ImageView;
-import android.widget.ResourceCursorAdapter;
 import android.widget.TextView;
 
-class BrowserBookmarksAdapter extends ResourceCursorAdapter {
+class BrowserBookmarksAdapter extends CursorAdapter {
+    LayoutInflater mInflater;
+    int mCurrentView;
+
     /**
      *  Create a new BrowserBookmarksAdapter.
      */
-    public BrowserBookmarksAdapter(Context context) {
+    public BrowserBookmarksAdapter(Context context, int defaultView) {
         // Make sure to tell the CursorAdapter to avoid the observer and auto-requery
         // since the Loader will do that for us.
-        super(context, R.layout.bookmark_thumbnail, null);
+        super(context, null);
+        mInflater = LayoutInflater.from(context);
+        selectView(defaultView);
     }
 
     @Override
     public void bindView(View view, Context context, Cursor cursor) {
+        if (mCurrentView == BrowserBookmarksPage.VIEW_LIST) {
+            bindListView(view, context, cursor);
+        } else {
+            bindGridView(view, context, cursor);
+        }
+    }
+
+    void bindGridView(View view, Context context, Cursor cursor) {
         ImageView thumb = (ImageView) view.findViewById(R.id.thumb);
         TextView tv = (TextView) view.findViewById(R.id.label);
 
         tv.setText(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
-        Bitmap thumbnail = null;
         if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0) {
             // folder
             thumb.setImageResource(R.drawable.ic_folder);
         } else {
-            byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_THUMBNAIL);
-            if (data != null) {
-                thumbnail = BitmapFactory.decodeByteArray(data, 0, data.length);
+            byte[] thumbData = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_THUMBNAIL);
+            Bitmap thumbBitmap = null;
+            if (thumbData != null) {
+                thumbBitmap = BitmapFactory.decodeByteArray(thumbData, 0, thumbData.length);
             }
 
-            if (thumbnail == null) {
+            if (thumbBitmap == null) {
                 thumb.setImageResource(R.drawable.browser_thumbnail);
             } else {
-                thumb.setImageBitmap(thumbnail);
+                thumb.setImageBitmap(thumbBitmap);
             }
         }
     }
+
+    void bindListView(View view, Context context, Cursor cursor) {
+        ImageView favicon = (ImageView) view.findViewById(R.id.favicon);
+        TextView tv = (TextView) view.findViewById(R.id.label);
+
+        tv.setText(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
+        if (cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0) {
+            // folder
+            favicon.setImageResource(R.drawable.ic_folder);
+        } else {
+            byte[] faviconData = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON);
+            Bitmap faviconBitmap = null;
+            if (faviconData != null) {
+                faviconBitmap = BitmapFactory.decodeByteArray(faviconData, 0, faviconData.length);
+            }
+
+            if (faviconBitmap == null) {
+                favicon.setImageResource(R.drawable.app_web_browser_sm);
+            } else {
+                favicon.setImageBitmap(faviconBitmap);
+            }
+        }
+    }
+
+    @Override
+    public View newView(Context context, Cursor cursor, ViewGroup parent) {
+        if (mCurrentView == BrowserBookmarksPage.VIEW_LIST) {
+            return mInflater.inflate(R.layout.bookmark_list, parent, false);
+        } else {
+            return mInflater.inflate(R.layout.bookmark_thumbnail, parent, false);
+        }
+    }
+
+    public void selectView(int view) {
+        if (view != BrowserBookmarksPage.VIEW_LIST
+                && view != BrowserBookmarksPage.VIEW_THUMBNAILS) {
+            throw new IllegalArgumentException("Unknown view specified: " + view);
+        }
+        mCurrentView = view;
+    }
 }
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index c7392cc..2b8c535 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -31,6 +31,7 @@
 import android.content.Intent;
 import android.content.Loader;
 import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -53,6 +54,7 @@
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.GridView;
+import android.widget.ListView;
 import android.widget.Toast;
 
 /**
@@ -77,15 +79,20 @@
     public static final String PREF_ACCOUNT_NAME = "acct_name";
 
     static final String DEFAULT_ACCOUNT = "local";
+    static final int VIEW_THUMBNAILS = 1;
+    static final int VIEW_LIST = 2;
+    static final String PREF_SELECTED_VIEW = "bookmarks_view";
 
     BookmarksHistoryCallbacks mCallbacks;
     GridView mGrid;
+    ListView mList;
     BrowserBookmarksAdapter mAdapter;
     boolean mDisableNewWindow;
     BookmarkItem mContextHeader;
     boolean mCanceled = false;
     boolean mCreateShortcut;
     View mEmptyView;
+    int mCurrentView;
 
     BreadCrumbView mCrumbs;
 
@@ -134,9 +141,10 @@
                 if (cursor == null || cursor.getCount() == 0) {
                     mEmptyView.setVisibility(View.VISIBLE);
                     mGrid.setVisibility(View.GONE);
+                    mList.setVisibility(View.GONE);
                 } else {
                     mEmptyView.setVisibility(View.GONE);
-                    mGrid.setVisibility(View.VISIBLE);
+                    setupBookmarkView();
                 }
 
                 // Give the new data to the adapter
@@ -372,13 +380,19 @@
         if (!mCreateShortcut) {
             mGrid.setOnCreateContextMenuListener(this);
         }
-
-        mAdapter = new BrowserBookmarksAdapter(getActivity());
-        mGrid.setAdapter(mAdapter);
+        mList = (ListView) root.findViewById(R.id.list);
+        mList.setOnItemClickListener(this);
+        if (!mCreateShortcut) {
+            mList.setOnCreateContextMenuListener(this);
+            registerForContextMenu(mList);
+        }
 
         // Start the loaders
         LoaderManager lm = getLoaderManager();
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+        mCurrentView =
+            prefs.getInt(PREF_SELECTED_VIEW, BrowserBookmarksPage.VIEW_THUMBNAILS);
+        mAdapter = new BrowserBookmarksAdapter(getActivity(), mCurrentView);
         String accountType = prefs.getString(PREF_ACCOUNT_TYPE, DEFAULT_ACCOUNT);
         String accountName = prefs.getString(PREF_ACCOUNT_NAME, DEFAULT_ACCOUNT);
         if (!TextUtils.isEmpty(accountType) && !TextUtils.isEmpty(accountName)) {
@@ -609,4 +623,36 @@
         cm.setPrimaryClip(ClipData.newRawUri(null, null, Uri.parse(text.toString())));
     }
 
+    void selectView(int view) {
+        if (view == mCurrentView) {
+            return;
+        }
+        mCurrentView = view;
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
+        Editor edit = prefs.edit();
+        edit.putInt(PREF_SELECTED_VIEW, mCurrentView);
+        edit.apply();
+        if (mEmptyView.getVisibility() == View.VISIBLE) {
+            return;
+        }
+        setupBookmarkView();
+    }
+
+    private void setupBookmarkView() {
+        mAdapter.selectView(mCurrentView);
+        switch (mCurrentView) {
+        case VIEW_THUMBNAILS:
+            mList.setAdapter(null);
+            mGrid.setAdapter(mAdapter);
+            mGrid.setVisibility(View.VISIBLE);
+            mList.setVisibility(View.GONE);
+            break;
+        case VIEW_LIST:
+            mGrid.setAdapter(null);
+            mList.setAdapter(mAdapter);
+            mGrid.setVisibility(View.GONE);
+            mList.setVisibility(View.VISIBLE);
+            break;
+        }
+    }
 }
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index c078b51..4f6f10c 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -21,17 +21,22 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.preference.PreferenceManager;
 import android.provider.Browser;
 import android.view.LayoutInflater;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.webkit.WebIconDatabase;
 import android.webkit.WebIconDatabase.IconListener;
 import android.widget.LinearLayout;
+import android.widget.PopupMenu;
+import android.widget.PopupMenu.OnMenuItemClickListener;
 import android.widget.TextView;
 
 import java.util.HashMap;
@@ -44,7 +49,7 @@
 }
 
 public class CombinedBookmarkHistoryView extends LinearLayout
-        implements OnClickListener, BreadCrumbView.Controller {
+        implements OnClickListener, BreadCrumbView.Controller, OnMenuItemClickListener {
 
     final static String STARTING_FRAGMENT = "fragment";
 
@@ -63,6 +68,8 @@
     TextView mTabBookmarks;
     TextView mTabHistory;
     TextView mAddBookmark;
+    TextView mSelectBookmarkView;
+    View mSeperateSelectAdd;
 
     BrowserBookmarksPage mBookmarks;
     BrowserHistoryPage mHistory;
@@ -122,9 +129,20 @@
         mTabBookmarks = (TextView) findViewById(R.id.bmtab);
         mTabHistory = (TextView) findViewById(R.id.historytab);
         mAddBookmark = (TextView) findViewById(R.id.addbm);
+        mSeperateSelectAdd = findViewById(R.id.seperate_select_add);
+        mSelectBookmarkView = (TextView) findViewById(R.id.select_bookmark_view);
         mAddBookmark.setOnClickListener(this);
         mTabHistory.setOnClickListener(this);
         mTabBookmarks.setOnClickListener(this);
+        mSelectBookmarkView.setOnClickListener(this);
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
+        int bookmarksView =
+            prefs.getInt(BrowserBookmarksPage.PREF_SELECTED_VIEW, BrowserBookmarksPage.VIEW_THUMBNAILS);
+        if (bookmarksView == BrowserBookmarksPage.VIEW_THUMBNAILS) {
+            mSelectBookmarkView.setText(R.string.bookmark_thumbnail_view);
+        } else {
+            mSelectBookmarkView.setText(R.string.bookmark_list_view);
+        }
         // Start up the default fragment
         initFragments(mExtras);
         loadFragment(startingFragment, mExtras, false);
@@ -157,6 +175,8 @@
         switch (id) {
             case FRAGMENT_ID_BOOKMARKS:
                 fragment = mBookmarks;
+                mSeperateSelectAdd.setVisibility(View.VISIBLE);
+                mSelectBookmarkView.setVisibility(View.VISIBLE);
                 mCrumbs.setVisibility(View.VISIBLE);
                 if (notify) {
                     mCrumbs.notifyController();
@@ -165,6 +185,8 @@
             case FRAGMENT_ID_HISTORY:
                 fragment = mHistory;
                 mCrumbs.setVisibility(View.GONE);
+                mSeperateSelectAdd.setVisibility(View.GONE);
+                mSelectBookmarkView.setVisibility(View.GONE);
                 break;
             default:
                 throw new IllegalArgumentException();
@@ -189,6 +211,12 @@
             }
         } else if (mAddBookmark == view) {
             mUiController.bookmarkCurrentPage(mBookmarks.getFolderId());
+        } else if (mSelectBookmarkView == view) {
+            PopupMenu popup = new PopupMenu(mContext, mSelectBookmarkView);
+            popup.getMenuInflater().inflate(R.menu.bookmark_view,
+                    popup.getMenu());
+            popup.setOnMenuItemClickListener(this);
+            popup.show();
         }
     }
 
@@ -212,4 +240,19 @@
         return false;
     }
 
+    @Override
+    public boolean onMenuItemClick(MenuItem item) {
+        switch (item.getItemId()) {
+        case R.id.list_view:
+            mSelectBookmarkView.setText(R.string.bookmark_list_view);
+            mBookmarks.selectView(BrowserBookmarksPage.VIEW_LIST);
+            return true;
+        case R.id.thumbnail_view:
+            mSelectBookmarkView.setText(R.string.bookmark_thumbnail_view);
+            mBookmarks.selectView(BrowserBookmarksPage.VIEW_THUMBNAILS);
+            return true;
+        }
+        return false;
+    }
+
 }