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