BrowserBookmarksPage.java revision 9db9529bdb7490ccd72fbe66f7e9c9d7cdd73899
1/* 2 * Copyright (C) 2006 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 17package com.android.browser; 18 19import android.app.Activity; 20import android.app.Fragment; 21import android.app.LoaderManager; 22import android.content.ClipData; 23import android.content.ClipboardManager; 24import android.content.ContentUris; 25import android.content.Context; 26import android.content.CursorLoader; 27import android.content.Intent; 28import android.content.Loader; 29import android.content.SharedPreferences; 30import android.content.SharedPreferences.Editor; 31import android.content.res.Configuration; 32import android.content.res.Resources; 33import android.database.Cursor; 34import android.graphics.Bitmap; 35import android.graphics.BitmapFactory; 36import android.net.Uri; 37import android.os.AsyncTask; 38import android.os.Bundle; 39import android.preference.PreferenceManager; 40import android.provider.BrowserContract; 41import android.provider.BrowserContract.Accounts; 42import android.provider.BrowserContract.ChromeSyncColumns; 43import android.view.ActionMode; 44import android.view.ContextMenu; 45import android.view.ContextMenu.ContextMenuInfo; 46import android.view.LayoutInflater; 47import android.view.Menu; 48import android.view.MenuInflater; 49import android.view.MenuItem; 50import android.view.View; 51import android.view.ViewGroup; 52import android.widget.ExpandableListView; 53import android.widget.ExpandableListView.OnChildClickListener; 54import android.widget.ImageView; 55import android.widget.LinearLayout; 56import android.widget.PopupMenu.OnMenuItemClickListener; 57import android.widget.Toast; 58 59import com.android.browser.BookmarkDragHandler.BookmarkDragController; 60import com.android.browser.BookmarkDragHandler.BookmarkDragState; 61import com.android.browser.view.BookmarkExpandableView; 62import com.android.browser.view.BookmarkExpandableView.BookmarkContextMenuInfo; 63 64import java.util.HashMap; 65 66interface BookmarksPageCallbacks { 67 // Return true if handled 68 boolean onBookmarkSelected(Cursor c, boolean isFolder); 69 // Return true if handled 70 boolean onOpenInNewWindow(Cursor c); 71} 72 73/** 74 * View showing the user's bookmarks in the browser. 75 */ 76public class BrowserBookmarksPage extends Fragment implements View.OnCreateContextMenuListener, 77 LoaderManager.LoaderCallbacks<Cursor>, BreadCrumbView.Controller, 78 OnMenuItemClickListener, OnChildClickListener { 79 80 public static class ExtraDragState { 81 public int childPosition; 82 public int groupPosition; 83 } 84 85 static final String LOGTAG = "browser"; 86 87 static final int LOADER_ACCOUNTS = 1; 88 static final int LOADER_BOOKMARKS = 100; 89 90 static final String EXTRA_DISABLE_WINDOW = "disable_new_window"; 91 92 static final String ACCOUNT_TYPE = "account_type"; 93 static final String ACCOUNT_NAME = "account_name"; 94 95 public static final int VIEW_THUMBNAILS = 1; 96 public static final int VIEW_LIST = 2; 97 static final String PREF_SELECTED_VIEW = "bookmarks_view"; 98 99 BookmarksPageCallbacks mCallbacks; 100 View mRoot; 101 BookmarkExpandableView mGrid; 102 boolean mDisableNewWindow; 103 boolean mEnableContextMenu = true; 104 View mEmptyView; 105 int mCurrentView; 106 View mHeader; 107 HashMap<Integer, BrowserBookmarksAdapter> mBookmarkAdapters = new HashMap<Integer, BrowserBookmarksAdapter>(); 108 BookmarkDragHandler mDragHandler; 109 110 static BrowserBookmarksPage newInstance(BookmarksPageCallbacks cb, 111 Bundle args, ViewGroup headerContainer) { 112 BrowserBookmarksPage bbp = new BrowserBookmarksPage(); 113 bbp.mCallbacks = cb; 114 bbp.setArguments(args); 115 return bbp; 116 } 117 118 @Override 119 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 120 if (id == LOADER_ACCOUNTS) { 121 return new AccountsLoader(getActivity()); 122 } else if (id >= LOADER_BOOKMARKS) { 123 String accountType = args.getString(ACCOUNT_TYPE); 124 String accountName = args.getString(ACCOUNT_NAME); 125 BookmarksLoader bl = new BookmarksLoader(getActivity(), 126 accountType, accountName); 127 return bl; 128 } else { 129 throw new UnsupportedOperationException("Unknown loader id " + id); 130 } 131 } 132 133 @Override 134 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 135 if (loader.getId() == LOADER_ACCOUNTS) { 136 LoaderManager lm = getLoaderManager(); 137 int id = LOADER_BOOKMARKS; 138 while (cursor.moveToNext()) { 139 String accountName = cursor.getString(0); 140 String accountType = cursor.getString(1); 141 Bundle args = new Bundle(); 142 args.putString(ACCOUNT_NAME, accountName); 143 args.putString(ACCOUNT_TYPE, accountType); 144 BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter( 145 getActivity(), mCurrentView); 146 mBookmarkAdapters.put(id, adapter); 147 mGrid.addAccount(accountName, adapter); 148 lm.restartLoader(id, args, this); 149 id++; 150 } 151 // TODO: Figure out what a reload of these means 152 // Currently, a reload is triggered whenever bookmarks change 153 // This is less than ideal 154 // It also causes UI flickering as a new adapter is created 155 // instead of re-using an existing one when the account_name is the 156 // same. 157 // For now, this is a one-shot load 158 getLoaderManager().destroyLoader(LOADER_ACCOUNTS); 159 } else if (loader.getId() >= LOADER_BOOKMARKS) { 160 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId()); 161 adapter.changeCursor(cursor); 162 } 163 } 164 165 @Override 166 public void onLoaderReset(Loader<Cursor> loader) { 167 } 168 169 @Override 170 public boolean onContextItemSelected(MenuItem item) { 171 BookmarkContextMenuInfo i = (BookmarkContextMenuInfo)item.getMenuInfo(); 172 // If we have no menu info, we can't tell which item was selected. 173 if (i == null) { 174 return false; 175 } 176 177 if (handleContextItem(item.getItemId(), i.groupPosition, i.childPosition)) { 178 return true; 179 } 180 return super.onContextItemSelected(item); 181 } 182 183 public boolean handleContextItem(int itemId, int groupPosition, 184 int childPosition) { 185 final Activity activity = getActivity(); 186 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition); 187 188 switch (itemId) { 189 case R.id.open_context_menu_id: 190 loadUrl(adapter, childPosition); 191 break; 192 case R.id.edit_context_menu_id: 193 editBookmark(adapter, childPosition); 194 break; 195 case R.id.shortcut_context_menu_id: 196 Cursor c = adapter.getItem(childPosition); 197 activity.sendBroadcast(createShortcutIntent(getActivity(), c)); 198 break; 199 case R.id.delete_context_menu_id: 200 displayRemoveBookmarkDialog(adapter, childPosition); 201 break; 202 case R.id.new_window_context_menu_id: 203 openInNewWindow(adapter, childPosition); 204 break; 205 case R.id.share_link_context_menu_id: { 206 Cursor cursor = adapter.getItem(childPosition); 207 Controller.sharePage(activity, 208 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE), 209 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL), 210 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON), 211 getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_THUMBNAIL)); 212 break; 213 } 214 case R.id.copy_url_context_menu_id: 215 copy(getUrl(adapter, childPosition)); 216 break; 217 case R.id.homepage_context_menu_id: { 218 BrowserSettings.getInstance().setHomePage(getUrl(adapter, childPosition)); 219 Toast.makeText(activity, R.string.homepage_set, Toast.LENGTH_LONG).show(); 220 break; 221 } 222 // Only for the Most visited page 223 case R.id.save_to_bookmarks_menu_id: { 224 Cursor cursor = adapter.getItem(childPosition); 225 String name = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 226 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 227 // If the site is bookmarked, the item becomes remove from 228 // bookmarks. 229 Bookmarks.removeFromBookmarks(activity, activity.getContentResolver(), url, name); 230 break; 231 } 232 default: 233 return false; 234 } 235 return true; 236 } 237 238 static Bitmap getBitmap(Cursor cursor, int columnIndex) { 239 byte[] data = cursor.getBlob(columnIndex); 240 if (data == null) { 241 return null; 242 } 243 return BitmapFactory.decodeByteArray(data, 0, data.length); 244 } 245 246 private MenuItem.OnMenuItemClickListener mContextItemClickListener = 247 new MenuItem.OnMenuItemClickListener() { 248 @Override 249 public boolean onMenuItemClick(MenuItem item) { 250 return onContextItemSelected(item); 251 } 252 }; 253 254 @Override 255 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 256 inflater.inflate(R.menu.bookmark, menu); 257 } 258 259 @Override 260 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 261 BookmarkContextMenuInfo info = (BookmarkContextMenuInfo) menuInfo; 262 BrowserBookmarksAdapter adapter = getChildAdapter(info.groupPosition); 263 Cursor cursor = adapter.getItem(info.childPosition); 264 if (!canEdit(cursor)) { 265 return; 266 } 267 boolean isFolder 268 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 269 270 final Activity activity = getActivity(); 271 MenuInflater inflater = activity.getMenuInflater(); 272 inflater.inflate(R.menu.bookmarkscontext, menu); 273 if (isFolder) { 274 menu.setGroupVisible(R.id.FOLDER_CONTEXT_MENU, true); 275 } else { 276 menu.setGroupVisible(R.id.BOOKMARK_CONTEXT_MENU, true); 277 if (mDisableNewWindow) { 278 menu.findItem(R.id.new_window_context_menu_id).setVisible(false); 279 } 280 } 281 BookmarkItem header = new BookmarkItem(activity); 282 populateBookmarkItem(cursor, header, isFolder); 283 menu.setHeaderView(header); 284 285 int count = menu.size(); 286 for (int i = 0; i < count; i++) { 287 menu.getItem(i).setOnMenuItemClickListener(mContextItemClickListener); 288 } 289 } 290 291 boolean canEdit(Cursor c) { 292 String unique = c.getString(BookmarksLoader.COLUMN_INDEX_SERVER_UNIQUE); 293 return !ChromeSyncColumns.FOLDER_NAME_OTHER_BOOKMARKS.equals(unique); 294 } 295 296 private void populateBookmarkItem(Cursor cursor, BookmarkItem item, boolean isFolder) { 297 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 298 if (isFolder) { 299 item.setUrl(null); 300 Bitmap bitmap = 301 BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder_holo_dark); 302 item.setFavicon(bitmap); 303 new LookupBookmarkCount(getActivity(), item) 304 .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 305 } else { 306 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 307 item.setUrl(url); 308 Bitmap bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 309 if (bitmap == null) { 310 bitmap = CombinedBookmarkHistoryView.getIconListenerSet().getFavicon(url); 311 } 312 item.setFavicon(bitmap); 313 } 314 } 315 316 /** 317 * Create a new BrowserBookmarksPage. 318 */ 319 @Override 320 public void onCreate(Bundle icicle) { 321 super.onCreate(icicle); 322 SharedPreferences prefs = PreferenceManager 323 .getDefaultSharedPreferences(getActivity()); 324 mCurrentView = prefs.getInt(PREF_SELECTED_VIEW, getDefaultView()); 325 326 Bundle args = getArguments(); 327 mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false); 328 329 setHasOptionsMenu(true); 330 } 331 332 @Override 333 public View onCreateView(LayoutInflater inflater, ViewGroup container, 334 Bundle savedInstanceState) { 335 mRoot = inflater.inflate(R.layout.bookmarks, container, false); 336 mEmptyView = mRoot.findViewById(android.R.id.empty); 337 338 mGrid = (BookmarkExpandableView) mRoot.findViewById(R.id.grid); 339 mGrid.setOnChildClickListener(this); 340 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 341 mGrid.setBreadcrumbController(this); 342 setEnableContextMenu(mEnableContextMenu); 343 mDragHandler = new BookmarkDragHandler(getActivity(), mDragController, 344 mGrid.getDragAdapter()); 345 346 // Start the loaders 347 LoaderManager lm = getLoaderManager(); 348 lm.restartLoader(LOADER_ACCOUNTS, null, this); 349 350 return mRoot; 351 } 352 353 private int getDefaultView() { 354 if (BrowserActivity.isTablet(getActivity())) { 355 return VIEW_THUMBNAILS; 356 } 357 return VIEW_LIST; 358 } 359 360 @Override 361 public void onDestroyView() { 362 super.onDestroyView(); 363 mGrid.setBreadcrumbController(null); 364 LoaderManager lm = getLoaderManager(); 365 lm.destroyLoader(LOADER_ACCOUNTS); 366 for (int id : mBookmarkAdapters.keySet()) { 367 lm.destroyLoader(id); 368 } 369 mBookmarkAdapters.clear(); 370 } 371 372 private BrowserBookmarksAdapter getChildAdapter(int groupPosition) { 373 return mGrid.getChildAdapter(groupPosition); 374 } 375 376 private BreadCrumbView getBreadCrumbs(int groupPosition) { 377 return mGrid.getBreadCrumbs(groupPosition); 378 } 379 380 @Override 381 public boolean onChildClick(ExpandableListView parent, View v, 382 int groupPosition, int childPosition, long id) { 383 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition); 384 Cursor cursor = adapter.getItem(childPosition); 385 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 386 if (mCallbacks != null && 387 mCallbacks.onBookmarkSelected(cursor, isFolder)) { 388 return true; 389 } 390 391 // TODO: Folder stuff 392 if (isFolder) { 393 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 394 Uri uri = ContentUris.withAppendedId( 395 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id); 396 BreadCrumbView crumbs = getBreadCrumbs(groupPosition); 397 if (crumbs != null) { 398 // update crumbs 399 crumbs.pushView(title, uri); 400 } 401 loadFolder(groupPosition, uri); 402 } 403 return true; 404 } 405 406 /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) { 407 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 408 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 409 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON); 410 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 411 return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon); 412 } 413 414 private void loadUrl(BrowserBookmarksAdapter adapter, int position) { 415 if (mCallbacks != null && adapter != null) { 416 mCallbacks.onBookmarkSelected(adapter.getItem(position), false); 417 } 418 } 419 420 private void openInNewWindow(BrowserBookmarksAdapter adapter, int position) { 421 if (mCallbacks != null) { 422 Cursor c = adapter.getItem(position); 423 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1; 424 if (isFolder) { 425 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID); 426 new OpenAllInTabsTask(id).execute(); 427 } else { 428 mCallbacks.onOpenInNewWindow(c); 429 } 430 } 431 } 432 433 class OpenAllInTabsTask extends AsyncTask<Void, Void, Cursor> { 434 long mFolderId; 435 public OpenAllInTabsTask(long id) { 436 mFolderId = id; 437 } 438 439 @Override 440 protected Cursor doInBackground(Void... params) { 441 Context c = getActivity(); 442 if (c == null) return null; 443 return c.getContentResolver().query(BookmarkUtils.getBookmarksUri(c), 444 BookmarksLoader.PROJECTION, BrowserContract.Bookmarks.PARENT + "=?", 445 new String[] { Long.toString(mFolderId) }, null); 446 } 447 448 @Override 449 protected void onPostExecute(Cursor result) { 450 if (mCallbacks != null) { 451 while (result.moveToNext()) { 452 mCallbacks.onOpenInNewWindow(result); 453 } 454 } 455 } 456 457 } 458 459 private void editBookmark(BrowserBookmarksAdapter adapter, int position) { 460 Intent intent = new Intent(getActivity(), AddBookmarkPage.class); 461 Cursor cursor = adapter.getItem(position); 462 Bundle item = new Bundle(); 463 item.putString(BrowserContract.Bookmarks.TITLE, 464 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 465 item.putString(BrowserContract.Bookmarks.URL, 466 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL)); 467 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON); 468 if (data != null) { 469 item.putParcelable(BrowserContract.Bookmarks.FAVICON, 470 BitmapFactory.decodeByteArray(data, 0, data.length)); 471 } 472 item.putLong(BrowserContract.Bookmarks._ID, 473 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 474 item.putLong(BrowserContract.Bookmarks.PARENT, 475 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT)); 476 intent.putExtra(AddBookmarkPage.EXTRA_EDIT_BOOKMARK, item); 477 intent.putExtra(AddBookmarkPage.EXTRA_IS_FOLDER, 478 cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1); 479 startActivity(intent); 480 } 481 482 private void displayRemoveBookmarkDialog(BrowserBookmarksAdapter adapter, 483 int position) { 484 // Put up a dialog asking if the user really wants to 485 // delete the bookmark 486 Cursor cursor = adapter.getItem(position); 487 long id = cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID); 488 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 489 Context context = getActivity(); 490 BookmarkUtils.displayRemoveBookmarkDialog(id, title, context, null); 491 } 492 493 private String getUrl(BrowserBookmarksAdapter adapter, int position) { 494 return getUrl(adapter.getItem(position)); 495 } 496 497 /* package */ static String getUrl(Cursor c) { 498 return c.getString(BookmarksLoader.COLUMN_INDEX_URL); 499 } 500 501 private void copy(CharSequence text) { 502 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService( 503 Context.CLIPBOARD_SERVICE); 504 cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString()))); 505 } 506 507 @Override 508 public boolean onOptionsItemSelected(MenuItem item) { 509 switch (item.getItemId()) { 510 case R.id.thumbnail_view: 511 selectView(VIEW_THUMBNAILS); 512 return true; 513 case R.id.list_view: 514 selectView(VIEW_LIST); 515 return true; 516 } 517 return super.onOptionsItemSelected(item); 518 } 519 520 @Override 521 public void onConfigurationChanged(Configuration newConfig) { 522 super.onConfigurationChanged(newConfig); 523 Resources res = getActivity().getResources(); 524 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 525 int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop); 526 mRoot.setPadding(0, paddingTop, 0, 0); 527 getActivity().invalidateOptionsMenu(); 528 } 529 530 @Override 531 public void onPrepareOptionsMenu(Menu menu) { 532 super.onPrepareOptionsMenu(menu); 533 menu.findItem(R.id.list_view).setVisible(mCurrentView != VIEW_LIST); 534 menu.findItem(R.id.thumbnail_view).setVisible(mCurrentView != VIEW_THUMBNAILS); 535 } 536 537 void selectView(int view) { 538 if (view == mCurrentView) { 539 return; 540 } 541 mCurrentView = view; 542 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); 543 Editor edit = prefs.edit(); 544 edit.putInt(PREF_SELECTED_VIEW, mCurrentView); 545 edit.apply(); 546 if (mEmptyView.getVisibility() == View.VISIBLE) { 547 return; 548 } 549 mGrid.selectView(mCurrentView); 550 } 551 552 /** 553 * BreadCrumb controller callback 554 */ 555 @Override 556 public void onTop(BreadCrumbView view, int level, Object data) { 557 int groupPosition = (Integer) view.getTag(R.id.group_position); 558 Uri uri = (Uri) data; 559 if (uri == null) { 560 // top level 561 uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER; 562 } 563 loadFolder(groupPosition, uri); 564 } 565 566 /** 567 * @param uri 568 */ 569 private void loadFolder(int groupPosition, Uri uri) { 570 LoaderManager manager = getLoaderManager(); 571 // This assumes groups are ordered the same as loaders 572 BookmarksLoader loader = (BookmarksLoader) ((Loader<?>) 573 manager.getLoader(LOADER_BOOKMARKS + groupPosition)); 574 loader.setUri(uri); 575 loader.forceLoad(); 576 } 577 578 @Override 579 public boolean onMenuItemClick(MenuItem item) { 580 switch (item.getItemId()) { 581 case R.id.list_view: 582 selectView(BrowserBookmarksPage.VIEW_LIST); 583 return true; 584 case R.id.thumbnail_view: 585 selectView(BrowserBookmarksPage.VIEW_THUMBNAILS); 586 return true; 587 } 588 return false; 589 } 590 591 public boolean onBackPressed() { 592 return false; 593 } 594 595 public void setCallbackListener(BookmarksPageCallbacks callbackListener) { 596 mCallbacks = callbackListener; 597 } 598 599 public void setEnableContextMenu(boolean enable) { 600 mEnableContextMenu = enable; 601 if (mGrid != null) { 602 if (mEnableContextMenu) { 603 registerForContextMenu(mGrid); 604 } else { 605 unregisterForContextMenu(mGrid); 606 mGrid.setLongClickable(false); 607 } 608 } 609 } 610 611 private BookmarkDragController mDragController = new BookmarkDragController() { 612 613 @Override 614 public boolean startDrag(Cursor item) { 615 return canEdit(item); 616 } 617 618 @Override 619 public ViewGroup getActionModeView(ActionMode mode, 620 BookmarkDragState state) { 621 LayoutInflater inflater = LayoutInflater.from(getActivity()); 622 LinearLayout view = (LinearLayout) inflater.inflate( 623 R.layout.bookmarks_drag_actionmode, null); 624 view.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); 625 ExtraDragState extraState = (ExtraDragState) state.extraState; 626 BrowserBookmarksAdapter adapter = getChildAdapter(extraState.groupPosition); 627 Cursor c = adapter.getItem(extraState.childPosition); 628 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 629 if (isFolder) { 630 view.findViewById(R.id.open_context_menu_id).setVisibility(View.GONE); 631 ImageView iv = (ImageView) view.findViewById( 632 R.id.new_window_context_menu_id); 633 iv.setImageResource(R.drawable.ic_windows_holo_dark); 634 } 635 return view; 636 } 637 638 @Override 639 public void actionItemClicked(View v, BookmarkDragState state) { 640 if (v.getId() == R.id.info) { 641 mGrid.showContextMenuForState(state); 642 } else { 643 ExtraDragState extraState = (ExtraDragState) state.extraState; 644 handleContextItem(v.getId(), extraState.groupPosition, 645 extraState.childPosition); 646 } 647 } 648 }; 649 650 private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> { 651 Context mContext; 652 BookmarkItem mHeader; 653 654 public LookupBookmarkCount(Context context, BookmarkItem header) { 655 mContext = context; 656 mHeader = header; 657 } 658 659 @Override 660 protected Integer doInBackground(Long... params) { 661 if (params.length != 1) { 662 throw new IllegalArgumentException("Missing folder id!"); 663 } 664 Uri uri = BookmarkUtils.getBookmarksUri(mContext); 665 Cursor c = mContext.getContentResolver().query(uri, 666 null, BrowserContract.Bookmarks.PARENT + "=?", 667 new String[] {params[0].toString()}, null); 668 return c.getCount(); 669 } 670 671 @Override 672 protected void onPostExecute(Integer result) { 673 if (result > 0) { 674 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_bookmarkcount, 675 result)); 676 } else if (result == 0) { 677 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_empty)); 678 } 679 } 680 } 681 682 static class AccountsLoader extends CursorLoader { 683 684 static String[] ACCOUNTS_PROJECTION = new String[] { 685 Accounts.ACCOUNT_NAME, 686 Accounts.ACCOUNT_TYPE 687 }; 688 689 public AccountsLoader(Context context) { 690 super(context, Accounts.CONTENT_URI, ACCOUNTS_PROJECTION, null, null, 691 Accounts.ACCOUNT_NAME + " ASC"); 692 } 693 694 } 695} 696