Bookmark drop CAB

 When dragging a bookmark, show the CAB with drop targets

Change-Id: I2a05800c8ab393f8fba64c46945266566eeacc7f
diff --git a/src/com/android/browser/BookmarkDragHandler.java b/src/com/android/browser/BookmarkDragHandler.java
index 0707058..fc0752f 100644
--- a/src/com/android/browser/BookmarkDragHandler.java
+++ b/src/com/android/browser/BookmarkDragHandler.java
@@ -16,23 +16,30 @@
 
 package com.android.browser;
 
+import android.app.Activity;
 import android.content.ClipData;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
-import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.BrowserContract;
-import android.provider.BrowserContract.Bookmarks;
+import android.view.ActionMode;
+import android.view.ActionMode.Callback;
 import android.view.DragEvent;
+import android.view.Menu;
+import android.view.MenuItem;
 import android.view.View;
 import android.view.View.OnDragListener;
+import android.view.ViewGroup;
 
-public class BookmarkDragHandler {
+public class BookmarkDragHandler implements Callback {
 
     public static interface BookmarkDragController {
         boolean startDrag(Cursor item);
+
+        ViewGroup getActionModeView(ActionMode mode, BookmarkDragState state);
+        void actionItemClicked(View v, BookmarkDragState state);
     }
 
     public static interface BookmarkDragAdapter {
@@ -40,26 +47,29 @@
         Cursor getItemForView(View v);
     }
 
-    static class BookmarkDragState {
-        long id;
-        long parent;
+    public static class BookmarkDragState {
+        public long id;
+        public long parent;
+        public Object extraState;
     }
 
     static final String BOOKMARK_DRAG_LABEL = "com.android.browser.BOOKMARK_LABEL";
 
-    private Context mContext;
+    private Activity mActivity;
     private BookmarkDragController mDragController;
     private BookmarkDragAdapter mDragAdapter;
+    private ActionMode mActionMode;
+    private BookmarkDragState mDragState;
 
-    public BookmarkDragHandler(Context context, BookmarkDragController controller,
+    public BookmarkDragHandler(Activity activity, BookmarkDragController controller,
             BookmarkDragAdapter adapter) {
-        mContext = context;
+        mActivity = activity;
         mDragController = controller;
         mDragAdapter = adapter;
         mDragAdapter.setBookmarkDragHandler(this);
     }
 
-    public boolean startDrag(View view, Cursor item, long id) {
+    public boolean startDrag(View view, Cursor item, long id, Object extraState) {
         if (!mDragController.startDrag(item)) {
             return false;
         }
@@ -69,7 +79,10 @@
         BookmarkDragState state = new BookmarkDragState();
         state.id = id;
         state.parent = item.getLong(BookmarksLoader.COLUMN_INDEX_PARENT);
+        state.extraState = extraState;
+        mDragState = state;
         view.startDrag(data, new View.DragShadowBuilder(view), state, 0);
+        mActionMode = view.startActionMode(this);
         return true;
     }
 
@@ -98,9 +111,9 @@
                     parent = c.getLong(BookmarksLoader.COLUMN_INDEX_ID);
                 }
                 if (parent != state.parent) {
-                    ContentResolver cr = mContext.getContentResolver();
+                    ContentResolver cr = mActivity.getContentResolver();
                     ContentValues values = new ContentValues();
-                    values.put(Bookmarks.PARENT, parent);
+                    values.put(BrowserContract.Bookmarks.PARENT, parent);
                     Uri uri = event.getClipData().getItemAt(0).getUri();
                     cr.update(uri, values, null, null);
                 }
@@ -110,7 +123,55 @@
         }
     };
 
+    private OnDragListener mActionModeDragListener = new OnDragListener() {
+
+        @Override
+        public boolean onDrag(View v, DragEvent event) {
+            BookmarkDragState state = (BookmarkDragState) event.getLocalState();
+            switch (event.getAction()) {
+            case DragEvent.ACTION_DRAG_STARTED:
+                return true;
+            case DragEvent.ACTION_DROP:
+                mDragController.actionItemClicked(v, state);
+                // fall through
+            case DragEvent.ACTION_DRAG_ENDED:
+                if (mActionMode != null) {
+                    mActionMode.finish();
+                    mActionMode = null;
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+
     static boolean isFolder(Cursor c) {
         return c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
     }
+
+    @Override
+    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+        ViewGroup view = mDragController.getActionModeView(mode, mDragState);
+        int count = view.getChildCount();
+        for (int i = 0; i < count; i++) {
+            view.getChildAt(i).setOnDragListener(mActionModeDragListener);
+        }
+        mode.setCustomView(view);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+        return true;
+    }
+
+    @Override
+    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+        return false;
+    }
+
+    @Override
+    public void onDestroyActionMode(ActionMode mode) {
+    }
+
 }
diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java
index caf8a83..d4d1c0d 100644
--- a/src/com/android/browser/BrowserBookmarksPage.java
+++ b/src/com/android/browser/BrowserBookmarksPage.java
@@ -16,10 +16,6 @@
 
 package com.android.browser;
 
-import com.android.browser.BookmarkDragHandler.BookmarkDragController;
-import com.android.browser.view.BookmarkExpandableGridView;
-import com.android.browser.view.BookmarkExpandableGridView.BookmarkContextMenuInfo;
-
 import android.app.Activity;
 import android.app.Fragment;
 import android.app.LoaderManager;
@@ -44,6 +40,7 @@
 import android.provider.BrowserContract;
 import android.provider.BrowserContract.Accounts;
 import android.provider.BrowserContract.ChromeSyncColumns;
+import android.view.ActionMode;
 import android.view.ContextMenu;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.LayoutInflater;
@@ -55,10 +52,17 @@
 import android.webkit.WebIconDatabase.IconListener;
 import android.widget.ExpandableListView;
 import android.widget.ExpandableListView.OnChildClickListener;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.ListView;
 import android.widget.PopupMenu.OnMenuItemClickListener;
 import android.widget.Toast;
 
+import com.android.browser.BookmarkDragHandler.BookmarkDragController;
+import com.android.browser.BookmarkDragHandler.BookmarkDragState;
+import com.android.browser.view.BookmarkExpandableGridView;
+import com.android.browser.view.BookmarkExpandableGridView.BookmarkContextMenuInfo;
+
 import java.util.HashMap;
 
 interface BookmarksPageCallbacks {
@@ -75,6 +79,11 @@
         LoaderManager.LoaderCallbacks<Cursor>, IconListener,
         BreadCrumbView.Controller, OnMenuItemClickListener, OnChildClickListener {
 
+    public static class ExtraDragState {
+        public int childPosition;
+        public int groupPosition;
+    }
+
     static final String LOGTAG = "browser";
 
     static final int LOADER_ACCOUNTS = 1;
@@ -179,33 +188,42 @@
 
     @Override
     public boolean onContextItemSelected(MenuItem item) {
-        final Activity activity = getActivity();
         BookmarkContextMenuInfo i = (BookmarkContextMenuInfo)item.getMenuInfo();
         // If we have no menu info, we can't tell which item was selected.
         if (i == null) {
             return false;
         }
-        BrowserBookmarksAdapter adapter = getChildAdapter(i.groupPosition);
 
-        switch (item.getItemId()) {
+        if (handleContextItem(item.getItemId(), i.groupPosition, i.childPosition)) {
+            return true;
+        }
+        return super.onContextItemSelected(item);
+    }
+
+    public boolean handleContextItem(int itemId, int groupPosition,
+            int childPosition) {
+        final Activity activity = getActivity();
+        BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition);
+
+        switch (itemId) {
         case R.id.open_context_menu_id:
-            loadUrl(adapter, i.childPosition);
+            loadUrl(adapter, childPosition);
             break;
         case R.id.edit_context_menu_id:
-            editBookmark(adapter, i.childPosition);
+            editBookmark(adapter, childPosition);
             break;
         case R.id.shortcut_context_menu_id:
-            Cursor c = adapter.getItem(i.childPosition);
+            Cursor c = adapter.getItem(childPosition);
             activity.sendBroadcast(createShortcutIntent(getActivity(), c));
             break;
         case R.id.delete_context_menu_id:
-            displayRemoveBookmarkDialog(adapter, i.childPosition);
+            displayRemoveBookmarkDialog(adapter, childPosition);
             break;
         case R.id.new_window_context_menu_id:
-            openInNewWindow(adapter, i.childPosition);
+            openInNewWindow(adapter, childPosition);
             break;
         case R.id.share_link_context_menu_id: {
-            Cursor cursor = adapter.getItem(i.childPosition);
+            Cursor cursor = adapter.getItem(childPosition);
             Controller.sharePage(activity,
                     cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE),
                     cursor.getString(BookmarksLoader.COLUMN_INDEX_URL),
@@ -214,16 +232,16 @@
             break;
         }
         case R.id.copy_url_context_menu_id:
-            copy(getUrl(adapter, i.childPosition));
+            copy(getUrl(adapter, childPosition));
             break;
         case R.id.homepage_context_menu_id: {
-            BrowserSettings.getInstance().setHomePage(getUrl(adapter, i.childPosition));
+            BrowserSettings.getInstance().setHomePage(getUrl(adapter, childPosition));
             Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show();
             break;
         }
         // Only for the Most visited page
         case R.id.save_to_bookmarks_menu_id: {
-            Cursor cursor = adapter.getItem(i.childPosition);
+            Cursor cursor = adapter.getItem(childPosition);
             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
@@ -232,7 +250,7 @@
             break;
         }
         default:
-            return super.onContextItemSelected(item);
+            return false;
         }
         return true;
     }
@@ -684,6 +702,41 @@
         public boolean startDrag(Cursor item) {
             return canEdit(item);
         }
+
+        @Override
+        public ViewGroup getActionModeView(ActionMode mode,
+                BookmarkDragState state) {
+            LayoutInflater inflater = LayoutInflater.from(getActivity());
+            LinearLayout view = (LinearLayout) inflater.inflate(
+                    R.layout.bookmarks_drag_actionmode, null);
+            view.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
+            ExtraDragState extraState = (ExtraDragState) state.extraState;
+            BrowserBookmarksAdapter adapter = getChildAdapter(extraState.groupPosition);
+            Cursor c = adapter.getItem(extraState.childPosition);
+            boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0;
+            if (isFolder) {
+                view.findViewById(R.id.open_context_menu_id).setVisibility(View.GONE);
+                ImageView iv = (ImageView) view.findViewById(
+                        R.id.new_window_context_menu_id);
+                iv.setImageResource(R.drawable.ic_windows_holo_dark);
+            }
+            return view;
+        }
+
+        @Override
+        public void actionItemClicked(View v, BookmarkDragState state) {
+            if (v.getId() == R.id.info) {
+                if (mCurrentView == VIEW_THUMBNAILS) {
+                    mGrid.showContextMenuForState(state);
+                } else {
+                    // TODO: Support expandable list
+                }
+            } else {
+                ExtraDragState extraState = (ExtraDragState) state.extraState;
+                handleContextItem(v.getId(), extraState.groupPosition,
+                        extraState.childPosition);
+            }
+        }
     };
 
     private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> {
diff --git a/src/com/android/browser/view/BookmarkExpandableGridView.java b/src/com/android/browser/view/BookmarkExpandableGridView.java
index 2cf4a65..f6b9f19 100644
--- a/src/com/android/browser/view/BookmarkExpandableGridView.java
+++ b/src/com/android/browser/view/BookmarkExpandableGridView.java
@@ -16,13 +16,6 @@
 
 package com.android.browser.view;
 
-import com.android.browser.BookmarkDragHandler;
-import com.android.browser.BreadCrumbView;
-import com.android.browser.BrowserBookmarksAdapter;
-import com.android.browser.R;
-import com.android.browser.BookmarkDragHandler.BookmarkDragAdapter;
-import com.android.internal.view.menu.MenuBuilder;
-
 import android.content.Context;
 import android.database.Cursor;
 import android.database.DataSetObserver;
@@ -40,6 +33,15 @@
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.browser.BookmarkDragHandler;
+import com.android.browser.BookmarkDragHandler.BookmarkDragAdapter;
+import com.android.browser.BookmarkDragHandler.BookmarkDragState;
+import com.android.browser.BreadCrumbView;
+import com.android.browser.BrowserBookmarksAdapter;
+import com.android.browser.BrowserBookmarksPage.ExtraDragState;
+import com.android.browser.R;
+import com.android.internal.view.menu.MenuBuilder;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -206,6 +208,16 @@
         return mDragAdapter;
     }
 
+    public void showContextMenuForState(BookmarkDragState state) {
+        ExtraDragState extraState = (ExtraDragState) state.extraState;
+        mContextMenuInfo = new BookmarkContextMenuInfo(
+                extraState.childPosition,
+                extraState.groupPosition);
+        if (getParent() != null) {
+            getParent().showContextMenuForChild(BookmarkExpandableGridView.this);
+        }
+    }
+
     private BookmarkDragAdapter mDragAdapter = new BookmarkDragAdapter() {
 
         @Override
@@ -219,6 +231,7 @@
             int childPosition = (Integer) v.getTag(R.id.child_position);
             return getChildAdapter(groupPosition).getItem(childPosition);
         }
+
     };
 
     private OnClickListener mChildClickListener = new OnClickListener() {
@@ -252,11 +265,13 @@
 
         @Override
         public boolean onLongClick(View v) {
-            int groupPosition = (Integer) v.getTag(R.id.group_position);
-            int childPosition = (Integer) v.getTag(R.id.child_position);
+            ExtraDragState state = new ExtraDragState();
+            state.groupPosition = (Integer) v.getTag(R.id.group_position);
+            state.childPosition = (Integer) v.getTag(R.id.child_position);
             long id = (Long) v.getTag(R.id.child_id);
-            Cursor c = getChildAdapter(groupPosition).getItem(childPosition);
-            return mDragHandler.startDrag(v, c, id);
+            Cursor c = getChildAdapter(state.groupPosition)
+                    .getItem(state.childPosition);
+            return mDragHandler.startDrag(v, c, id, state);
         }
     };