BrowserBookmarksPage.java revision fde9746ac3055848e110c35f19ec5893c621f766
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.AlertDialog; 21import android.content.DialogInterface; 22import android.content.Intent; 23import android.content.SharedPreferences; 24import android.content.SharedPreferences.Editor; 25import android.graphics.Bitmap; 26import android.graphics.BitmapFactory; 27import android.graphics.Canvas; 28import android.graphics.Color; 29import android.graphics.Paint; 30import android.graphics.Path; 31import android.graphics.PorterDuff; 32import android.graphics.PorterDuffXfermode; 33import android.graphics.RectF; 34import android.net.Uri; 35import android.os.Bundle; 36import android.os.Handler; 37import android.os.Message; 38import android.os.ServiceManager; 39import android.provider.Browser; 40import android.text.IClipboard; 41import android.util.Log; 42import android.view.ContextMenu; 43import android.view.KeyEvent; 44import android.view.LayoutInflater; 45import android.view.Menu; 46import android.view.MenuInflater; 47import android.view.MenuItem; 48import android.view.View; 49import android.view.ViewGroup; 50import android.view.ViewGroup.LayoutParams; 51import android.view.ViewStub; 52import android.view.ContextMenu.ContextMenuInfo; 53import android.widget.AdapterView; 54import android.widget.GridView; 55import android.widget.ListView; 56import android.widget.Toast; 57 58/*package*/ enum BookmarkViewMode { NONE, GRID, LIST } 59/** 60 * View showing the user's bookmarks in the browser. 61 */ 62public class BrowserBookmarksPage extends Activity implements 63 View.OnCreateContextMenuListener { 64 65 private BookmarkViewMode mViewMode = BookmarkViewMode.NONE; 66 private GridView mGridPage; 67 private ListView mVerticalList; 68 private BrowserBookmarksAdapter mBookmarksAdapter; 69 private static final int BOOKMARKS_SAVE = 1; 70 private boolean mDisableNewWindow; 71 private BookmarkItem mContextHeader; 72 private AddNewBookmark mAddHeader; 73 private boolean mCanceled = false; 74 private boolean mCreateShortcut; 75 private boolean mMostVisited; 76 private View mEmptyView; 77 // XXX: There is no public string defining this intent so if Home changes 78 // the value, we have to update this string. 79 private static final String INSTALL_SHORTCUT = 80 "com.android.launcher.action.INSTALL_SHORTCUT"; 81 82 private final static String LOGTAG = "browser"; 83 private final static String PREF_BOOKMARK_VIEW_MODE = "pref_bookmark_view_mode"; 84 private final static String PREF_MOST_VISITED_VIEW_MODE = "pref_most_visited_view_mode"; 85 86 @Override 87 public boolean onContextItemSelected(MenuItem item) { 88 // It is possible that the view has been canceled when we get to 89 // this point as back has a higher priority 90 if (mCanceled) { 91 return true; 92 } 93 AdapterView.AdapterContextMenuInfo i = 94 (AdapterView.AdapterContextMenuInfo)item.getMenuInfo(); 95 // If we have no menu info, we can't tell which item was selected. 96 if (i == null) { 97 return true; 98 } 99 100 switch (item.getItemId()) { 101 case R.id.new_context_menu_id: 102 saveCurrentPage(); 103 break; 104 case R.id.open_context_menu_id: 105 loadUrl(i.position); 106 break; 107 case R.id.edit_context_menu_id: 108 editBookmark(i.position); 109 break; 110 case R.id.shortcut_context_menu_id: 111 final Intent send = createShortcutIntent(i.position); 112 send.setAction(INSTALL_SHORTCUT); 113 sendBroadcast(send); 114 break; 115 case R.id.delete_context_menu_id: 116 if (mMostVisited) { 117 Browser.deleteFromHistory(getContentResolver(), 118 getUrl(i.position)); 119 refreshList(); 120 } else { 121 displayRemoveBookmarkDialog(i.position); 122 } 123 break; 124 case R.id.new_window_context_menu_id: 125 openInNewWindow(i.position); 126 break; 127 case R.id.share_link_context_menu_id: 128 Browser.sendString(BrowserBookmarksPage.this, getUrl(i.position), 129 getText(R.string.choosertitle_sharevia).toString()); 130 break; 131 case R.id.copy_url_context_menu_id: 132 copy(getUrl(i.position)); 133 break; 134 case R.id.homepage_context_menu_id: 135 BrowserSettings.getInstance().setHomePage(this, 136 getUrl(i.position)); 137 Toast.makeText(this, R.string.homepage_set, 138 Toast.LENGTH_LONG).show(); 139 break; 140 // Only for the Most visited page 141 case R.id.save_to_bookmarks_menu_id: 142 boolean isBookmark; 143 String name; 144 String url; 145 if (mViewMode == BookmarkViewMode.GRID) { 146 isBookmark = mBookmarksAdapter.getIsBookmark(i.position); 147 name = mBookmarksAdapter.getTitle(i.position); 148 url = mBookmarksAdapter.getUrl(i.position); 149 } else { 150 HistoryItem historyItem = ((HistoryItem) i.targetView); 151 isBookmark = historyItem.isBookmark(); 152 name = historyItem.getName(); 153 url = historyItem.getUrl(); 154 } 155 // If the site is bookmarked, the item becomes remove from 156 // bookmarks. 157 if (isBookmark) { 158 Bookmarks.removeFromBookmarks(this, getContentResolver(), url, name); 159 } else { 160 Browser.saveBookmark(this, name, url); 161 } 162 break; 163 default: 164 return super.onContextItemSelected(item); 165 } 166 return true; 167 } 168 169 @Override 170 public void onCreateContextMenu(ContextMenu menu, View v, 171 ContextMenuInfo menuInfo) { 172 AdapterView.AdapterContextMenuInfo i = 173 (AdapterView.AdapterContextMenuInfo) menuInfo; 174 175 MenuInflater inflater = getMenuInflater(); 176 if (mMostVisited) { 177 inflater.inflate(R.menu.historycontext, menu); 178 } else { 179 inflater.inflate(R.menu.bookmarkscontext, menu); 180 } 181 182 if (0 == i.position && !mMostVisited) { 183 menu.setGroupVisible(R.id.CONTEXT_MENU, false); 184 if (mAddHeader == null) { 185 mAddHeader = new AddNewBookmark(BrowserBookmarksPage.this); 186 } else if (mAddHeader.getParent() != null) { 187 ((ViewGroup) mAddHeader.getParent()). 188 removeView(mAddHeader); 189 } 190 mAddHeader.setUrl(getIntent().getStringExtra("url")); 191 menu.setHeaderView(mAddHeader); 192 return; 193 } 194 if (mMostVisited) { 195 if ((mViewMode == BookmarkViewMode.LIST 196 && ((HistoryItem) i.targetView).isBookmark()) 197 || mBookmarksAdapter.getIsBookmark(i.position)) { 198 MenuItem item = menu.findItem( 199 R.id.save_to_bookmarks_menu_id); 200 item.setTitle(R.string.remove_from_bookmarks); 201 } 202 } else { 203 // The historycontext menu has no ADD_MENU group. 204 menu.setGroupVisible(R.id.ADD_MENU, false); 205 } 206 if (mDisableNewWindow) { 207 menu.findItem(R.id.new_window_context_menu_id).setVisible( 208 false); 209 } 210 if (mContextHeader == null) { 211 mContextHeader = new BookmarkItem(BrowserBookmarksPage.this); 212 } else if (mContextHeader.getParent() != null) { 213 ((ViewGroup) mContextHeader.getParent()). 214 removeView(mContextHeader); 215 } 216 if (mViewMode == BookmarkViewMode.GRID) { 217 mBookmarksAdapter.populateBookmarkItem(mContextHeader, 218 i.position); 219 } else { 220 BookmarkItem b = (BookmarkItem) i.targetView; 221 b.copyTo(mContextHeader); 222 } 223 menu.setHeaderView(mContextHeader); 224 } 225 226 /** 227 * Create a new BrowserBookmarksPage. 228 */ 229 @Override 230 protected void onCreate(Bundle icicle) { 231 super.onCreate(icicle); 232 233 if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) { 234 mCreateShortcut = true; 235 } 236 mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window", 237 false); 238 mMostVisited = getIntent().getBooleanExtra("mostVisited", false); 239 240 if (mCreateShortcut) { 241 setTitle(R.string.browser_bookmarks_page_bookmarks_text); 242 } 243 mHandler.obtainMessage(CREATE_ADAPTER).sendToTarget(); 244 245 setContentView(R.layout.empty_history); 246 mEmptyView = findViewById(R.id.empty_view); 247 mEmptyView.setVisibility(View.GONE); 248 249 SharedPreferences p = getPreferences(MODE_PRIVATE); 250 251 // See if the user has set a preference for the view mode of their 252 // bookmarks. Otherwise default to grid mode. 253 BookmarkViewMode preference = BookmarkViewMode.NONE; 254 if (mMostVisited) { 255 // For the most visited page, only use list mode. 256 preference = BookmarkViewMode.LIST; 257 } else { 258 preference = BookmarkViewMode.values()[p.getInt( 259 PREF_BOOKMARK_VIEW_MODE, BookmarkViewMode.GRID.ordinal())]; 260 } 261 switchViewMode(preference); 262 } 263 264 /** 265 * Set the ContentView to be either the grid of thumbnails or the vertical 266 * list. 267 */ 268 private void switchViewMode(BookmarkViewMode viewMode) { 269 if (mViewMode == viewMode) { 270 return; 271 } 272 273 mViewMode = viewMode; 274 275 // Update the preferences to make the new view mode sticky. 276 Editor ed = getPreferences(MODE_PRIVATE).edit(); 277 if (mMostVisited) { 278 ed.putInt(PREF_MOST_VISITED_VIEW_MODE, mViewMode.ordinal()); 279 } else { 280 ed.putInt(PREF_BOOKMARK_VIEW_MODE, mViewMode.ordinal()); 281 } 282 ed.commit(); 283 284 if (mBookmarksAdapter != null) { 285 mBookmarksAdapter.switchViewMode(viewMode); 286 } 287 if (mViewMode == BookmarkViewMode.GRID) { 288 if (mGridPage == null) { 289 mGridPage = new GridView(this); 290 if (mBookmarksAdapter != null) { 291 mGridPage.setAdapter(mBookmarksAdapter); 292 } 293 mGridPage.setOnItemClickListener(mListener); 294 mGridPage.setNumColumns(GridView.AUTO_FIT); 295 mGridPage.setColumnWidth( 296 BrowserActivity.getDesiredThumbnailWidth(this)); 297 mGridPage.setFocusable(true); 298 mGridPage.setFocusableInTouchMode(true); 299 mGridPage.setSelector(android.R.drawable.gallery_thumb); 300 float density = getResources().getDisplayMetrics().density; 301 mGridPage.setVerticalSpacing((int) (14 * density)); 302 mGridPage.setHorizontalSpacing((int) (8 * density)); 303 mGridPage.setStretchMode(GridView.STRETCH_SPACING); 304 mGridPage.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); 305 mGridPage.setDrawSelectorOnTop(true); 306 if (mMostVisited) { 307 mGridPage.setEmptyView(mEmptyView); 308 } 309 if (!mCreateShortcut) { 310 mGridPage.setOnCreateContextMenuListener(this); 311 } 312 } 313 addContentView(mGridPage, FULL_SCREEN_PARAMS); 314 if (mVerticalList != null) { 315 ViewGroup parent = (ViewGroup) mVerticalList.getParent(); 316 if (parent != null) { 317 parent.removeView(mVerticalList); 318 } 319 } 320 } else { 321 if (null == mVerticalList) { 322 ListView listView = new ListView(this); 323 if (mBookmarksAdapter != null) { 324 listView.setAdapter(mBookmarksAdapter); 325 } 326 listView.setDrawSelectorOnTop(false); 327 listView.setVerticalScrollBarEnabled(true); 328 listView.setOnItemClickListener(mListener); 329 if (mMostVisited) { 330 listView.setEmptyView(mEmptyView); 331 } 332 if (!mCreateShortcut) { 333 listView.setOnCreateContextMenuListener(this); 334 } 335 mVerticalList = listView; 336 } 337 addContentView(mVerticalList, FULL_SCREEN_PARAMS); 338 if (mGridPage != null) { 339 ViewGroup parent = (ViewGroup) mGridPage.getParent(); 340 if (parent != null) { 341 parent.removeView(mGridPage); 342 } 343 } 344 } 345 } 346 347 private static final ViewGroup.LayoutParams FULL_SCREEN_PARAMS 348 = new ViewGroup.LayoutParams( 349 ViewGroup.LayoutParams.FILL_PARENT, 350 ViewGroup.LayoutParams.FILL_PARENT); 351 352 private static final int SAVE_CURRENT_PAGE = 1000; 353 private static final int CREATE_ADAPTER = 1001; 354 private final Handler mHandler = new Handler() { 355 @Override 356 public void handleMessage(Message msg) { 357 switch (msg.what) { 358 case SAVE_CURRENT_PAGE: 359 saveCurrentPage(); 360 break; 361 case CREATE_ADAPTER: 362 Intent intent = getIntent(); 363 mBookmarksAdapter = new BrowserBookmarksAdapter( 364 BrowserBookmarksPage.this, 365 intent.getStringExtra("url"), 366 intent.getStringExtra("title"), 367 (Bitmap) intent.getParcelableExtra("thumbnail"), 368 mCreateShortcut, 369 mMostVisited); 370 mBookmarksAdapter.switchViewMode(mViewMode); 371 if (mGridPage != null) { 372 mGridPage.setAdapter(mBookmarksAdapter); 373 } 374 if (mVerticalList != null) { 375 mVerticalList.setAdapter(mBookmarksAdapter); 376 } 377 break; 378 } 379 } 380 }; 381 382 private AdapterView.OnItemClickListener mListener = new AdapterView.OnItemClickListener() { 383 public void onItemClick(AdapterView parent, View v, int position, long id) { 384 // It is possible that the view has been canceled when we get to 385 // this point as back has a higher priority 386 if (mCanceled) { 387 android.util.Log.e(LOGTAG, "item clicked when dismissing"); 388 return; 389 } 390 if (!mCreateShortcut) { 391 if (0 == position && !mMostVisited) { 392 // XXX: Work-around for a framework issue. 393 mHandler.sendEmptyMessage(SAVE_CURRENT_PAGE); 394 } else { 395 loadUrl(position); 396 } 397 } else { 398 final Intent intent = createShortcutIntent(position); 399 setResultToParent(RESULT_OK, intent); 400 finish(); 401 } 402 } 403 }; 404 405 private Intent createShortcutIntent(int position) { 406 String url = getUrl(position); 407 String title = getBookmarkTitle(position); 408 Bitmap touchIcon = getTouchIcon(position); 409 410 final Intent i = new Intent(); 411 final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW, 412 Uri.parse(url)); 413 long urlHash = url.hashCode(); 414 long uniqueId = (urlHash << 32) | shortcutIntent.hashCode(); 415 shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID, 416 Long.toString(uniqueId)); 417 i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); 418 i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title); 419 // Use the apple-touch-icon if available 420 if (touchIcon != null) { 421 // Make a copy so we can modify the pixels. 422 Bitmap copy = touchIcon.copy(Bitmap.Config.ARGB_8888, true); 423 Canvas canvas = new Canvas(copy); 424 425 // Construct a path from a round rect. This will allow drawing with 426 // an inverse fill so we can punch a hole using the round rect. 427 Path path = new Path(); 428 path.setFillType(Path.FillType.INVERSE_WINDING); 429 RectF rect = new RectF(0, 0, touchIcon.getWidth(), 430 touchIcon.getHeight()); 431 rect.inset(1, 1); 432 path.addRoundRect(rect, 8f, 8f, Path.Direction.CW); 433 434 // Construct a paint that clears the outside of the rectangle and 435 // draw. 436 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 437 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); 438 canvas.drawPath(path, paint); 439 440 i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy); 441 } else { 442 Bitmap favicon = getFavicon(position); 443 if (favicon == null) { 444 i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, 445 Intent.ShortcutIconResource.fromContext( 446 BrowserBookmarksPage.this, 447 R.drawable.ic_launcher_shortcut_browser_bookmark)); 448 } else { 449 Bitmap icon = BitmapFactory.decodeResource(getResources(), 450 R.drawable.ic_launcher_shortcut_browser_bookmark); 451 452 // Make a copy of the regular icon so we can modify the pixels. 453 Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true); 454 Canvas canvas = new Canvas(copy); 455 456 // Make a Paint for the white background rectangle and for 457 // filtering the favicon. 458 Paint p = new Paint(Paint.ANTI_ALIAS_FLAG 459 | Paint.FILTER_BITMAP_FLAG); 460 p.setStyle(Paint.Style.FILL_AND_STROKE); 461 p.setColor(Color.WHITE); 462 463 float density = getResources().getDisplayMetrics().density; 464 // Create a rectangle that is slightly wider than the favicon 465 final float iconSize = 16 * density; // 16x16 favicon 466 final float padding = 2; // white padding around icon 467 final float rectSize = iconSize + 2 * padding; 468 final float y = icon.getHeight() - rectSize; 469 RectF r = new RectF(0, y, rectSize, y + rectSize); 470 471 // Draw a white rounded rectangle behind the favicon 472 canvas.drawRoundRect(r, 2, 2, p); 473 474 // Draw the favicon in the same rectangle as the rounded 475 // rectangle but inset by the padding 476 // (results in a 16x16 favicon). 477 r.inset(padding, padding); 478 canvas.drawBitmap(favicon, null, r, p); 479 i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy); 480 } 481 } 482 // Do not allow duplicate items 483 i.putExtra("duplicate", false); 484 return i; 485 } 486 487 private void saveCurrentPage() { 488 Intent i = new Intent(BrowserBookmarksPage.this, 489 AddBookmarkPage.class); 490 i.putExtras(getIntent()); 491 startActivityForResult(i, BOOKMARKS_SAVE); 492 } 493 494 private void loadUrl(int position) { 495 Intent intent = (new Intent()).setAction(getUrl(position)); 496 setResultToParent(RESULT_OK, intent); 497 finish(); 498 } 499 500 @Override 501 public boolean onCreateOptionsMenu(Menu menu) { 502 boolean result = super.onCreateOptionsMenu(menu); 503 if (!mCreateShortcut && !mMostVisited) { 504 MenuInflater inflater = getMenuInflater(); 505 inflater.inflate(R.menu.bookmarks, menu); 506 return true; 507 } 508 return result; 509 } 510 511 @Override 512 public boolean onPrepareOptionsMenu(Menu menu) { 513 boolean result = super.onPrepareOptionsMenu(menu); 514 if (mCreateShortcut || mMostVisited || mBookmarksAdapter == null 515 || mBookmarksAdapter.getCount() == 0) { 516 // No need to show the menu if there are no items. 517 return result; 518 } 519 MenuItem switchItem = menu.findItem(R.id.switch_mode_menu_id); 520 int titleResId; 521 int iconResId; 522 if (mViewMode == BookmarkViewMode.GRID) { 523 titleResId = R.string.switch_to_list; 524 iconResId = R.drawable.ic_menu_list; 525 } else { 526 titleResId = R.string.switch_to_thumbnails; 527 iconResId = R.drawable.ic_menu_thumbnail; 528 } 529 switchItem.setTitle(titleResId); 530 switchItem.setIcon(iconResId); 531 return true; 532 } 533 534 @Override 535 public boolean onOptionsItemSelected(MenuItem item) { 536 switch (item.getItemId()) { 537 case R.id.new_context_menu_id: 538 saveCurrentPage(); 539 break; 540 541 case R.id.switch_mode_menu_id: 542 if (mViewMode == BookmarkViewMode.GRID) { 543 switchViewMode(BookmarkViewMode.LIST); 544 } else { 545 switchViewMode(BookmarkViewMode.GRID); 546 } 547 break; 548 549 default: 550 return super.onOptionsItemSelected(item); 551 } 552 return true; 553 } 554 555 private void openInNewWindow(int position) { 556 Bundle b = new Bundle(); 557 b.putBoolean("new_window", true); 558 setResultToParent(RESULT_OK, 559 (new Intent()).setAction(getUrl(position)).putExtras(b)); 560 561 finish(); 562 } 563 564 565 private void editBookmark(int position) { 566 Intent intent = new Intent(BrowserBookmarksPage.this, 567 AddBookmarkPage.class); 568 intent.putExtra("bookmark", getRow(position)); 569 startActivityForResult(intent, BOOKMARKS_SAVE); 570 } 571 572 @Override 573 protected void onActivityResult(int requestCode, int resultCode, 574 Intent data) { 575 switch(requestCode) { 576 case BOOKMARKS_SAVE: 577 if (resultCode == RESULT_OK) { 578 Bundle extras; 579 if (data != null && (extras = data.getExtras()) != null) { 580 // If there are extras, then we need to save 581 // the edited bookmark. This is done in updateRow() 582 String title = extras.getString("title"); 583 String url = extras.getString("url"); 584 if (title != null && url != null) { 585 mBookmarksAdapter.updateRow(extras); 586 } 587 } else { 588 // extras == null then a new bookmark was added to 589 // the database. 590 refreshList(); 591 } 592 } 593 break; 594 default: 595 break; 596 } 597 } 598 599 private void displayRemoveBookmarkDialog(int position) { 600 // Put up a dialog asking if the user really wants to 601 // delete the bookmark 602 final int deletePos = position; 603 new AlertDialog.Builder(this) 604 .setTitle(R.string.delete_bookmark) 605 .setIcon(android.R.drawable.ic_dialog_alert) 606 .setMessage(getText(R.string.delete_bookmark_warning).toString().replace( 607 "%s", getBookmarkTitle(deletePos))) 608 .setPositiveButton(R.string.ok, 609 new DialogInterface.OnClickListener() { 610 public void onClick(DialogInterface dialog, int whichButton) { 611 deleteBookmark(deletePos); 612 } 613 }) 614 .setNegativeButton(R.string.cancel, null) 615 .show(); 616 } 617 618 /** 619 * Refresh the shown list after the database has changed. 620 */ 621 private void refreshList() { 622 mBookmarksAdapter.refreshList(); 623 } 624 625 /** 626 * Return a hashmap representing the currently highlighted row. 627 */ 628 public Bundle getRow(int position) { 629 return mBookmarksAdapter == null ? null 630 : mBookmarksAdapter.getRow(position); 631 } 632 633 /** 634 * Return the url of the currently highlighted row. 635 */ 636 public String getUrl(int position) { 637 return mBookmarksAdapter == null ? null 638 : mBookmarksAdapter.getUrl(position); 639 } 640 641 /** 642 * Return the favicon of the currently highlighted row. 643 */ 644 public Bitmap getFavicon(int position) { 645 return mBookmarksAdapter == null ? null 646 : mBookmarksAdapter.getFavicon(position); 647 } 648 649 private Bitmap getTouchIcon(int position) { 650 return mBookmarksAdapter == null ? null 651 : mBookmarksAdapter.getTouchIcon(position); 652 } 653 654 private void copy(CharSequence text) { 655 try { 656 IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard")); 657 if (clip != null) { 658 clip.setClipboardText(text); 659 } 660 } catch (android.os.RemoteException e) { 661 Log.e(LOGTAG, "Copy failed", e); 662 } 663 } 664 665 public String getBookmarkTitle(int position) { 666 return mBookmarksAdapter == null ? null 667 : mBookmarksAdapter.getTitle(position); 668 } 669 670 /** 671 * Delete the currently highlighted row. 672 */ 673 public void deleteBookmark(int position) { 674 if (mBookmarksAdapter == null) return; 675 mBookmarksAdapter.deleteRow(position); 676 } 677 678 @Override 679 public void onBackPressed() { 680 setResultToParent(RESULT_CANCELED, null); 681 mCanceled = true; 682 super.onBackPressed(); 683 } 684 685 // This Activity is generally a sub-Activity of 686 // CombinedBookmarkHistoryActivity. In that situation, we need to pass our 687 // result code up to our parent. However, if someone calls this Activity 688 // directly, then this has no parent, and it needs to set it on itself. 689 private void setResultToParent(int resultCode, Intent data) { 690 Activity parent = getParent(); 691 if (parent == null) { 692 setResult(resultCode, data); 693 } else { 694 ((CombinedBookmarkHistoryActivity) parent).setResultFromChild( 695 resultCode, data); 696 } 697 } 698} 699