BrowserBookmarksPage.java revision f94abcf44fc1611f76e55461f48220e621fc31b7
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.res.Configuration; 31import android.content.res.Resources; 32import android.database.Cursor; 33import android.graphics.Bitmap; 34import android.graphics.BitmapFactory; 35import android.graphics.BitmapFactory.Options; 36import android.net.Uri; 37import android.os.AsyncTask; 38import android.os.Bundle; 39import android.provider.BrowserContract; 40import android.provider.BrowserContract.Accounts; 41import android.view.ActionMode; 42import android.view.ContextMenu; 43import android.view.ContextMenu.ContextMenuInfo; 44import android.view.LayoutInflater; 45import android.view.MenuInflater; 46import android.view.MenuItem; 47import android.view.View; 48import android.view.ViewGroup; 49import android.widget.ExpandableListView; 50import android.widget.ExpandableListView.OnChildClickListener; 51import android.widget.ImageView; 52import android.widget.LinearLayout; 53import android.widget.Toast; 54 55import com.android.browser.BookmarkDragHandler.BookmarkDragController; 56import com.android.browser.BookmarkDragHandler.BookmarkDragState; 57import com.android.browser.provider.BrowserProvider2; 58import com.android.browser.view.BookmarkExpandableView; 59import com.android.browser.view.BookmarkExpandableView.BookmarkContextMenuInfo; 60 61import org.json.JSONException; 62import org.json.JSONObject; 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(String... urls); 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 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 static final String PREF_GROUP_STATE = "bbp_group_state"; 92 93 static final String ACCOUNT_TYPE = "account_type"; 94 static final String ACCOUNT_NAME = "account_name"; 95 96 public static final int VIEW_THUMBNAILS = 1; 97 public static final int VIEW_LIST = 2; 98 99 BookmarksPageCallbacks mCallbacks; 100 View mRoot; 101 BookmarkExpandableView mGrid; 102 boolean mDisableNewWindow; 103 boolean mEnableContextMenu = true; 104 View mEmptyView; 105 View mHeader; 106 HashMap<Integer, BrowserBookmarksAdapter> mBookmarkAdapters = new HashMap<Integer, BrowserBookmarksAdapter>(); 107 BookmarkDragHandler mDragHandler; 108 JSONObject mState; 109 110 @Override 111 public Loader<Cursor> onCreateLoader(int id, Bundle args) { 112 if (id == LOADER_ACCOUNTS) { 113 return new AccountsLoader(getActivity()); 114 } else if (id >= LOADER_BOOKMARKS) { 115 String accountType = args.getString(ACCOUNT_TYPE); 116 String accountName = args.getString(ACCOUNT_NAME); 117 BookmarksLoader bl = new BookmarksLoader(getActivity(), 118 accountType, accountName); 119 return bl; 120 } else { 121 throw new UnsupportedOperationException("Unknown loader id " + id); 122 } 123 } 124 125 @Override 126 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 127 if (loader.getId() == LOADER_ACCOUNTS) { 128 LoaderManager lm = getLoaderManager(); 129 int id = LOADER_BOOKMARKS; 130 while (cursor.moveToNext()) { 131 String accountName = cursor.getString(0); 132 String accountType = cursor.getString(1); 133 Bundle args = new Bundle(); 134 args.putString(ACCOUNT_NAME, accountName); 135 args.putString(ACCOUNT_TYPE, accountType); 136 BrowserBookmarksAdapter adapter = new BrowserBookmarksAdapter( 137 getActivity(), VIEW_THUMBNAILS); 138 mBookmarkAdapters.put(id, adapter); 139 boolean expand = true; 140 try { 141 expand = mState.getBoolean(accountName != null ? accountName 142 : BookmarkExpandableView.LOCAL_ACCOUNT_NAME); 143 } catch (JSONException e) {} // no state for accountName 144 mGrid.addAccount(accountName, adapter, expand); 145 lm.restartLoader(id, args, this); 146 id++; 147 } 148 // TODO: Figure out what a reload of these means 149 // Currently, a reload is triggered whenever bookmarks change 150 // This is less than ideal 151 // It also causes UI flickering as a new adapter is created 152 // instead of re-using an existing one when the account_name is the 153 // same. 154 // For now, this is a one-shot load 155 getLoaderManager().destroyLoader(LOADER_ACCOUNTS); 156 } else if (loader.getId() >= LOADER_BOOKMARKS) { 157 BrowserBookmarksAdapter adapter = mBookmarkAdapters.get(loader.getId()); 158 adapter.changeCursor(cursor); 159 } 160 } 161 162 @Override 163 public void onLoaderReset(Loader<Cursor> loader) { 164 } 165 166 @Override 167 public boolean onContextItemSelected(MenuItem item) { 168 if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) { 169 return false; 170 } 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 return getBitmap(cursor, columnIndex, null); 240 } 241 242 static ThreadLocal<Options> sOptions = new ThreadLocal<Options>() { 243 @Override 244 protected Options initialValue() { 245 return new Options(); 246 }; 247 }; 248 static Bitmap getBitmap(Cursor cursor, int columnIndex, Bitmap inBitmap) { 249 byte[] data = cursor.getBlob(columnIndex); 250 if (data == null) { 251 return null; 252 } 253 Options opts = sOptions.get(); 254 opts.inBitmap = inBitmap; 255 opts.inSampleSize = 1; 256 opts.inScaled = false; 257 try { 258 return BitmapFactory.decodeByteArray(data, 0, data.length, opts); 259 } catch (IllegalArgumentException ex) { 260 // Failed to re-use bitmap, create a new one 261 return BitmapFactory.decodeByteArray(data, 0, data.length); 262 } 263 } 264 265 private MenuItem.OnMenuItemClickListener mContextItemClickListener = 266 new MenuItem.OnMenuItemClickListener() { 267 @Override 268 public boolean onMenuItemClick(MenuItem item) { 269 return onContextItemSelected(item); 270 } 271 }; 272 273 @Override 274 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 275 BookmarkContextMenuInfo info = (BookmarkContextMenuInfo) menuInfo; 276 BrowserBookmarksAdapter adapter = getChildAdapter(info.groupPosition); 277 Cursor cursor = adapter.getItem(info.childPosition); 278 if (!canEdit(cursor)) { 279 return; 280 } 281 boolean isFolder 282 = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 283 284 final Activity activity = getActivity(); 285 MenuInflater inflater = activity.getMenuInflater(); 286 inflater.inflate(R.menu.bookmarkscontext, menu); 287 if (isFolder) { 288 menu.setGroupVisible(R.id.FOLDER_CONTEXT_MENU, true); 289 } else { 290 menu.setGroupVisible(R.id.BOOKMARK_CONTEXT_MENU, true); 291 if (mDisableNewWindow) { 292 menu.findItem(R.id.new_window_context_menu_id).setVisible(false); 293 } 294 } 295 BookmarkItem header = new BookmarkItem(activity); 296 header.setEnableScrolling(true); 297 populateBookmarkItem(cursor, header, isFolder); 298 menu.setHeaderView(header); 299 300 int count = menu.size(); 301 for (int i = 0; i < count; i++) { 302 menu.getItem(i).setOnMenuItemClickListener(mContextItemClickListener); 303 } 304 } 305 306 boolean canEdit(Cursor c) { 307 int type = c.getInt(BookmarksLoader.COLUMN_INDEX_TYPE); 308 return type == BrowserContract.Bookmarks.BOOKMARK_TYPE_BOOKMARK 309 || type == BrowserContract.Bookmarks.BOOKMARK_TYPE_FOLDER; 310 } 311 312 private void populateBookmarkItem(Cursor cursor, BookmarkItem item, boolean isFolder) { 313 item.setName(cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 314 if (isFolder) { 315 item.setUrl(null); 316 Bitmap bitmap = 317 BitmapFactory.decodeResource(getResources(), R.drawable.ic_folder_holo_dark); 318 item.setFavicon(bitmap); 319 new LookupBookmarkCount(getActivity(), item) 320 .execute(cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 321 } else { 322 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 323 item.setUrl(url); 324 Bitmap bitmap = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 325 item.setFavicon(bitmap); 326 } 327 } 328 329 /** 330 * Create a new BrowserBookmarksPage. 331 */ 332 @Override 333 public void onCreate(Bundle icicle) { 334 super.onCreate(icicle); 335 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences(); 336 try { 337 mState = new JSONObject(prefs.getString(PREF_GROUP_STATE, "{}")); 338 } catch (JSONException e) { 339 // Parse failed, clear preference and start with empty state 340 prefs.edit().remove(PREF_GROUP_STATE).apply(); 341 mState = new JSONObject(); 342 } 343 Bundle args = getArguments(); 344 mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false); 345 setHasOptionsMenu(true); 346 if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) { 347 mCallbacks = new CombinedBookmarksCallbackWrapper( 348 (CombinedBookmarksCallbacks) getActivity()); 349 } 350 } 351 352 @Override 353 public void onPause() { 354 super.onPause(); 355 try { 356 mState = mGrid.saveGroupState(); 357 // Save state 358 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences(); 359 prefs.edit() 360 .putString(PREF_GROUP_STATE, mState.toString()) 361 .apply(); 362 } catch (JSONException e) { 363 // Not critical, ignore 364 } 365 } 366 367 private static class CombinedBookmarksCallbackWrapper 368 implements BookmarksPageCallbacks { 369 370 private CombinedBookmarksCallbacks mCombinedCallback; 371 372 private CombinedBookmarksCallbackWrapper(CombinedBookmarksCallbacks cb) { 373 mCombinedCallback = cb; 374 } 375 376 @Override 377 public boolean onOpenInNewWindow(String... urls) { 378 mCombinedCallback.openInNewTab(urls); 379 return true; 380 } 381 382 @Override 383 public boolean onBookmarkSelected(Cursor c, boolean isFolder) { 384 if (isFolder) { 385 return false; 386 } 387 mCombinedCallback.openUrl(BrowserBookmarksPage.getUrl(c)); 388 return true; 389 } 390 }; 391 392 @Override 393 public View onCreateView(LayoutInflater inflater, ViewGroup container, 394 Bundle savedInstanceState) { 395 mRoot = inflater.inflate(R.layout.bookmarks, container, false); 396 mEmptyView = mRoot.findViewById(android.R.id.empty); 397 398 mGrid = (BookmarkExpandableView) mRoot.findViewById(R.id.grid); 399 mGrid.setOnChildClickListener(this); 400 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 401 mGrid.setBreadcrumbController(this); 402 setEnableContextMenu(mEnableContextMenu); 403 mDragHandler = new BookmarkDragHandler(getActivity(), mDragController, 404 mGrid.getDragAdapter()); 405 406 // Start the loaders 407 LoaderManager lm = getLoaderManager(); 408 lm.restartLoader(LOADER_ACCOUNTS, null, this); 409 410 return mRoot; 411 } 412 413 @Override 414 public void onDestroyView() { 415 super.onDestroyView(); 416 mGrid.setBreadcrumbController(null); 417 mGrid.clearAccounts(); 418 LoaderManager lm = getLoaderManager(); 419 lm.destroyLoader(LOADER_ACCOUNTS); 420 for (int id : mBookmarkAdapters.keySet()) { 421 lm.destroyLoader(id); 422 } 423 mBookmarkAdapters.clear(); 424 } 425 426 private BrowserBookmarksAdapter getChildAdapter(int groupPosition) { 427 return mGrid.getChildAdapter(groupPosition); 428 } 429 430 private BreadCrumbView getBreadCrumbs(int groupPosition) { 431 return mGrid.getBreadCrumbs(groupPosition); 432 } 433 434 @Override 435 public boolean onChildClick(ExpandableListView parent, View v, 436 int groupPosition, int childPosition, long id) { 437 BrowserBookmarksAdapter adapter = getChildAdapter(groupPosition); 438 Cursor cursor = adapter.getItem(childPosition); 439 boolean isFolder = cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 440 if (mCallbacks != null && 441 mCallbacks.onBookmarkSelected(cursor, isFolder)) { 442 return true; 443 } 444 445 if (isFolder) { 446 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 447 Uri uri = ContentUris.withAppendedId( 448 BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER, id); 449 BreadCrumbView crumbs = getBreadCrumbs(groupPosition); 450 if (crumbs != null) { 451 // update crumbs 452 crumbs.pushView(title, uri); 453 crumbs.setVisibility(View.VISIBLE); 454 } 455 loadFolder(groupPosition, uri); 456 } 457 return true; 458 } 459 460 /* package */ static Intent createShortcutIntent(Context context, Cursor cursor) { 461 String url = cursor.getString(BookmarksLoader.COLUMN_INDEX_URL); 462 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 463 Bitmap touchIcon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_TOUCH_ICON); 464 Bitmap favicon = getBitmap(cursor, BookmarksLoader.COLUMN_INDEX_FAVICON); 465 return BookmarkUtils.createAddToHomeIntent(context, url, title, touchIcon, favicon); 466 } 467 468 private void loadUrl(BrowserBookmarksAdapter adapter, int position) { 469 if (mCallbacks != null && adapter != null) { 470 mCallbacks.onBookmarkSelected(adapter.getItem(position), false); 471 } 472 } 473 474 private void openInNewWindow(BrowserBookmarksAdapter adapter, int position) { 475 if (mCallbacks != null) { 476 Cursor c = adapter.getItem(position); 477 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1; 478 if (isFolder) { 479 long id = c.getLong(BookmarksLoader.COLUMN_INDEX_ID); 480 new OpenAllInTabsTask(id).execute(); 481 } else { 482 mCallbacks.onOpenInNewWindow(BrowserBookmarksPage.getUrl(c)); 483 } 484 } 485 } 486 487 class OpenAllInTabsTask extends AsyncTask<Void, Void, Cursor> { 488 long mFolderId; 489 public OpenAllInTabsTask(long id) { 490 mFolderId = id; 491 } 492 493 @Override 494 protected Cursor doInBackground(Void... params) { 495 Context c = getActivity(); 496 if (c == null) return null; 497 return c.getContentResolver().query(BookmarkUtils.getBookmarksUri(c), 498 BookmarksLoader.PROJECTION, BrowserContract.Bookmarks.PARENT + "=?", 499 new String[] { Long.toString(mFolderId) }, null); 500 } 501 502 @Override 503 protected void onPostExecute(Cursor result) { 504 if (mCallbacks != null && result.getCount() > 0) { 505 String[] urls = new String[result.getCount()]; 506 int i = 0; 507 while (result.moveToNext()) { 508 urls[i++] = BrowserBookmarksPage.getUrl(result); 509 } 510 mCallbacks.onOpenInNewWindow(urls); 511 } 512 } 513 514 } 515 516 private void editBookmark(BrowserBookmarksAdapter adapter, int position) { 517 Intent intent = new Intent(getActivity(), AddBookmarkPage.class); 518 Cursor cursor = adapter.getItem(position); 519 Bundle item = new Bundle(); 520 item.putString(BrowserContract.Bookmarks.TITLE, 521 cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE)); 522 item.putString(BrowserContract.Bookmarks.URL, 523 cursor.getString(BookmarksLoader.COLUMN_INDEX_URL)); 524 byte[] data = cursor.getBlob(BookmarksLoader.COLUMN_INDEX_FAVICON); 525 if (data != null) { 526 item.putParcelable(BrowserContract.Bookmarks.FAVICON, 527 BitmapFactory.decodeByteArray(data, 0, data.length)); 528 } 529 item.putLong(BrowserContract.Bookmarks._ID, 530 cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID)); 531 item.putLong(BrowserContract.Bookmarks.PARENT, 532 cursor.getLong(BookmarksLoader.COLUMN_INDEX_PARENT)); 533 intent.putExtra(AddBookmarkPage.EXTRA_EDIT_BOOKMARK, item); 534 intent.putExtra(AddBookmarkPage.EXTRA_IS_FOLDER, 535 cursor.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) == 1); 536 startActivity(intent); 537 } 538 539 private void displayRemoveBookmarkDialog(BrowserBookmarksAdapter adapter, 540 int position) { 541 // Put up a dialog asking if the user really wants to 542 // delete the bookmark 543 Cursor cursor = adapter.getItem(position); 544 long id = cursor.getLong(BookmarksLoader.COLUMN_INDEX_ID); 545 String title = cursor.getString(BookmarksLoader.COLUMN_INDEX_TITLE); 546 Context context = getActivity(); 547 BookmarkUtils.displayRemoveBookmarkDialog(id, title, context, null); 548 } 549 550 private String getUrl(BrowserBookmarksAdapter adapter, int position) { 551 return getUrl(adapter.getItem(position)); 552 } 553 554 /* package */ static String getUrl(Cursor c) { 555 return c.getString(BookmarksLoader.COLUMN_INDEX_URL); 556 } 557 558 private void copy(CharSequence text) { 559 ClipboardManager cm = (ClipboardManager) getActivity().getSystemService( 560 Context.CLIPBOARD_SERVICE); 561 cm.setPrimaryClip(ClipData.newRawUri(null, Uri.parse(text.toString()))); 562 } 563 564 @Override 565 public void onConfigurationChanged(Configuration newConfig) { 566 super.onConfigurationChanged(newConfig); 567 Resources res = getActivity().getResources(); 568 mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); 569 int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop); 570 mRoot.setPadding(0, paddingTop, 0, 0); 571 getActivity().invalidateOptionsMenu(); 572 } 573 574 /** 575 * BreadCrumb controller callback 576 */ 577 @Override 578 public void onTop(BreadCrumbView view, int level, Object data) { 579 int groupPosition = (Integer) view.getTag(R.id.group_position); 580 Uri uri = (Uri) data; 581 if (uri == null) { 582 // top level 583 uri = BrowserContract.Bookmarks.CONTENT_URI_DEFAULT_FOLDER; 584 } 585 loadFolder(groupPosition, uri); 586 if (level <= 1) { 587 view.setVisibility(View.GONE); 588 } else { 589 view.setVisibility(View.VISIBLE); 590 } 591 } 592 593 /** 594 * @param uri 595 */ 596 private void loadFolder(int groupPosition, Uri uri) { 597 LoaderManager manager = getLoaderManager(); 598 // This assumes groups are ordered the same as loaders 599 BookmarksLoader loader = (BookmarksLoader) ((Loader<?>) 600 manager.getLoader(LOADER_BOOKMARKS + groupPosition)); 601 loader.setUri(uri); 602 loader.forceLoad(); 603 } 604 605 public void setCallbackListener(BookmarksPageCallbacks callbackListener) { 606 mCallbacks = callbackListener; 607 } 608 609 public void setEnableContextMenu(boolean enable) { 610 mEnableContextMenu = enable; 611 if (mGrid != null) { 612 if (mEnableContextMenu) { 613 registerForContextMenu(mGrid); 614 } else { 615 unregisterForContextMenu(mGrid); 616 mGrid.setLongClickable(false); 617 } 618 } 619 } 620 621 private BookmarkDragController mDragController = new BookmarkDragController() { 622 623 @Override 624 public boolean startDrag(Cursor item) { 625 return canEdit(item); 626 } 627 628 @Override 629 public ViewGroup getActionModeView(ActionMode mode, 630 BookmarkDragState state) { 631 LayoutInflater inflater = LayoutInflater.from(getActivity()); 632 LinearLayout view = (LinearLayout) inflater.inflate( 633 R.layout.bookmarks_drag_actionmode, null); 634 view.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE); 635 ExtraDragState extraState = (ExtraDragState) state.extraState; 636 BrowserBookmarksAdapter adapter = getChildAdapter(extraState.groupPosition); 637 Cursor c = adapter.getItem(extraState.childPosition); 638 boolean isFolder = c.getInt(BookmarksLoader.COLUMN_INDEX_IS_FOLDER) != 0; 639 if (isFolder) { 640 view.findViewById(R.id.open_context_menu_id).setVisibility(View.GONE); 641 ImageView iv = (ImageView) view.findViewById( 642 R.id.new_window_context_menu_id); 643 iv.setImageResource(R.drawable.ic_windows_holo_dark); 644 } 645 return view; 646 } 647 648 @Override 649 public void actionItemClicked(View v, BookmarkDragState state) { 650 if (v.getId() == R.id.info) { 651 mGrid.showContextMenuForState(state); 652 } else { 653 ExtraDragState extraState = (ExtraDragState) state.extraState; 654 handleContextItem(v.getId(), extraState.groupPosition, 655 extraState.childPosition); 656 } 657 } 658 }; 659 660 private static class LookupBookmarkCount extends AsyncTask<Long, Void, Integer> { 661 Context mContext; 662 BookmarkItem mHeader; 663 664 public LookupBookmarkCount(Context context, BookmarkItem header) { 665 mContext = context.getApplicationContext(); 666 mHeader = header; 667 } 668 669 @Override 670 protected Integer doInBackground(Long... params) { 671 if (params.length != 1) { 672 throw new IllegalArgumentException("Missing folder id!"); 673 } 674 Uri uri = BookmarkUtils.getBookmarksUri(mContext); 675 Cursor c = mContext.getContentResolver().query(uri, 676 null, BrowserContract.Bookmarks.PARENT + "=?", 677 new String[] {params[0].toString()}, null); 678 return c.getCount(); 679 } 680 681 @Override 682 protected void onPostExecute(Integer result) { 683 if (result > 0) { 684 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_bookmarkcount, 685 result)); 686 } else if (result == 0) { 687 mHeader.setUrl(mContext.getString(R.string.contextheader_folder_empty)); 688 } 689 } 690 } 691 692 static class AccountsLoader extends CursorLoader { 693 694 static String[] ACCOUNTS_PROJECTION = new String[] { 695 Accounts.ACCOUNT_NAME, 696 Accounts.ACCOUNT_TYPE 697 }; 698 699 public AccountsLoader(Context context) { 700 super(context, Accounts.CONTENT_URI 701 .buildUpon() 702 .appendQueryParameter(BrowserProvider2.PARAM_ALLOW_EMPTY_ACCOUNTS, "false") 703 .build(), 704 ACCOUNTS_PROJECTION, null, null, null); 705 } 706 707 } 708} 709