PageRenderTime 85ms CodeModel.GetById 15ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

/WebVox/src/com/marvin/webvox/BrowserBookmarksPage.java

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