/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.browser; import android.app.ActionBar; import android.app.ActionBar.Tab; import android.app.ActionBar.TabListener; import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.content.res.Configuration; import android.database.Cursor; import android.graphics.Bitmap; import android.os.AsyncTask; import android.os.Bundle; import android.provider.Browser; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; import android.view.ViewGroup; import android.webkit.WebIconDatabase; import android.webkit.WebIconDatabase.IconListener; import android.widget.FrameLayout; import android.widget.LinearLayout; import com.android.browser.UI.ComboViews; import java.util.HashMap; import java.util.Vector; public class CombinedBookmarkHistoryView extends LinearLayout implements OnTouchListener, TabListener { final static String STARTING_FRAGMENT = "fragment"; final static int INVALID_ID = 0; final static int FRAGMENT_ID_BOOKMARKS = 1; final static int FRAGMENT_ID_HISTORY = 2; final static int FRAGMENT_ID_SNAPSHOTS = 3; private Activity mActivity; private ActionBar mActionBar; private Bundle mExtras; int mCurrentFragment = INVALID_ID; ActionBar.Tab mTabBookmarks; ActionBar.Tab mTabHistory; ActionBar.Tab mTabSnapshots; ViewGroup mBookmarksHeader; BrowserBookmarksPage mBookmarks; BrowserHistoryPage mHistory; BrowserSnapshotPage mSnapshots; CombinedBookmarksCallbacks mCallback; public static interface CombinedBookmarksCallbacks { void openUrl(String url); void openInNewTab(String... urls); void openSnapshot(long id); void close(); } static class IconListenerSet implements IconListener { // Used to store favicons as we get them from the database // FIXME: We use a different method to get the Favicons in // BrowserBookmarksAdapter. They should probably be unified. private HashMap mUrlsToIcons; private Vector mListeners; public IconListenerSet() { mUrlsToIcons = new HashMap(); mListeners = new Vector(); } @Override public void onReceivedIcon(String url, Bitmap icon) { mUrlsToIcons.put(url, icon); for (IconListener listener : mListeners) { listener.onReceivedIcon(url, icon); } } public void addListener(IconListener listener) { mListeners.add(listener); } public void removeListener(IconListener listener) { mListeners.remove(listener); } public Bitmap getFavicon(String url) { return mUrlsToIcons.get(url); } } private static IconListenerSet sIconListenerSet; static IconListenerSet getIconListenerSet() { if (null == sIconListenerSet) { sIconListenerSet = new IconListenerSet(); } return sIconListenerSet; } public CombinedBookmarkHistoryView(Activity activity, CombinedBookmarksCallbacks cb, ComboViews startingView, Bundle extras) { super(activity); mActivity = activity; mExtras = extras; mActionBar = mActivity.getActionBar(); mCallback = cb; View v = LayoutInflater.from(activity).inflate(R.layout.bookmarks_history, this); v.setOnTouchListener(this); mBookmarksHeader = new FrameLayout(mActivity); mBookmarksHeader.setLayoutParams(new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.MATCH_PARENT, Gravity.CENTER_VERTICAL)); // Start up the default fragment initFragments(mExtras); // XXX: Must do this before launching the AsyncTask to avoid a // potential crash if the icon database has not been created. WebIconDatabase.getInstance(); // Do this every time the view is created in case a new favicon was // added to the webkit db. (new AsyncTask() { @Override public Void doInBackground(Void... v) { Browser.requestAllIcons(mActivity.getContentResolver(), Browser.BookmarkColumns.FAVICON + " is NULL", getIconListenerSet()); return null; } }).execute(); setupActionBar(startingView); } void setupActionBar(ComboViews startingView) { if (BrowserActivity.isTablet(mContext)) { mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO); } else { mActionBar.setDisplayOptions(0); } mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); mActionBar.removeAllTabs(); mTabBookmarks = mActionBar.newTab(); mTabBookmarks.setText(R.string.tab_bookmarks); mTabBookmarks.setTabListener(this); mActionBar.addTab(mTabBookmarks, ComboViews.Bookmarks == startingView); mTabHistory = mActionBar.newTab(); mTabHistory.setText(R.string.tab_history); mTabHistory.setTabListener(this); mActionBar.addTab(mTabHistory, ComboViews.History == startingView); mTabSnapshots = mActionBar.newTab(); mTabSnapshots.setText(R.string.tab_snapshots); mTabSnapshots.setTabListener(this); mActionBar.addTab(mTabSnapshots, ComboViews.Snapshots == startingView); mActionBar.setCustomView(mBookmarksHeader); mActionBar.show(); } void tearDownActionBar() { if (mActionBar != null) { mActionBar.removeAllTabs(); mTabBookmarks.setTabListener(null); mTabHistory.setTabListener(null); mTabSnapshots.setTabListener(null); mTabBookmarks = null; mTabHistory = null; mTabSnapshots = null; mActionBar = null; } } @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); if (mCurrentFragment == FRAGMENT_ID_HISTORY) { // Warning, ugly hack below // This is done because history uses orientation-specific padding FragmentManager fm = mActivity.getFragmentManager(); mHistory = BrowserHistoryPage.newInstance(mCallback, mHistory.getArguments()); fm.beginTransaction().replace(R.id.fragment, mHistory).commit(); } } private BookmarksPageCallbacks mBookmarkCallbackWrapper = new BookmarksPageCallbacks() { @Override public boolean onOpenInNewWindow(String... urls) { mCallback.openInNewTab(urls); return true; } @Override public boolean onBookmarkSelected(Cursor c, boolean isFolder) { if (isFolder) { return false; } mCallback.openUrl(BrowserBookmarksPage.getUrl(c)); return true; } }; private void initFragments(Bundle extras) { mBookmarks = BrowserBookmarksPage.newInstance(mBookmarkCallbackWrapper, extras, mBookmarksHeader); mHistory = BrowserHistoryPage.newInstance(mCallback, extras); mSnapshots = BrowserSnapshotPage.newInstance(mCallback, extras); } private void loadFragment(int id, FragmentTransaction ft) { if (mCurrentFragment == id) return; switch (id) { case FRAGMENT_ID_BOOKMARKS: ft.replace(R.id.fragment, mBookmarks); break; case FRAGMENT_ID_HISTORY: ft.replace(R.id.fragment, mHistory); break; case FRAGMENT_ID_SNAPSHOTS: ft.replace(R.id.fragment, mSnapshots); break; default: throw new IllegalArgumentException(); } mCurrentFragment = id; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); tearDownActionBar(); if (mCurrentFragment != INVALID_ID) { try { FragmentManager fm = mActivity.getFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); if (mCurrentFragment == FRAGMENT_ID_BOOKMARKS) { transaction.remove(mBookmarks); } else if (mCurrentFragment == FRAGMENT_ID_HISTORY) { transaction.remove(mHistory); } else if (mCurrentFragment == FRAGMENT_ID_SNAPSHOTS) { transaction.remove(mSnapshots); } transaction.commit(); } catch (IllegalStateException ex) { // This exception is thrown if the fragment isn't added // This will happen if the activity is finishing, and the // fragment was already removed before this view was detached // Aka, success! } mCurrentFragment = INVALID_ID; } } /** * callback for back key presses */ boolean onBackPressed() { if (mCurrentFragment == FRAGMENT_ID_BOOKMARKS) { return mBookmarks.onBackPressed(); } return false; } /** * capture touch events to prevent them from going to the underlying * WebView */ @Override public boolean onTouch(View v, MotionEvent event) { return true; } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { // Ignore } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { if (tab == mTabBookmarks) { loadFragment(FRAGMENT_ID_BOOKMARKS, ft); } else if (tab == mTabHistory) { loadFragment(FRAGMENT_ID_HISTORY, ft); } else if (tab == mTabSnapshots) { loadFragment(FRAGMENT_ID_SNAPSHOTS, ft); } } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { // Ignore } }