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