1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.browser; 18 19 import android.app.Activity; 20 import android.content.ClipData; 21 import android.content.ContentResolver; 22 import android.content.ContentUris; 23 import android.content.ContentValues; 24 import android.database.Cursor; 25 import android.net.Uri; 26 import android.provider.BrowserContract; 27 import android.view.ActionMode; 28 import android.view.ActionMode.Callback; 29 import android.view.DragEvent; 30 import android.view.Menu; 31 import android.view.MenuItem; 32 import android.view.View; 33 import android.view.View.OnDragListener; 34 import android.view.ViewGroup; 35 36 public class BookmarkDragHandler implements Callback { 37 38 public static interface BookmarkDragController { 39 boolean startDrag(Cursor item); 40 41 ViewGroup getActionModeView(ActionMode mode, BookmarkDragState state); 42 void actionItemClicked(View v, BookmarkDragState state); 43 } 44 45 public static interface BookmarkDragAdapter { 46 void setBookmarkDragHandler(BookmarkDragHandler handler); 47 Cursor getItemForView(View v); 48 } 49 50 public static class BookmarkDragState { 51 public long id; 52 public long parent; 53 public Object extraState; 54 } 55 56 static final String BOOKMARK_DRAG_LABEL = "com.android.browser.BOOKMARK_LABEL"; 57 58 private Activity mActivity; 59 private BookmarkDragController mDragController; 60 private BookmarkDragAdapter mDragAdapter; 61 private ActionMode mActionMode; 62 private BookmarkDragState mDragState; 63 64 public BookmarkDragHandler(Activity activity, BookmarkDragController controller, 65 BookmarkDragAdapter adapter) { 66 mActivity = activity; 67 mDragController = controller; 68 mDragAdapter = adapter; 69 mDragAdapter.setBookmarkDragHandler(this); 70 } 71 72 public boolean startDrag(View view, Cursor item, long id, Object extraState) { 73 if (!mDragController.startDrag(item)) { 74 return false; 75 } 76 Uri uri = ContentUris.withAppendedId( 77 BrowserContract.Bookmarks.CONTENT_URI, id); 78 ClipData data = ClipData.newRawUri(BOOKMARK_DRAG_LABEL, uri); 79 BookmarkDragState state = new BookmarkDragState(); 80 state.id = id; 81 state.parent = item.getLong(BookmarksLoader.COLUMN_INDEX_PARENT); 82 state.extraState = extraState; 83 mDragState = state; 84 view.startDrag(data, new View.DragShadowBuilder(view), state, 0); 85 mActionMode = view.startActionMode(this); 86 return true; 87 } 88 89 public void registerBookmarkDragHandler(View view) { 90 view.setOnDragListener(mBookmarkDragListener); 91 } 92 93 private OnDragListener mBookmarkDragListener = new OnDragListener() { 94 95 @Override 96 public boolean onDrag(View v, DragEvent event) { 97 Cursor c = mDragAdapter.getItemForView(v); 98 BookmarkDragState state = (BookmarkDragState) event.getLocalState(); 99 switch (event.getAction()) { 100 case DragEvent.ACTION_DRAG_STARTED: 101 return true; 102 case DragEvent.ACTION_DROP: 103 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID); 104 if (id == state.id) { 105 // We dropped onto ourselves, show the context menu 106 v.showContextMenu(); 107 return false; 108 } 109 long parent = c.getLong(BookmarksLoader.COLUMN_INDEX_PARENT); 110 if (isFolder(c)) { 111 parent = c.getLong(BookmarksLoader.COLUMN_INDEX_ID); 112 } 113 if (parent != state.parent) { 114 ContentResolver cr = mActivity.getContentResolver(); 115 ContentValues values = new ContentValues(); 116 values.put(BrowserContract.Bookmarks.PARENT, parent); 117 Uri uri = event.getClipData().getItemAt(0).getUri(); 118 cr.update(uri, values, null, null); 119 } 120 break; 121 } 122 return false; 123 } 124 }; 125 126 private OnDragListener mActionModeDragListener = new OnDragListener() { 127 128 @Override 129 public boolean onDrag(View v, DragEvent event) { 130 BookmarkDragState state = (BookmarkDragState) event.getLocalState(); 131 switch (event.getAction()) { 132 case DragEvent.ACTION_DRAG_STARTED: 133 return true; 134 case DragEvent.ACTION_DROP: 135 mDragController.actionItemClicked(v, state); 136 // fall through 137 case DragEvent.ACTION_DRAG_ENDED: 138 if (mActionMode != null) { 139 mActionMode.finish(); 140 mActionMode = null; 141 } 142 return true; 143 } 144 return false; 145 } 146 }; 147 148 static boolean isFolder(Cursor c) { 149 return c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 150 } 151 152 @Override 153 public boolean onCreateActionMode(ActionMode mode, Menu menu) { 154 ViewGroup view = mDragController.getActionModeView(mode, mDragState); 155 int count = view.getChildCount(); 156 for (int i = 0; i < count; i++) { 157 view.getChildAt(i).setOnDragListener(mActionModeDragListener); 158 } 159 mode.setCustomView(view); 160 return true; 161 } 162 163 @Override 164 public boolean onPrepareActionMode(ActionMode mode, Menu menu) { 165 return true; 166 } 167 168 @Override 169 public boolean onActionItemClicked(ActionMode mode, MenuItem item) { 170 return false; 171 } 172 173 @Override 174 public void onDestroyActionMode(ActionMode mode) { 175 } 176 177 } 178