blob: 7e72ae95490f70c5b97d517fd253aea540218cdb [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
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.graphics.Bitmap;
Patrick Scotte09761e2009-03-24 20:43:37 -070024import android.graphics.BitmapFactory;
25import android.graphics.Canvas;
26import android.graphics.Color;
27import android.graphics.Paint;
Patrick Scott3918d442009-08-04 13:22:29 -040028import android.graphics.Path;
29import android.graphics.PorterDuff;
30import android.graphics.PorterDuffXfermode;
Patrick Scotte09761e2009-03-24 20:43:37 -070031import android.graphics.RectF;
The Android Open Source Project0c908882009-03-03 19:32:16 -080032import android.net.Uri;
33import android.os.Bundle;
34import android.os.Handler;
35import android.os.Message;
36import android.os.ServiceManager;
37import android.provider.Browser;
38import android.text.IClipboard;
39import android.util.Log;
40import android.view.ContextMenu;
41import android.view.KeyEvent;
Leon Scroggins892df312009-07-14 14:48:02 -040042import android.view.LayoutInflater;
The Android Open Source Project0c908882009-03-03 19:32:16 -080043import android.view.Menu;
44import android.view.MenuInflater;
45import android.view.MenuItem;
46import android.view.View;
47import android.view.ViewGroup;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040048import android.view.ViewGroup.LayoutParams;
49import android.view.ViewStub;
The Android Open Source Project0c908882009-03-03 19:32:16 -080050import android.view.ContextMenu.ContextMenuInfo;
51import android.widget.AdapterView;
Leon Scroggins89c6d362009-07-15 16:54:37 -040052import android.widget.GridView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080053import android.widget.ListView;
Leon Scrogginsfeb941d2009-05-28 17:27:38 -040054import android.widget.Toast;
The Android Open Source Project0c908882009-03-03 19:32:16 -080055
56/**
57 * View showing the user's bookmarks in the browser.
58 */
59public class BrowserBookmarksPage extends Activity implements
60 View.OnCreateContextMenuListener {
61
Leon Scroggins892df312009-07-14 14:48:02 -040062 private boolean mGridMode;
Leon Scroggins89c6d362009-07-15 16:54:37 -040063 private GridView mGridPage;
Leon Scroggins892df312009-07-14 14:48:02 -040064 private View mVerticalList;
The Android Open Source Project0c908882009-03-03 19:32:16 -080065 private BrowserBookmarksAdapter mBookmarksAdapter;
66 private static final int BOOKMARKS_SAVE = 1;
Leon Scroggins190095d2009-08-17 17:01:38 -040067 private boolean mDisableNewWindow;
The Android Open Source Project0c908882009-03-03 19:32:16 -080068 private BookmarkItem mContextHeader;
69 private AddNewBookmark mAddHeader;
70 private boolean mCanceled = false;
71 private boolean mCreateShortcut;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -040072 private boolean mMostVisited;
73 private View mEmptyView;
The Android Open Source Project0c908882009-03-03 19:32:16 -080074 // XXX: There is no public string defining this intent so if Home changes
75 // the value, we have to update this string.
76 private static final String INSTALL_SHORTCUT =
77 "com.android.launcher.action.INSTALL_SHORTCUT";
78
79 private final static String LOGTAG = "browser";
80
81
82 @Override
83 public boolean onContextItemSelected(MenuItem item) {
84 // It is possible that the view has been canceled when we get to
85 // this point as back has a higher priority
86 if (mCanceled) {
87 return true;
88 }
89 AdapterView.AdapterContextMenuInfo i =
90 (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
91 // If we have no menu info, we can't tell which item was selected.
92 if (i == null) {
93 return true;
94 }
95
96 switch (item.getItemId()) {
97 case R.id.new_context_menu_id:
98 saveCurrentPage();
99 break;
100 case R.id.open_context_menu_id:
101 loadUrl(i.position);
102 break;
103 case R.id.edit_context_menu_id:
104 editBookmark(i.position);
105 break;
106 case R.id.shortcut_context_menu_id:
Patrick Scott3918d442009-08-04 13:22:29 -0400107 final Intent send = createShortcutIntent(i.position);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800108 send.setAction(INSTALL_SHORTCUT);
109 sendBroadcast(send);
110 break;
111 case R.id.delete_context_menu_id:
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400112 if (mMostVisited) {
113 Browser.deleteFromHistory(getContentResolver(),
114 getUrl(i.position));
115 refreshList();
116 } else {
117 displayRemoveBookmarkDialog(i.position);
118 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800119 break;
120 case R.id.new_window_context_menu_id:
121 openInNewWindow(i.position);
122 break;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400123 case R.id.share_link_context_menu_id:
The Android Open Source Project0c908882009-03-03 19:32:16 -0800124 Browser.sendString(BrowserBookmarksPage.this, getUrl(i.position));
125 break;
126 case R.id.copy_url_context_menu_id:
127 copy(getUrl(i.position));
Leon Scrogginsfeb941d2009-05-28 17:27:38 -0400128 break;
129 case R.id.homepage_context_menu_id:
130 BrowserSettings.getInstance().setHomePage(this,
131 getUrl(i.position));
132 Toast.makeText(this, R.string.homepage_set,
133 Toast.LENGTH_LONG).show();
134 break;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400135 // Only for the Most visited page
136 case R.id.save_to_bookmarks_menu_id:
Leon Scrogginsc1f57592009-08-14 14:16:10 -0400137 boolean isBookmark;
138 String name;
139 String url;
140 if (mGridMode) {
141 isBookmark = mBookmarksAdapter.getIsBookmark(i.position);
142 name = mBookmarksAdapter.getTitle(i.position);
143 url = mBookmarksAdapter.getUrl(i.position);
144 } else {
145 HistoryItem historyItem = ((HistoryItem) i.targetView);
146 isBookmark = historyItem.isBookmark();
147 name = historyItem.getName();
148 url = historyItem.getUrl();
149 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400150 // If the site is bookmarked, the item becomes remove from
151 // bookmarks.
Leon Scrogginsc1f57592009-08-14 14:16:10 -0400152 if (isBookmark) {
153 Bookmarks.removeFromBookmarks(this, getContentResolver(), url);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400154 } else {
Leon Scrogginsc1f57592009-08-14 14:16:10 -0400155 Browser.saveBookmark(this, name, url);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400156 }
157 break;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800158 default:
159 return super.onContextItemSelected(item);
160 }
161 return true;
162 }
163
164 @Override
165 public void onCreateContextMenu(ContextMenu menu, View v,
166 ContextMenuInfo menuInfo) {
167 AdapterView.AdapterContextMenuInfo i =
168 (AdapterView.AdapterContextMenuInfo) menuInfo;
169
170 MenuInflater inflater = getMenuInflater();
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400171 if (mMostVisited) {
172 inflater.inflate(R.menu.historycontext, menu);
173 } else {
174 inflater.inflate(R.menu.bookmarkscontext, menu);
175 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800176
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400177 if (0 == i.position && !mMostVisited) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800178 menu.setGroupVisible(R.id.CONTEXT_MENU, false);
179 if (mAddHeader == null) {
180 mAddHeader = new AddNewBookmark(BrowserBookmarksPage.this);
181 } else if (mAddHeader.getParent() != null) {
182 ((ViewGroup) mAddHeader.getParent()).
183 removeView(mAddHeader);
184 }
Leon Scroggins892df312009-07-14 14:48:02 -0400185 mAddHeader.setUrl(getIntent().getStringExtra("url"));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800186 menu.setHeaderView(mAddHeader);
187 return;
188 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400189 if (mMostVisited) {
190 if ((!mGridMode && ((HistoryItem) i.targetView).isBookmark())
191 || mBookmarksAdapter.getIsBookmark(i.position)) {
192 MenuItem item = menu.findItem(
193 R.id.save_to_bookmarks_menu_id);
194 item.setTitle(R.string.remove_from_bookmarks);
195 }
196 } else {
197 // The historycontext menu has no ADD_MENU group.
198 menu.setGroupVisible(R.id.ADD_MENU, false);
199 }
Leon Scroggins190095d2009-08-17 17:01:38 -0400200 if (mDisableNewWindow) {
Leon Scroggins892df312009-07-14 14:48:02 -0400201 menu.findItem(R.id.new_window_context_menu_id).setVisible(
202 false);
203 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800204 if (mContextHeader == null) {
205 mContextHeader = new BookmarkItem(BrowserBookmarksPage.this);
206 } else if (mContextHeader.getParent() != null) {
207 ((ViewGroup) mContextHeader.getParent()).
208 removeView(mContextHeader);
209 }
Leon Scroggins892df312009-07-14 14:48:02 -0400210 if (mGridMode) {
211 mBookmarksAdapter.populateBookmarkItem(mContextHeader,
212 i.position);
213 } else {
214 BookmarkItem b = (BookmarkItem) i.targetView;
215 b.copyTo(mContextHeader);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800216 }
Leon Scroggins892df312009-07-14 14:48:02 -0400217 menu.setHeaderView(mContextHeader);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800218 }
219
220 /**
221 * Create a new BrowserBookmarksPage.
222 */
223 @Override
224 protected void onCreate(Bundle icicle) {
225 super.onCreate(icicle);
226
The Android Open Source Project0c908882009-03-03 19:32:16 -0800227 if (Intent.ACTION_CREATE_SHORTCUT.equals(getIntent().getAction())) {
228 mCreateShortcut = true;
229 }
Leon Scroggins190095d2009-08-17 17:01:38 -0400230 mDisableNewWindow = getIntent().getBooleanExtra("disable_new_window",
231 false);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400232 mMostVisited = getIntent().getBooleanExtra("mostVisited", false);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800233
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400234 if (mCreateShortcut) {
235 setTitle(R.string.browser_bookmarks_page_bookmarks_text);
236 }
Leon Scroggins892df312009-07-14 14:48:02 -0400237 mBookmarksAdapter = new BrowserBookmarksAdapter(this,
Leon Scroggins89c6d362009-07-15 16:54:37 -0400238 getIntent().getStringExtra("url"),
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400239 getIntent().getStringExtra("title"), mCreateShortcut,
240 mMostVisited);
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400241
242 setContentView(R.layout.empty_history);
243 mEmptyView = findViewById(R.id.empty_view);
244 mEmptyView.setVisibility(View.GONE);
245
Leon Scroggins89c6d362009-07-15 16:54:37 -0400246 switchViewMode(true);
Leon Scroggins892df312009-07-14 14:48:02 -0400247 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800248
Leon Scroggins892df312009-07-14 14:48:02 -0400249 /**
250 * Set the ContentView to be either the grid of thumbnails or the vertical
251 * list. Pass true to set it to the grid.
252 */
253 private void switchViewMode(boolean gridMode) {
254 mGridMode = gridMode;
255 mBookmarksAdapter.switchViewMode(gridMode);
256 if (mGridMode) {
257 if (mGridPage == null) {
Leon Scroggins89c6d362009-07-15 16:54:37 -0400258 mGridPage = new GridView(this);
259 mGridPage.setAdapter(mBookmarksAdapter);
Leon Scroggins892df312009-07-14 14:48:02 -0400260 mGridPage.setOnItemClickListener(mListener);
Leon Scroggins89c6d362009-07-15 16:54:37 -0400261 mGridPage.setNumColumns(GridView.AUTO_FIT);
262 // Keep this in sync with bookmark_thumb and
263 // BrowserActivity.updateScreenshot
264 mGridPage.setColumnWidth(100);
265 mGridPage.setFocusable(true);
266 mGridPage.setFocusableInTouchMode(true);
267 mGridPage.setSelector(android.R.drawable.gallery_thumb);
268 mGridPage.setVerticalSpacing(10);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400269 if (mMostVisited) {
270 mGridPage.setEmptyView(mEmptyView);
271 }
Leon Scroggins892df312009-07-14 14:48:02 -0400272 if (!mCreateShortcut) {
273 mGridPage.setOnCreateContextMenuListener(this);
274 }
275 }
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400276 addContentView(mGridPage, FULL_SCREEN_PARAMS);
277 if (mVerticalList != null) {
278 ViewGroup parent = (ViewGroup) mVerticalList.getParent();
279 if (parent != null) {
280 parent.removeView(mVerticalList);
281 }
282 }
Leon Scroggins892df312009-07-14 14:48:02 -0400283 } else {
284 if (null == mVerticalList) {
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400285 ListView listView = new ListView(this);
Leon Scroggins892df312009-07-14 14:48:02 -0400286 listView.setAdapter(mBookmarksAdapter);
287 listView.setDrawSelectorOnTop(false);
288 listView.setVerticalScrollBarEnabled(true);
289 listView.setOnItemClickListener(mListener);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400290 if (mMostVisited) {
291 listView.setEmptyView(mEmptyView);
292 }
Leon Scroggins892df312009-07-14 14:48:02 -0400293 if (!mCreateShortcut) {
294 listView.setOnCreateContextMenuListener(this);
295 }
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400296 mVerticalList = listView;
Leon Scroggins892df312009-07-14 14:48:02 -0400297 }
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400298 addContentView(mVerticalList, FULL_SCREEN_PARAMS);
299 if (mGridPage != null) {
300 ViewGroup parent = (ViewGroup) mGridPage.getParent();
301 if (parent != null) {
302 parent.removeView(mGridPage);
303 }
304 }
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400305 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800306 }
307
Leon Scrogginsd87f85e2009-08-18 14:13:31 -0400308 private static final ViewGroup.LayoutParams FULL_SCREEN_PARAMS
309 = new ViewGroup.LayoutParams(
310 ViewGroup.LayoutParams.FILL_PARENT,
311 ViewGroup.LayoutParams.FILL_PARENT);
312
The Android Open Source Project0c908882009-03-03 19:32:16 -0800313 private static final int SAVE_CURRENT_PAGE = 1000;
314 private final Handler mHandler = new Handler() {
315 @Override
316 public void handleMessage(Message msg) {
317 if (msg.what == SAVE_CURRENT_PAGE) {
318 saveCurrentPage();
319 }
320 }
321 };
322
323 private AdapterView.OnItemClickListener mListener = new AdapterView.OnItemClickListener() {
324 public void onItemClick(AdapterView parent, View v, int position, long id) {
325 // It is possible that the view has been canceled when we get to
326 // this point as back has a higher priority
327 if (mCanceled) {
Leon Scroggins892df312009-07-14 14:48:02 -0400328 android.util.Log.e(LOGTAG, "item clicked when dismissing");
The Android Open Source Project0c908882009-03-03 19:32:16 -0800329 return;
330 }
331 if (!mCreateShortcut) {
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400332 if (0 == position && !mMostVisited) {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800333 // XXX: Work-around for a framework issue.
334 mHandler.sendEmptyMessage(SAVE_CURRENT_PAGE);
335 } else {
336 loadUrl(position);
337 }
338 } else {
Patrick Scott3918d442009-08-04 13:22:29 -0400339 final Intent intent = createShortcutIntent(position);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800340 setResultToParent(RESULT_OK, intent);
341 finish();
342 }
343 }
344 };
345
Patrick Scott3918d442009-08-04 13:22:29 -0400346 private Intent createShortcutIntent(int position) {
347 String url = getUrl(position);
348 String title = getBookmarkTitle(position);
349 Bitmap touchIcon = getTouchIcon(position);
350
The Android Open Source Project0c908882009-03-03 19:32:16 -0800351 final Intent i = new Intent();
The Android Open Source Projectf59ec872009-03-13 13:04:24 -0700352 final Intent shortcutIntent = new Intent(Intent.ACTION_VIEW,
353 Uri.parse(url));
354 long urlHash = url.hashCode();
355 long uniqueId = (urlHash << 32) | shortcutIntent.hashCode();
356 shortcutIntent.putExtra(Browser.EXTRA_APPLICATION_ID,
357 Long.toString(uniqueId));
358 i.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800359 i.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
Patrick Scott3918d442009-08-04 13:22:29 -0400360 // Use the apple-touch-icon if available
361 if (touchIcon != null) {
362 // Make a copy so we can modify the pixels.
363 Bitmap copy = touchIcon.copy(Bitmap.Config.ARGB_8888, true);
Patrick Scotte09761e2009-03-24 20:43:37 -0700364 Canvas canvas = new Canvas(copy);
365
Patrick Scott3918d442009-08-04 13:22:29 -0400366 // Construct a path from a round rect. This will allow drawing with
367 // an inverse fill so we can punch a hole using the round rect.
368 Path path = new Path();
369 path.setFillType(Path.FillType.INVERSE_WINDING);
370 path.addRoundRect(new RectF(0, 0, touchIcon.getWidth(),
371 touchIcon.getHeight()), 8f, 8f, Path.Direction.CW);
Patrick Scotte09761e2009-03-24 20:43:37 -0700372
Patrick Scott3918d442009-08-04 13:22:29 -0400373 // Construct a paint that clears the outside of the rectangle and
374 // draw.
375 Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
376 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
377 canvas.drawPath(path, paint);
Patrick Scotte09761e2009-03-24 20:43:37 -0700378
Patrick Scotte09761e2009-03-24 20:43:37 -0700379 i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
Patrick Scott3918d442009-08-04 13:22:29 -0400380 } else {
381 Bitmap favicon = getFavicon(position);
382 if (favicon == null) {
383 i.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,
384 Intent.ShortcutIconResource.fromContext(
385 BrowserBookmarksPage.this,
386 R.drawable.ic_launcher_shortcut_browser_bookmark));
387 } else {
388 Bitmap icon = BitmapFactory.decodeResource(getResources(),
389 R.drawable.ic_launcher_shortcut_browser_bookmark);
390
391 // Make a copy of the regular icon so we can modify the pixels.
392 Bitmap copy = icon.copy(Bitmap.Config.ARGB_8888, true);
393 Canvas canvas = new Canvas(copy);
394
395 // Make a Paint for the white background rectangle and for
396 // filtering the favicon.
397 Paint p = new Paint(Paint.ANTI_ALIAS_FLAG
398 | Paint.FILTER_BITMAP_FLAG);
399 p.setStyle(Paint.Style.FILL_AND_STROKE);
400 p.setColor(Color.WHITE);
401
402 // Create a rectangle that is slightly wider than the favicon
403 final float iconSize = 16; // 16x16 favicon
404 final float padding = 2; // white padding around icon
405 final float rectSize = iconSize + 2 * padding;
406 final float y = icon.getHeight() - rectSize;
407 RectF r = new RectF(0, y, rectSize, y + rectSize);
408
409 // Draw a white rounded rectangle behind the favicon
410 canvas.drawRoundRect(r, 2, 2, p);
411
412 // Draw the favicon in the same rectangle as the rounded
413 // rectangle but inset by the padding
414 // (results in a 16x16 favicon).
415 r.inset(padding, padding);
416 canvas.drawBitmap(favicon, null, r, p);
417 i.putExtra(Intent.EXTRA_SHORTCUT_ICON, copy);
418 }
Patrick Scotte09761e2009-03-24 20:43:37 -0700419 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800420 // Do not allow duplicate items
421 i.putExtra("duplicate", false);
422 return i;
423 }
424
425 private void saveCurrentPage() {
426 Intent i = new Intent(BrowserBookmarksPage.this,
427 AddBookmarkPage.class);
428 i.putExtras(getIntent());
429 startActivityForResult(i, BOOKMARKS_SAVE);
430 }
431
432 private void loadUrl(int position) {
433 Intent intent = (new Intent()).setAction(getUrl(position));
434 setResultToParent(RESULT_OK, intent);
435 finish();
436 }
437
438 @Override
439 public boolean onCreateOptionsMenu(Menu menu) {
440 boolean result = super.onCreateOptionsMenu(menu);
441 if (!mCreateShortcut) {
442 MenuInflater inflater = getMenuInflater();
443 inflater.inflate(R.menu.bookmarks, menu);
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400444 // Most visited page does not have an option to bookmark the last
445 // viewed page.
446 menu.findItem(R.id.new_context_menu_id).setVisible(!mMostVisited);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800447 return true;
448 }
449 return result;
450 }
451
452 @Override
Leon Scroggins0c786502009-08-04 16:04:55 -0400453 public boolean onPrepareOptionsMenu(Menu menu) {
Leon Scroggins8382d992009-08-19 11:25:14 -0400454 boolean result = super.onPrepareOptionsMenu(menu);
455 if (mCreateShortcut || mBookmarksAdapter.getCount() == 0) {
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400456 // No need to show the menu if there are no items.
Leon Scroggins8382d992009-08-19 11:25:14 -0400457 return result;
Leon Scrogginsa5d669e2009-08-05 14:07:58 -0400458 }
Leon Scroggins0c786502009-08-04 16:04:55 -0400459 menu.findItem(R.id.switch_mode_menu_id).setTitle(
460 mGridMode ? R.string.switch_to_list
461 : R.string.switch_to_thumbnails);
462 return true;
463 }
464
465 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800466 public boolean onOptionsItemSelected(MenuItem item) {
467 switch (item.getItemId()) {
Leon Scroggins892df312009-07-14 14:48:02 -0400468 case R.id.new_context_menu_id:
469 saveCurrentPage();
470 break;
471
472 case R.id.switch_mode_menu_id:
473 switchViewMode(!mGridMode);
474 break;
475
476 default:
477 return super.onOptionsItemSelected(item);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800478 }
479 return true;
480 }
481
482 private void openInNewWindow(int position) {
483 Bundle b = new Bundle();
484 b.putBoolean("new_window", true);
485 setResultToParent(RESULT_OK,
486 (new Intent()).setAction(getUrl(position)).putExtras(b));
487
488 finish();
489 }
490
491
492 private void editBookmark(int position) {
493 Intent intent = new Intent(BrowserBookmarksPage.this,
494 AddBookmarkPage.class);
495 intent.putExtra("bookmark", getRow(position));
496 startActivityForResult(intent, BOOKMARKS_SAVE);
497 }
498
499 @Override
500 protected void onActivityResult(int requestCode, int resultCode,
501 Intent data) {
502 switch(requestCode) {
503 case BOOKMARKS_SAVE:
504 if (resultCode == RESULT_OK) {
505 Bundle extras;
506 if (data != null && (extras = data.getExtras()) != null) {
507 // If there are extras, then we need to save
508 // the edited bookmark. This is done in updateRow()
509 String title = extras.getString("title");
510 String url = extras.getString("url");
511 if (title != null && url != null) {
512 mBookmarksAdapter.updateRow(extras);
513 }
514 } else {
515 // extras == null then a new bookmark was added to
516 // the database.
517 refreshList();
518 }
519 }
520 break;
521 default:
522 break;
523 }
524 }
525
526 private void displayRemoveBookmarkDialog(int position) {
527 // Put up a dialog asking if the user really wants to
528 // delete the bookmark
529 final int deletePos = position;
530 new AlertDialog.Builder(this)
531 .setTitle(R.string.delete_bookmark)
532 .setIcon(android.R.drawable.ic_dialog_alert)
533 .setMessage(getText(R.string.delete_bookmark_warning).toString().replace(
534 "%s", getBookmarkTitle(deletePos)))
535 .setPositiveButton(R.string.ok,
536 new DialogInterface.OnClickListener() {
537 public void onClick(DialogInterface dialog, int whichButton) {
538 deleteBookmark(deletePos);
539 }
540 })
541 .setNegativeButton(R.string.cancel, null)
542 .show();
543 }
544
545 /**
546 * Refresh the shown list after the database has changed.
547 */
Leon Scroggins892df312009-07-14 14:48:02 -0400548 private void refreshList() {
The Android Open Source Project0c908882009-03-03 19:32:16 -0800549 mBookmarksAdapter.refreshList();
550 }
551
552 /**
553 * Return a hashmap representing the currently highlighted row.
554 */
555 public Bundle getRow(int position) {
556 return mBookmarksAdapter.getRow(position);
557 }
558
559 /**
560 * Return the url of the currently highlighted row.
561 */
562 public String getUrl(int position) {
563 return mBookmarksAdapter.getUrl(position);
564 }
565
Patrick Scotte09761e2009-03-24 20:43:37 -0700566 /**
567 * Return the favicon of the currently highlighted row.
568 */
569 public Bitmap getFavicon(int position) {
570 return mBookmarksAdapter.getFavicon(position);
571 }
572
Patrick Scott3918d442009-08-04 13:22:29 -0400573 private Bitmap getTouchIcon(int position) {
574 return mBookmarksAdapter.getTouchIcon(position);
575 }
576
The Android Open Source Project0c908882009-03-03 19:32:16 -0800577 private void copy(CharSequence text) {
578 try {
579 IClipboard clip = IClipboard.Stub.asInterface(ServiceManager.getService("clipboard"));
580 if (clip != null) {
581 clip.setClipboardText(text);
582 }
583 } catch (android.os.RemoteException e) {
584 Log.e(LOGTAG, "Copy failed", e);
585 }
586 }
587
588 public String getBookmarkTitle(int position) {
589 return mBookmarksAdapter.getTitle(position);
590 }
591
592 /**
593 * Delete the currently highlighted row.
594 */
595 public void deleteBookmark(int position) {
596 mBookmarksAdapter.deleteRow(position);
597 }
598
599 public boolean dispatchKeyEvent(KeyEvent event) {
600 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.isDown()) {
601 setResultToParent(RESULT_CANCELED, null);
602 mCanceled = true;
603 }
604 return super.dispatchKeyEvent(event);
605 }
606
607 // This Activity is generally a sub-Activity of CombinedHistoryActivity. In
608 // that situation, we need to pass our result code up to our parent.
609 // However, if someone calls this Activity directly, then this has no
610 // parent, and it needs to set it on itself.
611 private void setResultToParent(int resultCode, Intent data) {
612 Activity a = getParent() == null ? this : getParent();
613 a.setResult(resultCode, data);
614 }
615}