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