From 608baa78f4071409294f79b37e7ffa9ca96c4223 Mon Sep 17 00:00:00 2001
From: John Reck <jreck@google.com>
Date: Wed, 24 Nov 2010 10:32:28 -0800
Subject: Refactor Bookmark fragment, fixes NPE

 Bug: 2926451
 This change refactors the BrowserBookmarkPage fragment for better
 encapsulation, and updates the CombinedBookmarkHistoryView and
 ShortcutActivity. ShortcutActivity now supports folder navigation
 as well as toggling list or thumbnail view.

Change-Id: Ie8168467e793d60d75c15746f81318cfa7e9f003
---
 res/layout/bookmarks.xml                           |  69 ++++---
 res/layout/bookmarks_header.xml                    |  49 +++++
 res/layout/bookmarks_history.xml                   |  48 ++---
 res/values/styles.xml                              |   2 +-
 .../android/browser/BrowserBookmarksAdapter.java   |   5 +
 src/com/android/browser/BrowserBookmarksPage.java  | 210 ++++++++++++++++-----
 .../browser/CombinedBookmarkHistoryView.java       |  97 ++++------
 src/com/android/browser/ShortcutActivity.java      |  61 +++---
 8 files changed, 340 insertions(+), 201 deletions(-)
 create mode 100644 res/layout/bookmarks_header.xml

diff --git a/res/layout/bookmarks.xml b/res/layout/bookmarks.xml
index 66a78e8..7a0aa23 100644
--- a/res/layout/bookmarks.xml
+++ b/res/layout/bookmarks.xml
@@ -14,36 +14,49 @@
      limitations under the License.
 -->
 
-<FrameLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
-    <GridView
-        android:id="@+id/grid"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:horizontalSpacing="16dip"
-        android:verticalSpacing="16dip"
-        android:stretchMode="spacingWidth"
-        android:scrollbarStyle="insideInset"
-        android:listSelector="@android:drawable/gallery_thumb"
-        android:drawSelectorOnTop="true"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        android:numColumns="auto_fit" />
-    <ListView
-        android:id="@+id/list"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <FrameLayout
+        android:id="@+id/header_container"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:focusable="true"
-        android:focusableInTouchMode="true"
-        android:visibility="gone"/>
-    <TextView
-        android:id="@android:id/empty"
-        android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:textAppearance="?android:attr/textAppearanceLarge"
-        android:text="@string/empty_bookmarks_folder"
         android:visibility="gone" />
-</FrameLayout>
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+        <GridView
+            android:id="@+id/grid"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:horizontalSpacing="16dip"
+            android:verticalSpacing="16dip"
+            android:stretchMode="spacingWidth"
+            android:scrollbarStyle="insideInset"
+            android:listSelector="@android:drawable/gallery_thumb"
+            android:drawSelectorOnTop="true"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            android:numColumns="auto_fit" />
+        <ListView
+            android:id="@+id/list"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:focusable="true"
+            android:focusableInTouchMode="true"
+            android:visibility="gone"/>
+        <TextView
+            android:id="@android:id/empty"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:text="@string/empty_bookmarks_folder"
+            android:visibility="gone" />
+    </FrameLayout>
+
+</LinearLayout>
diff --git a/res/layout/bookmarks_header.xml b/res/layout/bookmarks_header.xml
new file mode 100644
index 0000000..597e629
--- /dev/null
+++ b/res/layout/bookmarks_header.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="48dip"
+    android:orientation="horizontal">
+
+    <TextView
+        android:id="@+id/root_folder"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:text="@string/defaultBookmarksUpButton"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:gravity="center_vertical"
+        android:visibility="gone"
+        android:paddingLeft="16dip"
+        android:drawableLeft="@drawable/ic_tab_bookmarks_selected"
+        android:drawablePadding="16dip" />
+
+    <com.android.browser.BreadCrumbView
+        android:id="@+id/crumbs"
+        android:layout_width="0dip"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:paddingLeft="16dip" />
+
+    <TextView
+        android:id="@+id/select_bookmark_view"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:text="@string/switch_to_thumbnails"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:gravity="center_vertical" />
+
+</LinearLayout>
diff --git a/res/layout/bookmarks_history.xml b/res/layout/bookmarks_history.xml
index b8ccfe7..a3a5084 100644
--- a/res/layout/bookmarks_history.xml
+++ b/res/layout/bookmarks_history.xml
@@ -22,16 +22,14 @@
     android:paddingRight="16dip"
     android:orientation="vertical"
     android:background="@color/black">
-    <RelativeLayout
-        android:id="@+id/bar"
+    <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="48dip">
+
         <LinearLayout
             android:id="@+id/tabs"
             android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:paddingLeft="16dip"
-            android:paddingRight="16dip">
+            android:layout_height="match_parent">
             <TextView
                 android:id="@+id/historytab"
                 android:layout_width="wrap_content"
@@ -58,42 +56,34 @@
                 android:text="@string/bookmarks"
                 android:drawableLeft="@drawable/ic_tab_bookmarks_selected"
                 android:drawablePadding="16dip" />
-            <com.android.browser.BreadCrumbView
-                android:id="@+id/crumbs"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:paddingLeft="16dip"
-                android:paddingRight="16dip" />
         </LinearLayout>
-        <TextView
-            android:id="@+id/addbm"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:text="@string/add_new_bookmark"
-            android:layout_alignParentRight="true"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:gravity="center_vertical"
-            android:background="@null"
-            android:drawableLeft="@drawable/ic_favorite_off_normal"
-            android:drawablePadding="16dip" />
+
+        <FrameLayout
+            android:id="@+id/header_container"
+            android:layout_width="0dip"
+            android:layout_weight="1"
+            android:layout_height="match_parent" />
+
         <ImageView
             android:id="@+id/seperate_select_add"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:layout_toLeftOf="@id/addbm"
             android:paddingRight="16dip"
+            android:paddingLeft="16dip"
             android:src="@drawable/divider_vert" />
+
         <TextView
-            android:id="@+id/select_bookmark_view"
+            android:id="@+id/addbm"
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
-            android:text="@string/switch_to_thumbnails"
-            android:layout_toLeftOf="@id/seperate_select_add"
-            android:paddingRight="16dip"
+            android:text="@string/add_new_bookmark"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:gravity="center_vertical"
-            android:background="@null" />
-    </RelativeLayout>
+            android:background="@null"
+            android:drawableLeft="@drawable/ic_favorite_off_normal"
+            android:drawablePadding="16dip" />
+
+    </LinearLayout>
     <FrameLayout
         android:id="@+id/fragment"
         android:paddingTop="8dip"
diff --git a/res/values/styles.xml b/res/values/styles.xml
index a1ca842..1a4ee2d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -32,7 +32,7 @@
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
-    <style name="ShortcutTheme" parent="@android:Theme.Black">
+    <style name="ShortcutTheme" parent="@android:Theme.Holo.DialogWhenLarge">
         <item name="android:windowNoTitle">true</item>
         <item name="android:windowContentOverlay">@null</item>
     </style>
diff --git a/src/com/android/browser/BrowserBookmarksAdapter.java b/src/com/android/browser/BrowserBookmarksAdapter.java
index 6478b10..f587f01 100644
--- a/src/com/android/browser/BrowserBookmarksAdapter.java
+++ b/src/com/android/browser/BrowserBookmarksAdapter.java
@@ -113,4 +113,9 @@ class BrowserBookmarksAdapter extends CursorAdapter {
         }
         mCurrentView = view;
     }
+
+    @Override
+    public Cursor getItem(int position) {
+        return (Cursor) super.getItem(position);
+    }
 }
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index 2b8c535..4370885 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -47,6 +47,7 @@ import android.view.LayoutInflater;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.webkit.WebIconDatabase.IconListener;
 import android.widget.Adapter;
@@ -55,14 +56,24 @@ import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemSelectedListener;
 import android.widget.GridView;
 import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.PopupMenu.OnMenuItemClickListener;
+import android.widget.TextView;
 import android.widget.Toast;
 
+interface BookmarksPageCallbacks {
+    // Return true if handled
+    boolean onBookmarkSelected(Cursor c, boolean isFolder);
+    // Return true if handled
+    boolean onOpenInNewWindow(Cursor c);
+}
+
 /**
  *  View showing the user's bookmarks in the browser.
  */
 public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener,
         LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener, IconListener,
-        OnItemSelectedListener {
+        OnItemSelectedListener, BreadCrumbView.Controller, OnClickListener, OnMenuItemClickListener {
 
     static final int BOOKMARKS_SAVE = 1;
     static final String LOGTAG = "browser";
@@ -70,7 +81,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     static final int LOADER_BOOKMARKS = 1;
     static final int LOADER_ACCOUNTS_THEN_BOOKMARKS = 2;
 
-    static final String EXTRA_SHORTCUT = "create_shortcut";
     static final String EXTRA_DISABLE_WINDOW = "disable_new_window";
 
     static final String ACCOUNT_NAME_UNSYNCED = "Unsynced";
@@ -83,25 +93,29 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     static final int VIEW_LIST = 2;
     static final String PREF_SELECTED_VIEW = "bookmarks_view";
 
-    BookmarksHistoryCallbacks mCallbacks;
+    BookmarksPageCallbacks mCallbacks;
     GridView mGrid;
     ListView mList;
     BrowserBookmarksAdapter mAdapter;
     boolean mDisableNewWindow;
     BookmarkItem mContextHeader;
     boolean mCanceled = false;
-    boolean mCreateShortcut;
+    boolean mEnableContextMenu = true;
+    boolean mShowRootFolder = false;
     View mEmptyView;
     int mCurrentView;
-
+    View mHeader;
+    View mRootFolderView;
+    ViewGroup mHeaderContainer;
     BreadCrumbView mCrumbs;
+    TextView mSelectBookmarkView;
 
-    static BrowserBookmarksPage newInstance(BookmarksHistoryCallbacks cb,
-            BreadCrumbView crumbs, Bundle args) {
+    static BrowserBookmarksPage newInstance(BookmarksPageCallbacks cb,
+            Bundle args, ViewGroup headerContainer) {
         BrowserBookmarksPage bbp = new BrowserBookmarksPage();
         bbp.mCallbacks = cb;
+        bbp.mHeaderContainer = headerContainer;
         bbp.setArguments(args);
-        bbp.mCrumbs = crumbs;
         return bbp;
     }
 
@@ -217,7 +231,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     long getFolderId() {
         LoaderManager manager = getLoaderManager();
         BookmarksLoader loader =
-                (BookmarksLoader) ((Loader)(manager.getLoader(LOADER_BOOKMARKS)));
+                (BookmarksLoader) ((Loader<?>)manager.getLoader(LOADER_BOOKMARKS));
 
         Uri uri = loader.getUri();
         if (uri != null) {
@@ -238,7 +252,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         }
         LoaderManager manager = getLoaderManager();
         BookmarksLoader loader =
-                (BookmarksLoader) ((Loader) manager.getLoader(LOADER_BOOKMARKS));
+                (BookmarksLoader) ((Loader<?>) manager.getLoader(LOADER_BOOKMARKS));
         loader.setUri(uri);
         loader.forceLoad();
 
@@ -267,7 +281,8 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
             editBookmark(i.position);
             break;
         case R.id.shortcut_context_menu_id:
-            activity.sendBroadcast(createShortcutIntent(i.position));
+            Cursor c = mAdapter.getItem(i.position);
+            activity.sendBroadcast(createShortcutIntent(getActivity(), c));
             break;
         case R.id.delete_context_menu_id:
             displayRemoveBookmarkDialog(i.position);
@@ -276,7 +291,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
             openInNewWindow(i.position);
             break;
         case R.id.share_link_context_menu_id: {
-            Cursor cursor = (Cursor) mAdapter.getItem(i.position);
+            Cursor cursor = mAdapter.getItem(i.position);
             Controller.sharePage(activity,
                     cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE),
                     cursor.getString(BookmarksLoader.COLUMN_INDEX_URL),
@@ -294,7 +309,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         }
         // Only for the Most visited page
         case R.id.save_to_bookmarks_menu_id: {
-            Cursor cursor = (Cursor) mAdapter.getItem(i.position);
+            Cursor cursor = mAdapter.getItem(i.position);
             String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
             String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
             // If the site is bookmarked, the item becomes remove from
@@ -308,7 +323,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         return true;
     }
 
-    Bitmap getBitmap(Cursor cursor, int columnIndex) {
+    static Bitmap getBitmap(Cursor cursor, int columnIndex) {
         byte[] data = cursor.getBlob(columnIndex);
         if (data == null) {
             return null;
@@ -319,7 +334,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     @Override
     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
         AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
-        Cursor cursor = (Cursor) mAdapter.getItem(info.position);
+        Cursor cursor = mAdapter.getItem(info.position);
         boolean isFolder
                 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
         if (isFolder) return;
@@ -362,7 +377,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         super.onCreate(icicle);
 
         Bundle args = getArguments();
-        mCreateShortcut = args == null ? false : args.getBoolean(EXTRA_SHORTCUT, false);
         mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false);
     }
 
@@ -377,21 +391,35 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         mGrid = (GridView) root.findViewById(R.id.grid);
         mGrid.setOnItemClickListener(this);
         mGrid.setColumnWidth(Controller.getDesiredThumbnailWidth(getActivity()));
-        if (!mCreateShortcut) {
-            mGrid.setOnCreateContextMenuListener(this);
-        }
         mList = (ListView) root.findViewById(R.id.list);
         mList.setOnItemClickListener(this);
-        if (!mCreateShortcut) {
-            mList.setOnCreateContextMenuListener(this);
-            registerForContextMenu(mList);
-        }
+        setEnableContextMenu(mEnableContextMenu);
+
+        // Prep the header
+        ViewGroup hc = mHeaderContainer;
+        if (hc == null) {
+            hc = (ViewGroup) root.findViewById(R.id.header_container);
+            hc.setVisibility(View.VISIBLE);
+        }
+        mHeader = inflater.inflate(R.layout.bookmarks_header, hc, true);
+        mCrumbs = (BreadCrumbView) mHeader.findViewById(R.id.crumbs);
+        mCrumbs.setController(this);
+        mSelectBookmarkView = (TextView) mHeader.findViewById(R.id.select_bookmark_view);
+        mSelectBookmarkView.setOnClickListener(this);
+        mRootFolderView = mHeader.findViewById(R.id.root_folder);
+        mRootFolderView.setOnClickListener(this);
+        setShowRootFolder(mShowRootFolder);
 
         // Start the loaders
         LoaderManager lm = getLoaderManager();
         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
         mCurrentView =
             prefs.getInt(PREF_SELECTED_VIEW, BrowserBookmarksPage.VIEW_THUMBNAILS);
+        if (mCurrentView == BrowserBookmarksPage.VIEW_THUMBNAILS) {
+            mSelectBookmarkView.setText(R.string.bookmark_thumbnail_view);
+        } else {
+            mSelectBookmarkView.setText(R.string.bookmark_list_view);
+        }
         mAdapter = new BrowserBookmarksAdapter(getActivity(), mCurrentView);
         String accountType = prefs.getString(PREF_ACCOUNT_TYPE, DEFAULT_ACCOUNT);
         String accountName = prefs.getString(PREF_ACCOUNT_NAME, DEFAULT_ACCOUNT);
@@ -415,6 +443,27 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         return root;
     }
 
+    public void setShowRootFolder(boolean show) {
+        mShowRootFolder = show;
+        if (mRootFolderView != null) {
+            if (mShowRootFolder) {
+                mRootFolderView.setVisibility(View.VISIBLE);
+            } else {
+                mRootFolderView.setVisibility(View.GONE);
+            }
+        }
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        if (mHeaderContainer != null) {
+            mHeaderContainer.removeView(mHeader);
+        }
+        mCrumbs.setController(null);
+        mCrumbs = null;
+    }
+
     @Override
     public void onReceivedIcon(String url, Bitmap icon) {
         // A new favicon has been loaded, so let anything attached to the adapter know about it
@@ -423,7 +472,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     }
 
     @Override
-    public void onItemClick(AdapterView parent, View v, int position, long id) {
+    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
         // It is possible that the view has been canceled when we get to
         // this point as back has a higher priority
         if (mCanceled) {
@@ -431,22 +480,18 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
             return;
         }
 
-        if (mCreateShortcut) {
-            Intent intent = createShortcutIntent(position);
-            // the activity handles the intent in startActivityFromFragment
-            startActivity(intent);
+        Cursor cursor = mAdapter.getItem(position);
+        boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
+        if (mCallbacks != null &&
+                mCallbacks.onBookmarkSelected(cursor, isFolder)) {
             return;
         }
 
-        Cursor cursor = (Cursor) mAdapter.getItem(position);
-        boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
-        if (!isFolder) {
-            mCallbacks.onUrlSelected(getUrl(position), false);
-        } else {
+        if (isFolder) {
             String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
             LoaderManager manager = getLoaderManager();
             BookmarksLoader loader =
-                    (BookmarksLoader) ((Loader) manager.getLoader(LOADER_BOOKMARKS));
+                    (BookmarksLoader) ((Loader<?>) manager.getLoader(LOADER_BOOKMARKS));
             Uri uri = ContentUris.withAppendedId(
                     BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id);
             if (mCrumbs != null) {
@@ -488,26 +533,29 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
         // Do nothing
     }
 
-    private Intent createShortcutIntent(int position) {
-        Cursor cursor = (Cursor) mAdapter.getItem(position);
+    /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) {
         String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
         String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE);
         Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON);
         Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON);
-        return BookmarkUtils.createAddToHomeIntent(getActivity(), url, title, touchIcon, favicon);
+        return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon);
     }
 
     private void loadUrl(int position) {
-        mCallbacks.onUrlSelected(getUrl(position), false);
+        if (mCallbacks != null) {
+            mCallbacks.onBookmarkSelected(mAdapter.getItem(position), false);
+        }
     }
 
     private void openInNewWindow(int position) {
-        mCallbacks.onUrlSelected(getUrl(position), true);
+        if (mCallbacks != null) {
+            mCallbacks.onOpenInNewWindow(mAdapter.getItem(position));
+        }
     }
 
     private void editBookmark(int position) {
         Intent intent = new Intent(getActivity(), AddBookmarkPage.class);
-        Cursor cursor = (Cursor) mAdapter.getItem(position);
+        Cursor cursor = mAdapter.getItem(position);
         Bundle item = new Bundle();
         item.putString(BrowserContract.Bookmarks.TITLE,
                 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE));
@@ -590,7 +638,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     private void displayRemoveBookmarkDialog(final int position) {
         // Put up a dialog asking if the user really wants to
         // delete the bookmark
-        Cursor cursor = (Cursor) mAdapter.getItem(position);
+        Cursor cursor = mAdapter.getItem(position);
         Context context = getActivity();
         final ContentResolver resolver = context.getContentResolver();
         final Uri uri = ContentUris.withAppendedId(BrowserContract.Bookmarks.CONTENT_URI,
@@ -613,8 +661,11 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
     }
 
     private String getUrl(int position) {
-        Cursor cursor = (Cursor) mAdapter.getItem(position);
-        return cursor.getString(BookmarksLoader.COLUMN_INDEX_URL);
+        return getUrl(mAdapter.getItem(position));
+    }
+
+    /* package */ static String getUrl(Cursor c) {
+        return c.getString(BookmarksLoader.COLUMN_INDEX_URL);
     }
 
     private void copy(CharSequence text) {
@@ -655,4 +706,77 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte
             break;
         }
     }
+
+    public BreadCrumbView getBreadCrumb() {
+        return mCrumbs;
+    }
+
+    /**
+     * BreadCrumb controller callback
+     */
+    @Override
+    public void onTop(int level, Object data) {
+        onFolderChange(level, data);
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (mSelectBookmarkView == view) {
+            PopupMenu popup = new PopupMenu(getActivity(), mSelectBookmarkView);
+            popup.getMenuInflater().inflate(R.menu.bookmark_view,
+                    popup.getMenu());
+            popup.setOnMenuItemClickListener(this);
+            popup.show();
+        } else if (mRootFolderView == view) {
+            mCrumbs.clear();
+        }
+    }
+
+    @Override
+    public boolean onMenuItemClick(MenuItem item) {
+        switch (item.getItemId()) {
+        case R.id.list_view:
+            mSelectBookmarkView.setText(R.string.bookmark_list_view);
+            selectView(BrowserBookmarksPage.VIEW_LIST);
+            return true;
+        case R.id.thumbnail_view:
+            mSelectBookmarkView.setText(R.string.bookmark_thumbnail_view);
+            selectView(BrowserBookmarksPage.VIEW_THUMBNAILS);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean onBackPressed() {
+        if (mCrumbs != null &&
+                mCrumbs.size() > 0) {
+            mCrumbs.popView();
+            return true;
+        }
+        return false;
+    }
+
+    public void setCallbackListener(BookmarksPageCallbacks callbackListener) {
+        mCallbacks = callbackListener;
+    }
+
+    public void setEnableContextMenu(boolean enable) {
+        mEnableContextMenu = enable;
+        if (mGrid != null) {
+            if (mEnableContextMenu) {
+                registerForContextMenu(mGrid);
+            } else {
+                unregisterForContextMenu(mGrid);
+                mGrid.setLongClickable(false);
+            }
+        }
+        if (mList != null) {
+            if (mEnableContextMenu) {
+                registerForContextMenu(mList);
+            } else {
+                unregisterForContextMenu(mList);
+                mList.setLongClickable(false);
+            }
+        }
+    }
 }
diff --git a/src/com/android/browser/CombinedBookmarkHistoryView.java b/src/com/android/browser/CombinedBookmarkHistoryView.java
index 9ac357f..15f31f6 100644
--- a/src/com/android/browser/CombinedBookmarkHistoryView.java
+++ b/src/com/android/browser/CombinedBookmarkHistoryView.java
@@ -21,22 +21,19 @@ import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.FragmentTransaction;
-import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.database.Cursor;
 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.view.ViewGroup;
 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;
@@ -49,7 +46,7 @@ interface BookmarksHistoryCallbacks {
 }
 
 public class CombinedBookmarkHistoryView extends LinearLayout
-        implements OnClickListener, BreadCrumbView.Controller, OnMenuItemClickListener {
+        implements OnClickListener {
 
     final static String STARTING_FRAGMENT = "fragment";
 
@@ -64,12 +61,11 @@ public class CombinedBookmarkHistoryView extends LinearLayout
     long mCurrentFragment;
 
     View mTabs;
-    BreadCrumbView mCrumbs;
     TextView mTabBookmarks;
     TextView mTabHistory;
     TextView mAddBookmark;
-    TextView mSelectBookmarkView;
     View mSeperateSelectAdd;
+    ViewGroup mBookmarksHeader;
 
     BrowserBookmarksPage mBookmarks;
     BrowserHistoryPage mHistory;
@@ -123,26 +119,15 @@ public class CombinedBookmarkHistoryView extends LinearLayout
 //        setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
 
         mTabs = findViewById(R.id.tabs);
-        mCrumbs = (BreadCrumbView) findViewById(R.id.crumbs);
-        mCrumbs.setController(this);
+        mBookmarksHeader = (ViewGroup) findViewById(R.id.header_container);
 
         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);
@@ -164,8 +149,26 @@ public class CombinedBookmarkHistoryView extends LinearLayout
 
     }
 
+    private BookmarksPageCallbacks mBookmarkCallbackWrapper = new BookmarksPageCallbacks() {
+        @Override
+        public boolean onOpenInNewWindow(Cursor c) {
+            mUiController.onUrlSelected(BrowserBookmarksPage.getUrl(c), true);
+            return true;
+        }
+
+        @Override
+        public boolean onBookmarkSelected(Cursor c, boolean isFolder) {
+            if (isFolder) {
+                return false;
+            }
+            mUiController.onUrlSelected(BrowserBookmarksPage.getUrl(c), false);
+            return true;
+        }
+    };
+
     private void initFragments(Bundle extras) {
-        mBookmarks =  BrowserBookmarksPage.newInstance(mUiController, mCrumbs, extras);
+        mBookmarks = BrowserBookmarksPage.newInstance(mBookmarkCallbackWrapper,
+                extras, mBookmarksHeader);
         mHistory = BrowserHistoryPage.newInstance(mUiController, extras);
     }
 
@@ -176,17 +179,12 @@ public class CombinedBookmarkHistoryView extends LinearLayout
             case FRAGMENT_ID_BOOKMARKS:
                 fragment = mBookmarks;
                 mSeperateSelectAdd.setVisibility(View.VISIBLE);
-                mSelectBookmarkView.setVisibility(View.VISIBLE);
-                mCrumbs.setVisibility(View.VISIBLE);
-                if (notify) {
-                    mCrumbs.notifyController();
-                }
+                mBookmarksHeader.setVisibility(View.VISIBLE);
                 break;
             case FRAGMENT_ID_HISTORY:
                 fragment = mHistory;
-                mCrumbs.setVisibility(View.GONE);
-                mSeperateSelectAdd.setVisibility(View.GONE);
-                mSelectBookmarkView.setVisibility(View.GONE);
+                mBookmarksHeader.setVisibility(View.INVISIBLE);
+                mSeperateSelectAdd.setVisibility(View.INVISIBLE);
                 break;
             default:
                 throw new IllegalArgumentException();
@@ -220,52 +218,23 @@ public class CombinedBookmarkHistoryView extends LinearLayout
             if (mCurrentFragment != FRAGMENT_ID_BOOKMARKS) {
                 loadFragment(FRAGMENT_ID_BOOKMARKS, mExtras, true);
             } else {
-                mCrumbs.clear();
+                BreadCrumbView crumbs = mBookmarks.getBreadCrumb();
+                if (crumbs != null) {
+                    crumbs.clear();
+                }
             }
         } 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();
         }
     }
 
     /**
-     * BreadCrumb controller callback
-     */
-    @Override
-    public void onTop(int level, Object data) {
-        mBookmarks.onFolderChange(level, data);
-    }
-
-    /**
      * callback for back key presses
      */
     boolean onBackPressed() {
-        if ((mCurrentFragment == FRAGMENT_ID_BOOKMARKS) &&
-                (mCrumbs.size() > 0)) {
-            mCrumbs.popView();
-            return true;
-        }
-        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;
+        if (mCurrentFragment == FRAGMENT_ID_BOOKMARKS) {
+            return mBookmarks.onBackPressed();
         }
         return false;
     }
-
 }
diff --git a/src/com/android/browser/ShortcutActivity.java b/src/com/android/browser/ShortcutActivity.java
index 354d694..57cb4a7 100644
--- a/src/com/android/browser/ShortcutActivity.java
+++ b/src/com/android/browser/ShortcutActivity.java
@@ -17,62 +17,51 @@
 package com.android.browser;
 
 import android.app.Activity;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
 import android.content.Intent;
+import android.database.Cursor;
 import android.os.Bundle;
 
 public class ShortcutActivity extends Activity
-    implements BookmarksHistoryCallbacks {
+    implements BookmarksPageCallbacks {
+
+    private BrowserBookmarksPage mBookmarks;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        // TODO: Is this needed?
         setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
-        FragmentManager fm = getFragmentManager();
-        FragmentTransaction transaction = fm.openTransaction();
-        Bundle extras = new Bundle();
-        extras.putBoolean(BrowserBookmarksPage.EXTRA_SHORTCUT, true);
-        extras.putBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, true);
-        Fragment frag = BrowserBookmarksPage.newInstance(this, null, extras);
-        transaction.add(android.R.id.content, frag);
-        transaction.commit();
+        mBookmarks = BrowserBookmarksPage.newInstance(this, null, null);
+        mBookmarks.setEnableContextMenu(false);
+        mBookmarks.setShowRootFolder(true);
+        getFragmentManager()
+                .openTransaction()
+                .add(android.R.id.content, mBookmarks)
+                .commit();
     }
 
+    // BookmarksPageCallbacks
 
-    /**
-     * handle fragment startActivity
-     */
     @Override
-    public void startActivityFromFragment(Fragment f, Intent intent, int requestCode) {
+    public boolean onBookmarkSelected(Cursor c, boolean isFolder) {
+        if (isFolder) {
+            return false;
+        }
+        Intent intent = BrowserBookmarksPage.createShortcutIntent(this, c);
         setResult(RESULT_OK, intent);
         finish();
+        return true;
     }
 
     @Override
-    public void finish() {
-        super.finish();
+    public boolean onOpenInNewWindow(Cursor c) {
+        return false;
     }
 
-    // BookmarksHistoryCallbacks
-
-    /**
-     * not used for shortcuts
-     */
-    @Override
-    public void onRemoveParentChildRelationships() {}
-
     @Override
-    public void onComboCanceled() {
-        setResult(RESULT_CANCELED);
-        finish();
+    public void onBackPressed() {
+        if (!mBookmarks.onBackPressed()) {
+            super.onBackPressed();
+        }
     }
-
-    /**
-     * not used for shortcuts
-     */
-    @Override
-    public void onUrlSelected(String url, boolean newWindow) {}
-
 }
-- 
cgit v1.1