diff options
Diffstat (limited to 'src/com/android/browser')
17 files changed, 379 insertions, 174 deletions
diff --git a/src/com/android/browser/ActivityController.java b/src/com/android/browser/ActivityController.java index ac248b8d..817857ac 100644 --- a/src/com/android/browser/ActivityController.java +++ b/src/com/android/browser/ActivityController.java @@ -71,4 +71,5 @@ public interface ActivityController { boolean dispatchGenericMotionEvent(MotionEvent ev); + void invalidateOptionsMenu(); } diff --git a/src/com/android/browser/BrowserActivity.java b/src/com/android/browser/BrowserActivity.java index 351cb964..3b95ee90 100644 --- a/src/com/android/browser/BrowserActivity.java +++ b/src/com/android/browser/BrowserActivity.java @@ -297,9 +297,9 @@ public class BrowserActivity extends Activity implements ViewTreeObserver.OnPreD } @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - return mController.onCreateOptionsMenu(menu); + public void invalidateOptionsMenu() { + super.invalidateOptionsMenu(); + mController.invalidateOptionsMenu(); } @Override diff --git a/src/com/android/browser/BrowserBookmarksPage.java b/src/com/android/browser/BrowserBookmarksPage.java index 16eae77b..7abe07bb 100644 --- a/src/com/android/browser/BrowserBookmarksPage.java +++ b/src/com/android/browser/BrowserBookmarksPage.java @@ -45,6 +45,7 @@ import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; import android.widget.ExpandableListView; import android.widget.ExpandableListView.OnChildClickListener; import android.widget.Toast; @@ -169,31 +170,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte } } - //add for carrier feature which adds new bookmark/folder function. - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.bookmark, menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - final Activity activity = getActivity(); - if (item.getItemId() == R.id.add_bookmark_menu_id) { - Intent intent = new Intent(activity, AddBookmarkPage.class); - intent.putExtra(BrowserContract.Bookmarks.URL, "http://"); - intent.putExtra(BrowserContract.Bookmarks.TITLE, ""); - intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId); - activity.startActivity(intent); - } - if (item.getItemId() == R.id.new_bmfolder_menu_id) { - Intent intent = new Intent(activity, AddBookmarkFolder.class); - intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId); - activity.startActivity(intent); - } - return super.onOptionsItemSelected(item); - } - @Override public boolean onContextItemSelected(MenuItem item) { if (!(item.getMenuInfo() instanceof BookmarkContextMenuInfo)) { @@ -373,7 +349,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte } Bundle args = getArguments(); mDisableNewWindow = args == null ? false : args.getBoolean(EXTRA_DISABLE_WINDOW, false); - setHasOptionsMenu(true); if (mCallbacks == null && getActivity() instanceof CombinedBookmarksCallbacks) { mCallbacks = new CombinedBookmarksCallbackWrapper( (CombinedBookmarksCallbacks) getActivity()); @@ -423,6 +398,7 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + final Activity activity = getActivity(); mRoot = inflater.inflate(R.layout.bookmarks, container, false); mEmptyView = mRoot.findViewById(android.R.id.empty); @@ -432,6 +408,28 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte mGrid.setBreadcrumbController(this); setEnableContextMenu(mEnableContextMenu); + Button btn = (Button) mRoot.findViewById(R.id.add_bookmark_button); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(activity, AddBookmarkPage.class); + intent.putExtra(BrowserContract.Bookmarks.URL, "http://"); + intent.putExtra(BrowserContract.Bookmarks.TITLE, ""); + intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId); + activity.startActivity(intent); + } + }); + + btn = (Button) mRoot.findViewById(R.id.new_bmfolder_button); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent intent = new Intent(activity, AddBookmarkFolder.class); + intent.putExtra(BrowserContract.Bookmarks.PARENT, mCurrentFolderId); + activity.startActivity(intent); + } + }); + // Start the loaders LoaderManager lm = getLoaderManager(); lm.restartLoader(LOADER_ACCOUNTS, null, this); @@ -604,7 +602,6 @@ public class BrowserBookmarksPage extends Fragment implements View.OnCreateConte mGrid.setColumnWidthFromLayout(R.layout.bookmark_thumbnail); int paddingTop = (int) res.getDimension(R.dimen.combo_paddingTop); mRoot.setPadding(0, paddingTop, 0, 0); - getActivity().invalidateOptionsMenu(); } /** diff --git a/src/com/android/browser/BrowserHistoryPage.java b/src/com/android/browser/BrowserHistoryPage.java index fa25acad..193d0408 100644 --- a/src/com/android/browser/BrowserHistoryPage.java +++ b/src/com/android/browser/BrowserHistoryPage.java @@ -51,6 +51,7 @@ import android.widget.AdapterView; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; +import android.widget.Button; import android.widget.ExpandableListView; import android.widget.ExpandableListView.ExpandableListContextMenuInfo; import android.widget.ExpandableListView.OnChildClickListener; @@ -196,8 +197,6 @@ public class BrowserHistoryPage extends Fragment public void onCreate(Bundle icicle) { super.onCreate(icicle); - setHasOptionsMenu(true); - Bundle args = getArguments(); mDisableNewWindow = args.getBoolean(BrowserBookmarksPage.EXTRA_DISABLE_WINDOW, false); int mvlimit = getResources().getInteger(R.integer.most_visits_limit); @@ -216,6 +215,13 @@ public class BrowserHistoryPage extends Fragment } else { inflateSinglePane(); } + Button btn = (Button) mRoot.findViewById(R.id.clear_history_button); + btn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + promptToClearHistory(); + } + }); // Start the loaders getLoaderManager().restartLoader(LOADER_HISTORY, null, this); @@ -285,12 +291,6 @@ public class BrowserHistoryPage extends Fragment getLoaderManager().destroyLoader(LOADER_MOST_VISITED); } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - super.onCreateOptionsMenu(menu, inflater); - inflater.inflate(R.menu.history, menu); - } - void promptToClearHistory() { final ContentResolver resolver = getActivity().getContentResolver(); final ClearHistoryTask clear = new ClearHistoryTask(resolver); @@ -310,15 +310,6 @@ public class BrowserHistoryPage extends Fragment dialog.show(); } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.clear_history_menu_id) { - promptToClearHistory(); - return true; - } - return super.onOptionsItemSelected(item); - } - static class ClearHistoryTask extends Thread { ContentResolver mResolver; diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java index 292a46db..b0657c96 100644 --- a/src/com/android/browser/Controller.java +++ b/src/com/android/browser/Controller.java @@ -79,6 +79,8 @@ import android.view.WindowManager; import android.webkit.MimeTypeMap; import android.webkit.ValueCallback; import android.webkit.WebChromeClient.CustomViewCallback; +import android.widget.Button; +import android.widget.EditText; import android.widget.Toast; import org.codeaurora.swe.CookieManager; @@ -103,6 +105,8 @@ import com.android.browser.platformsupport.BrowserContract.Images; import com.android.browser.provider.BrowserProvider2.Thumbnails; import com.android.browser.provider.SnapshotProvider.Snapshots; import com.android.browser.reflect.ReflectHelper; +import com.android.browser.appmenu.AppMenuHandler; +import com.android.browser.appmenu.AppMenuPropertiesDelegate; import java.io.ByteArrayOutputStream; import java.io.File; @@ -123,7 +127,8 @@ import java.util.Map; * Controller for browser */ public class Controller - implements WebViewController, UiController, ActivityController { + implements WebViewController, UiController, ActivityController, + AppMenuPropertiesDelegate { private static final String LOGTAG = "Controller"; private static final String SEND_APP_ID_EXTRA = @@ -206,6 +211,9 @@ public class Controller private boolean mMenuIsDown; + private boolean mWasInPageLoad = false; + private AppMenuHandler mAppMenuHandler; + // For select and find, we keep track of the ActionMode so that // finish() can be called as desired. private ActionMode mActionMode; @@ -275,6 +283,7 @@ public class Controller mNetworkHandler = new NetworkStateHandler(mActivity, this); mHomepageHandler = new HomepageHandler(browser, this); + mAppMenuHandler = new AppMenuHandler(browser, this, R.menu.browser); } @Override @@ -654,6 +663,7 @@ public class Controller mConfigChanged = true; // update the menu in case of a locale change mActivity.invalidateOptionsMenu(); + mAppMenuHandler.hideAppMenu(); if (mOptionsMenuOpen) { mActivity.closeOptionsMenu(); mHandler.sendMessageDelayed(mHandler.obtainMessage(OPEN_MENU), 100); @@ -973,8 +983,14 @@ public class Controller // any sub frames so calls to onProgressChanges may continue after // onPageFinished has executed) if (tab.inPageLoad()) { + mWasInPageLoad = true; + updateInLoadMenuItems(mCachedMenu, tab); + } else if (mWasInPageLoad) { + mWasInPageLoad = false; updateInLoadMenuItems(mCachedMenu, tab); - } else if (mActivityPaused && pauseWebViewTimers(tab)) { + } + + if (mActivityPaused && pauseWebViewTimers(tab)) { // pause the WebView timer and release the wake lock if it is // finished while BrowserActivity is in pause state. releaseWakeLock(); @@ -1001,7 +1017,10 @@ public class Controller // still loading // updating the progress and // update the menu items. + mWasInPageLoad = false; updateInLoadMenuItems(mCachedMenu, tab); + } else { + mWasInPageLoad = true; } } mUi.onProgressChanged(tab); @@ -1780,10 +1799,22 @@ public class Controller dest.setIcon(src.getIcon()); dest.setTitle(src.getTitle()); } + mActivity.invalidateOptionsMenu(); + } + + public void invalidateOptionsMenu() { + mAppMenuHandler.invalidateAppMenu(); } @Override public boolean onPrepareOptionsMenu(Menu menu) { + // Software menu key (toolbar key) + mAppMenuHandler.showAppMenu(mActivity.findViewById(R.id.more_browser_settings), false, false); + return true; + } + + @Override + public void prepareMenu(Menu menu) { updateInLoadMenuItems(menu, getCurrentTab()); // hold on to the menu reference here; it is used by the page callbacks // to update the menu based on loading state @@ -1809,12 +1840,53 @@ public class Controller break; } mCurrentMenuState = mMenuState; - return mUi.onPrepareOptionsMenu(menu); + mUi.onPrepareOptionsMenu(menu); + } + + private void setMenuItemVisibility(Menu menu, int id, + boolean visibility) { + MenuItem item = menu.findItem(id); + if (item != null) { + item.setVisible(visibility); + } + } + + private int lookupBookmark(String title, String url) { + final ContentResolver cr = getActivity().getContentResolver(); + + Cursor cursor = cr.query(BrowserContract.Bookmarks.CONTENT_URI, + BookmarksLoader.PROJECTION, + "title = ? OR url = ?", + new String[] { + title, url + }, + null); + + if (cursor == null) { + return 0; + } + + return cursor.getCount(); + } + + private void resetMenuItems(Menu menu) { + setMenuItemVisibility(menu, R.id.history_menu_id, true); + setMenuItemVisibility(menu, R.id.find_menu_id, true); + + WebView w = getCurrentTopWebView(); + MenuItem bookmark_icon = menu.findItem(R.id.bookmark_this_page_id); + + String title = w.getTitle(); + String url = w.getUrl(); + if (title != null && url != null && lookupBookmark(title, url) > 0) { + bookmark_icon.setChecked(true); + } else { + bookmark_icon.setChecked(false); + } } @Override public void updateMenuState(Tab tab, Menu menu) { - boolean canGoBack = false; boolean canGoForward = false; boolean isDesktopUa = false; boolean isLive = false; @@ -1822,33 +1894,20 @@ public class Controller // items defined in res/menu/browser.xml should be enabled boolean isLiveScheme = false; boolean isPageFinished = false; - boolean isSavable = false; + + resetMenuItems(menu); + if (tab != null) { - canGoBack = tab.canGoBack(); canGoForward = tab.canGoForward(); isDesktopUa = mSettings.hasDesktopUseragent(tab.getWebView()); isLive = !tab.isSnapshot(); isLiveScheme = UrlUtils.isLiveScheme(tab.getWebView().getUrl()); - isPageFinished = tab.getPageFinishedStatus(); - isSavable = tab.getWebView().isSavable(); + isPageFinished = (tab.getPageFinishedStatus() || !tab.inPageLoad()); } - final MenuItem back = menu.findItem(R.id.back_menu_id); - back.setEnabled(canGoBack); - - final MenuItem home = menu.findItem(R.id.homepage_menu_id); final MenuItem forward = menu.findItem(R.id.forward_menu_id); forward.setEnabled(canGoForward); - final MenuItem source = menu.findItem(isInLoad() ? R.id.stop_menu_id - : R.id.reload_menu_id); - final MenuItem dest = menu.findItem(R.id.stop_reload_menu_id); - if (source != null && dest != null) { - dest.setTitle(source.getTitle()); - dest.setIcon(source.getIcon()); - } - menu.setGroupVisible(R.id.NAV_MENU, isLive); - // decide whether to show the share link option PackageManager pm = mActivity.getPackageManager(); Intent send = new Intent(Intent.ACTION_SEND); @@ -1866,8 +1925,13 @@ public class Controller final MenuItem uaSwitcher = menu.findItem(R.id.ua_desktop_menu_id); uaSwitcher.setChecked(isDesktopUa); menu.setGroupVisible(R.id.LIVE_MENU, isLive && isLiveScheme); + menu.setGroupVisible(R.id.NAV_MENU, isLive && isLiveScheme); + setMenuItemVisibility(menu, R.id.find_menu_id, isLive && isLiveScheme); menu.setGroupVisible(R.id.SNAPSHOT_MENU, !isLive); - menu.setGroupEnabled(R.id.OFFLINE_READING, isLive && isLiveScheme && isPageFinished && isSavable); + setMenuItemVisibility(menu, R.id.add_to_homescreen, + isLive && isLiveScheme && isPageFinished); + setMenuItemVisibility(menu, R.id.save_snapshot_menu_id, + isLive && isLiveScheme && isPageFinished); // history and snapshots item are the members of COMBO menu group, // so if show history item, only make snapshots item invisible. menu.findItem(R.id.snapshots_menu_id).setVisible(false); @@ -1901,10 +1965,6 @@ public class Controller openIncognitoTab(); break; - case R.id.close_other_tabs_id: - closeOtherTabs(); - break; - case R.id.goto_menu_id: editUrl(); break; @@ -1921,7 +1981,7 @@ public class Controller bookmarksOrHistoryPicker(ComboViews.Snapshots); break; - case R.id.add_bookmark_menu_id: + case R.id.bookmark_this_page_id: bookmarkCurrentPage(); break; @@ -1938,10 +1998,6 @@ public class Controller } break; - case R.id.back_menu_id: - getCurrentTab().goBack(); - break; - case R.id.forward_menu_id: getCurrentTab().goForward(); break; @@ -2068,6 +2124,34 @@ public class Controller builder.create().show(); break; + case R.id.add_to_homescreen: + final WebView w = getCurrentTopWebView(); + final EditText input = new EditText(getContext()); + input.setText(w.getTitle()); + new AlertDialog.Builder(getContext()) + .setTitle("Add to homescreen") + .setMessage("Title") + .setView(input) + .setPositiveButton("Add", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + mActivity.sendBroadcast(BookmarkUtils.createAddToHomeIntent( + getContext(), + w.getUrl(), + input.getText().toString(), + w.getViewportBitmap(), + w.getFavicon())); + + mActivity.startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME)); + }}) + .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int whichButton) { + // Do nothing. + } + }) + .show(); + break; + default: return false; } @@ -3130,6 +3214,13 @@ public class Controller */ @Override public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0) { + // Hardware menu key + mAppMenuHandler.showAppMenu(mActivity.findViewById(R.id.more_browser_settings), + true, false); + return true; + } + boolean noModifiers = event.hasNoModifiers(); // Even if MENU is already held down, we need to call to super to open // the IME on long press. @@ -3359,4 +3450,13 @@ public class Controller return mBlockEvents; } + @Override + public boolean shouldShowAppMenu() { + return true; + } + + @Override + public int getMenuThemeResourceId() { + return R.style.OverflowMenuTheme; + } } diff --git a/src/com/android/browser/NavScreen.java b/src/com/android/browser/NavScreen.java index b11cc4a0..64243e32 100644 --- a/src/com/android/browser/NavScreen.java +++ b/src/com/android/browser/NavScreen.java @@ -80,12 +80,13 @@ public class NavScreen extends RelativeLayout } protected void showMenu() { - PopupMenu popup = new PopupMenu(getContext(), mMore); - Menu menu = popup.getMenu(); - popup.getMenuInflater().inflate(R.menu.browser, menu); - mUiController.updateMenuState(mUiController.getCurrentTab(), menu); - popup.setOnMenuItemClickListener(this); - popup.show(); + if (mUiController instanceof Controller) { + PopupMenu popup = new PopupMenu(getContext(), mMore); + Menu menu = popup.getMenu(); + + Controller controller = (Controller) mUiController; + controller.onPrepareOptionsMenu(menu); + } } @Override diff --git a/src/com/android/browser/NavigationBarPhone.java b/src/com/android/browser/NavigationBarPhone.java index 076e4ada..fe5ca281 100644 --- a/src/com/android/browser/NavigationBarPhone.java +++ b/src/com/android/browser/NavigationBarPhone.java @@ -192,7 +192,6 @@ public class NavigationBarPhone extends NavigationBarBase implements Menu menu = mPopupMenu.getMenu(); if (activity.onPrepareOptionsMenu(menu)) { mOverflowMenuShowing = true; - mPopupMenu.show(); } } diff --git a/src/com/android/browser/PhoneUi.java b/src/com/android/browser/PhoneUi.java index a2799b39..ca478c20 100644 --- a/src/com/android/browser/PhoneUi.java +++ b/src/com/android/browser/PhoneUi.java @@ -160,42 +160,32 @@ public class PhoneUi extends BaseUi { return true; } + private void setMenuItemVisibility(Menu menu, int id, + boolean visibility) { + MenuItem item = menu.findItem(id); + if (item != null) { + item.setVisible(visibility); + } + } + @Override public void updateMenuState(Tab tab, Menu menu) { MenuItem bm = menu.findItem(R.id.bookmarks_menu_id); if (bm != null) { bm.setVisible(!showingNavScreen()); } - MenuItem abm = menu.findItem(R.id.add_bookmark_menu_id); - if (abm != null) { - abm.setVisible((tab != null) && !tab.isSnapshot() && !showingNavScreen()); - } MenuItem info = menu.findItem(R.id.page_info_menu_id); if (info != null) { info.setVisible(false); } - MenuItem newtab = menu.findItem(R.id.new_tab_menu_id); - if (newtab != null) { - newtab.setVisible(false); - } - MenuItem incognito = menu.findItem(R.id.incognito_menu_id); - if (incognito != null) { - incognito.setVisible(showingNavScreen()); - } - MenuItem closeOthers = menu.findItem(R.id.close_other_tabs_id); - if (closeOthers != null) { - boolean isLastTab = true; - if (tab != null) { - isLastTab = (mTabControl.getTabCount() <= 1); - } - closeOthers.setEnabled(!isLastTab); - } + if (showingNavScreen()) { + setMenuItemVisibility(menu, R.id.history_menu_id, false); + setMenuItemVisibility(menu, R.id.find_menu_id, false); menu.setGroupVisible(R.id.LIVE_MENU, false); - menu.setGroupVisible(R.id.OFFLINE_READING, false); + setMenuItemVisibility(menu, R.id.save_snapshot_menu_id, false); menu.setGroupVisible(R.id.SNAPSHOT_MENU, false); menu.setGroupVisible(R.id.NAV_MENU, false); - menu.setGroupVisible(R.id.COMBO_MENU, true); } } diff --git a/src/com/android/browser/appmenu/AppMenu.java b/src/com/android/browser/appmenu/AppMenu.java index 3f3ac689..a0ff7107 100644 --- a/src/com/android/browser/appmenu/AppMenu.java +++ b/src/com/android/browser/appmenu/AppMenu.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.animation.Animator; import android.animation.AnimatorSet; @@ -26,7 +26,7 @@ import android.widget.PopupWindow; import android.widget.PopupWindow.OnDismissListener; import org.chromium.base.SysUtils; -import org.chromium.chrome.R; +import com.android.browser.R; import java.util.ArrayList; import java.util.List; @@ -112,13 +112,7 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { // drawable here even though our style says @null we should use this padding instead... Drawable originalBgDrawable = mPopup.getBackground(); - // Need to explicitly set the background here. Relying on it being set in the style caused - // an incorrectly drawn background. - if (isByHardwareButton) { - mPopup.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.menu_bg)); - } else { - mPopup.setBackgroundDrawable( - context.getResources().getDrawable(R.drawable.edge_menu_bg)); + if (!isByHardwareButton) { mPopup.setAnimationStyle(R.style.OverflowMenuAnim); } @@ -189,6 +183,30 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { } } + public void invalidate(Context context, Menu menu) { + assert(mMenu == menu); + // Extract visible items from the Menu. + int numItems = mMenu.size(); + List<MenuItem> menuItems = new ArrayList<MenuItem>(); + for (int i = 0; i < numItems; ++i) { + MenuItem item = mMenu.getItem(i); + if (item.isVisible()) { + menuItems.add(item); + } + } + + boolean showMenuButton = !mIsByHardwareButton; + if (!SHOW_SW_MENU_BUTTON) showMenuButton = false; + + mAdapter = new AppMenuAdapter( + this, menuItems, LayoutInflater.from(context), showMenuButton); + mPopup.setAdapter(mAdapter); + + mPopup.show(); + mPopup.getListView().setItemsCanFocus(true); + mPopup.getListView().setOnKeyListener(this); + } + private void setPopupOffset( ListPopupWindow popup, int screenRotation, Rect appRect, Rect padding) { int[] anchorLocation = new int[2]; @@ -202,10 +220,10 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { switch (screenRotation) { case Surface.ROTATION_0: case Surface.ROTATION_180: - horizontalOffset += (appRect.width() - mPopup.getWidth()) / 2; + horizontalOffset += (appRect.width() - popup.getWidth()) / 2; break; case Surface.ROTATION_90: - horizontalOffset += appRect.width() - mPopup.getWidth(); + horizontalOffset += appRect.width() - popup.getWidth(); break; case Surface.ROTATION_270: break; @@ -216,7 +234,8 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { popup.setHorizontalOffset(horizontalOffset); // The menu is displayed above the anchored view, so shift the menu up by the bottom // padding of the background. - popup.setVerticalOffset(-padding.bottom); + int verticalOffset = appRect.height() - popup.getHeight() + padding.bottom; + popup.setVerticalOffset(verticalOffset); } else { // The menu is displayed over and below the anchored view, so shift the menu up by the // height of the anchor view. @@ -321,7 +340,8 @@ public class AppMenu implements OnItemClickListener, OnKeyListener { padding.top + padding.bottom); } } else { - mPopup.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); + mPopup.setHeight(numMenuItems * (mItemRowHeight + mItemDividerHeight) + + padding.top + padding.bottom); } } diff --git a/src/com/android/browser/appmenu/AppMenuAdapter.java b/src/com/android/browser/appmenu/AppMenuAdapter.java index 2b60292c..6a8cdb4c 100644 --- a/src/com/android/browser/appmenu/AppMenuAdapter.java +++ b/src/com/android/browser/appmenu/AppMenuAdapter.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -15,6 +15,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; +import android.widget.CheckBox; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ImageView.ScaleType; @@ -22,7 +23,7 @@ import android.widget.ListView; import android.widget.TextView; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.chrome.R; +import com.android.browser.R; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -32,7 +33,7 @@ import java.util.List; * ListAdapter to customize the view of items in the list. */ class AppMenuAdapter extends BaseAdapter { - private static final int VIEW_TYPE_COUNT = 5; + private static final int VIEW_TYPE_COUNT = 9; /** * Regular Android menu item that contains a title and an icon if icon is specified. @@ -44,18 +45,34 @@ class AppMenuAdapter extends BaseAdapter { */ private static final int TITLE_BUTTON_MENU_ITEM = 1; /** + * Menu item that has one button plus menu button. Every one of these buttons is displayed as an icon. + */ + private static final int ONE_BUTTON_PLUS_MENU_ITEM = 2; + /** + * Menu item that has two buttons. Every one of these buttons is displayed as an icon. + */ + private static final int TWO_BUTTON_MENU_ITEM = 3; + /** + * Menu item that has two buttons plus menu. Every one of these buttons is displayed as an icon. + */ + private static final int TWO_BUTTON_PLUS_MENU_ITEM = 4; + /** * Menu item that has three buttons. Every one of these buttons is displayed as an icon. */ - private static final int THREE_BUTTON_MENU_ITEM = 2; + private static final int THREE_BUTTON_MENU_ITEM = 5; + /** + * Menu item that has three buttons plus menu. Every one of these buttons is displayed as an icon. + */ + private static final int THREE_BUTTON_PLUS_MENU_ITEM = 6; /** * Menu item that has four buttons. Every one of these buttons is displayed as an icon. */ - private static final int FOUR_BUTTON_MENU_ITEM = 3; + private static final int FOUR_BUTTON_MENU_ITEM = 7; /** * Menu item that has two buttons, the first one is a title and the second is a menu icon. * This is similar to {@link #TITLE_BUTTON_MENU_ITEM} but has some slight layout differences. */ - private static final int MENU_BUTTON_MENU_ITEM = 4; + private static final int MENU_BUTTON_MENU_ITEM = 8; /** MenuItem Animation Constants */ private static final int ENTER_ITEM_DURATION_MS = 350; @@ -100,14 +117,21 @@ class AppMenuAdapter extends BaseAdapter { MenuItem item = getItem(position); boolean hasMenuButton = mShowMenuButton && position == 0; int viewCount = item.hasSubMenu() ? item.getSubMenu().size() : 1; - if (hasMenuButton) viewCount++; if (viewCount == 4) { return FOUR_BUTTON_MENU_ITEM; } else if (viewCount == 3) { + if (hasMenuButton) { + return THREE_BUTTON_PLUS_MENU_ITEM; + } return THREE_BUTTON_MENU_ITEM; } else if (viewCount == 2) { - return hasMenuButton ? MENU_BUTTON_MENU_ITEM : TITLE_BUTTON_MENU_ITEM; + if (hasMenuButton) { + return TWO_BUTTON_PLUS_MENU_ITEM; + } + return TWO_BUTTON_MENU_ITEM; + } else if (hasMenuButton) { + return ONE_BUTTON_PLUS_MENU_ITEM; } return STANDARD_MENU_ITEM; } @@ -137,6 +161,7 @@ class AppMenuAdapter extends BaseAdapter { convertView = mInflater.inflate(R.layout.menu_item, parent, false); holder.text = (TextView) convertView.findViewById(R.id.menu_item_text); holder.image = (AppMenuItemIcon) convertView.findViewById(R.id.menu_item_icon); + holder.checkbox = (CheckBox) convertView.findViewById(R.id.menu_item_checkbox); convertView.setTag(holder); convertView.setTag(R.id.menu_item_enter_anim_id, buildStandardItemEnterAnimator(convertView, position)); @@ -154,7 +179,15 @@ class AppMenuAdapter extends BaseAdapter { Drawable icon = item.getIcon(); holder.image.setImageDrawable(icon); holder.image.setVisibility(icon == null ? View.GONE : View.VISIBLE); - holder.image.setChecked(item.isChecked()); + + holder.checkbox.setVisibility(item.isCheckable() ? View.VISIBLE : View.GONE); + holder.checkbox.setChecked(item.isChecked()); + holder.checkbox.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + mAppMenu.onItemClick(item); + } + }); holder.text.setText(item.getTitle()); boolean isEnabled = item.isEnabled(); @@ -164,6 +197,65 @@ class AppMenuAdapter extends BaseAdapter { convertView.setEnabled(isEnabled); break; } + case ONE_BUTTON_PLUS_MENU_ITEM: { + TwoButtonMenuItemViewHolder holder = null; + if (convertView == null) { + holder = new TwoButtonMenuItemViewHolder(); + convertView = mInflater.inflate(R.layout.one_button_plus_menu_item, parent, false); + holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); + holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); + convertView.setTag(holder); + convertView.setTag(R.id.menu_item_enter_anim_id, + buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); + } else { + holder = (TwoButtonMenuItemViewHolder) convertView.getTag(); + } + setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); + setupMenuButton(holder.buttons[1]); + convertView.setFocusable(false); + convertView.setEnabled(false); + break; + } + case TWO_BUTTON_MENU_ITEM: { + TwoButtonMenuItemViewHolder holder = null; + if (convertView == null) { + holder = new TwoButtonMenuItemViewHolder(); + convertView = mInflater.inflate(R.layout.two_button_menu_item, parent, false); + holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); + holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); + convertView.setTag(holder); + convertView.setTag(R.id.menu_item_enter_anim_id, + buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); + } else { + holder = (TwoButtonMenuItemViewHolder) convertView.getTag(); + } + setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); + setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); + convertView.setFocusable(false); + convertView.setEnabled(false); + break; + } + case TWO_BUTTON_PLUS_MENU_ITEM: { + ThreeButtonMenuItemViewHolder holder = null; + if (convertView == null) { + holder = new ThreeButtonMenuItemViewHolder(); + convertView = mInflater.inflate(R.layout.two_button_plus_menu_item, parent, false); + holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); + holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); + holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three); + convertView.setTag(holder); + convertView.setTag(R.id.menu_item_enter_anim_id, + buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); + } else { + holder = (ThreeButtonMenuItemViewHolder) convertView.getTag(); + } + setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); + setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); + setupMenuButton(holder.buttons[2]); + convertView.setFocusable(false); + convertView.setEnabled(false); + break; + } case THREE_BUTTON_MENU_ITEM: { ThreeButtonMenuItemViewHolder holder = null; if (convertView == null) { @@ -180,12 +272,31 @@ class AppMenuAdapter extends BaseAdapter { } setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); - if (hasMenuButton) { - setupMenuButton(holder.buttons[3]); + setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); + convertView.setFocusable(false); + convertView.setEnabled(false); + break; + } + case THREE_BUTTON_PLUS_MENU_ITEM: { + FourButtonMenuItemViewHolder holder = null; + if (convertView == null) { + holder = new FourButtonMenuItemViewHolder(); + convertView = mInflater.inflate(R.layout.three_button_plus_menu_item, parent, false); + holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); + holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); + holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three); + holder.buttons[3] = (ImageButton) convertView.findViewById(R.id.button_four); + convertView.setTag(holder); + convertView.setTag(R.id.menu_item_enter_anim_id, + buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); } else { - setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); + holder = (FourButtonMenuItemViewHolder) convertView.getTag(); } + setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); + setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); + setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); + setupMenuButton(holder.buttons[3]); convertView.setFocusable(false); convertView.setEnabled(false); break; @@ -208,11 +319,7 @@ class AppMenuAdapter extends BaseAdapter { setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); - if (hasMenuButton) { - setupMenuButton(holder.buttons[3]); - } else { - setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3)); - } + setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3)); convertView.setFocusable(false); convertView.setEnabled(false); break; @@ -274,6 +381,7 @@ class AppMenuAdapter extends BaseAdapter { button.setContentDescription(item.getTitle()); button.setEnabled(item.isEnabled()); button.setFocusable(item.isEnabled()); + button.setSelected(item.isChecked()); button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { @@ -283,8 +391,7 @@ class AppMenuAdapter extends BaseAdapter { } private void setupMenuButton(ImageButton button) { - button.setImageResource(R.drawable.btn_menu_pressed); - button.setContentDescription(button.getResources().getString(R.string.menu_dismiss_btn)); + button.setImageResource(R.drawable.ic_menu_overflow); button.setEnabled(true); button.setFocusable(true); button.setOnClickListener(new OnClickListener() { @@ -294,10 +401,6 @@ class AppMenuAdapter extends BaseAdapter { } }); - // Set the button layout to make it properly line up with any underlying menu button - ApiCompatibilityUtils.setPaddingRelative( - button, (int) (MENU_BUTTON_START_PADDING_DP * mDpToPx), 0, 0, 0); - button.getLayoutParams().width = (int) (MENU_BUTTON_WIDTH_DP * mDpToPx); button.setScaleType(ScaleType.CENTER); } @@ -339,7 +442,7 @@ class AppMenuAdapter extends BaseAdapter { * @return The {@link Animator}. */ private Animator buildIconItemEnterAnimator(final ImageView[] views, boolean skipLastItem) { - final boolean rtl = LocalizationUtils.isLayoutRtl(); + final boolean rtl = false; //LocalizationUtils.isLayoutRtl(); final float offsetXPx = ENTER_STANDARD_ITEM_OFFSET_X_DP * mDpToPx * (rtl ? -1.f : 1.f); final int maxViewsToAnimate = views.length - (skipLastItem ? 1 : 0); @@ -379,6 +482,11 @@ class AppMenuAdapter extends BaseAdapter { static class StandardMenuItemViewHolder { public TextView text; public AppMenuItemIcon image; + public CheckBox checkbox; + } + + static class TwoButtonMenuItemViewHolder { + public ImageButton[] buttons = new ImageButton[2]; } static class ThreeButtonMenuItemViewHolder { diff --git a/src/com/android/browser/appmenu/AppMenuButtonHelper.java b/src/com/android/browser/appmenu/AppMenuButtonHelper.java index a63e2a51..364183a9 100644 --- a/src/com/android/browser/appmenu/AppMenuButtonHelper.java +++ b/src/com/android/browser/appmenu/AppMenuButtonHelper.java @@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.view.MotionEvent; import android.view.View; import android.view.View.OnTouchListener; -import org.chromium.chrome.browser.UmaBridge; - /** * A helper class for a menu button to decide when to show the app menu and forward touch * events. @@ -46,10 +44,6 @@ public class AppMenuButtonHelper implements OnTouchListener { private boolean showAppMenu(boolean startDragging) { if (!mMenuHandler.isAppMenuShowing() && mMenuHandler.showAppMenu(mMenuButton, false, startDragging)) { - // Initial start dragging can be canceled in case if it was just single tap. - // So we only record non-dragging here, and will deal with those dragging cases in - // AppMenuDragHelper class. - if (!startDragging) UmaBridge.usingMenu(false, false); if (mOnAppMenuShownListener != null) { mOnAppMenuShownListener.run(); @@ -94,13 +88,6 @@ public class AppMenuButtonHelper implements OnTouchListener { default: } - // If user starts to drag on this menu button, ACTION_DOWN and all the subsequent touch - // events are received here. We need to forward this event to the app menu to handle - // dragging correctly. - AppMenuDragHelper dragHelper = mMenuHandler.getAppMenuDragHelper(); - if (dragHelper != null) { - isTouchEventConsumed |= dragHelper.handleDragging(event); - } return isTouchEventConsumed; } }
\ No newline at end of file diff --git a/src/com/android/browser/appmenu/AppMenuDragHelper.java b/src/com/android/browser/appmenu/AppMenuDragHelper.java index 44e642af..ee2a8c75 100644 --- a/src/com/android/browser/appmenu/AppMenuDragHelper.java +++ b/src/com/android/browser/appmenu/AppMenuDragHelper.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.animation.TimeAnimator; import android.annotation.SuppressLint; @@ -18,8 +18,7 @@ import android.widget.LinearLayout; import android.widget.ListPopupWindow; import android.widget.ListView; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.UmaBridge; +import com.android.browser.R; import java.util.ArrayList; @@ -158,7 +157,6 @@ class AppMenuDragHelper { if (!mIsSingleTapUpHappened) { mGestureSingleTapDetector.onTouchEvent(event); if (mIsSingleTapUpHappened) { - UmaBridge.usingMenu(false, false); finishDragging(); } } @@ -182,7 +180,6 @@ class AppMenuDragHelper { didPerformClick = menuItemAction(roundedRawX, roundedRawY, itemAction); if (eventActionMasked == MotionEvent.ACTION_UP && !didPerformClick) { - UmaBridge.usingMenu(false, true); mAppMenu.dismiss(); } else if (eventActionMasked == MotionEvent.ACTION_MOVE) { // Auto scrolling on the top or the bottom of the listView. @@ -245,7 +242,6 @@ class AppMenuDragHelper { break; case ITEM_ACTION_PERFORM: if (shouldPerform) { - UmaBridge.usingMenu(false, true); itemView.performClick(); didPerformClick = true; } diff --git a/src/com/android/browser/appmenu/AppMenuHandler.java b/src/com/android/browser/appmenu/AppMenuHandler.java index 4e2c465f..94a429a7 100644 --- a/src/com/android/browser/appmenu/AppMenuHandler.java +++ b/src/com/android/browser/appmenu/AppMenuHandler.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.app.Activity; import android.content.res.TypedArray; @@ -17,8 +17,6 @@ import android.widget.PopupMenu; import com.google.common.annotations.VisibleForTesting; -import org.chromium.chrome.browser.UmaBridge; - import java.util.ArrayList; /** @@ -34,6 +32,7 @@ public class AppMenuHandler { private final AppMenuPropertiesDelegate mDelegate; private final Activity mActivity; + private boolean mInvalidateInProgress = false; /** * Constructs an AppMenuHandler object. @@ -107,13 +106,27 @@ public class AppMenuHandler { Point pt = new Point(); mActivity.getWindowManager().getDefaultDisplay().getSize(pt); mAppMenu.show(wrapper, anchorView, isByHardwareButton, rotation, appRect, pt.y); - mAppMenuDragHelper.onShow(startDragging); - UmaBridge.menuShow(); return true; } + public void invalidateAppMenu() { + if (!isAppMenuShowing()) return; + if (mInvalidateInProgress) return; + + mInvalidateInProgress = true; + + assert(mMenu != null); + assert(mAppMenu != null); + mDelegate.prepareMenu(mMenu); + + ContextThemeWrapper wrapper = new ContextThemeWrapper(mActivity, + mDelegate.getMenuThemeResourceId()); + + mAppMenu.invalidate(wrapper, mMenu); + mInvalidateInProgress = false; + } + void appMenuDismissed() { - mAppMenuDragHelper.finishDragging(); } /** @@ -132,7 +145,7 @@ public class AppMenuHandler { } AppMenuDragHelper getAppMenuDragHelper() { - return mAppMenuDragHelper; + return null; } /** diff --git a/src/com/android/browser/appmenu/AppMenuItemIcon.java b/src/com/android/browser/appmenu/AppMenuItemIcon.java index eddcc0da..ceecf10b 100644 --- a/src/com/android/browser/appmenu/AppMenuItemIcon.java +++ b/src/com/android/browser/appmenu/AppMenuItemIcon.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.content.Context; import android.util.AttributeSet; diff --git a/src/com/android/browser/appmenu/AppMenuObserver.java b/src/com/android/browser/appmenu/AppMenuObserver.java index c133bc38..febca8ff 100644 --- a/src/com/android/browser/appmenu/AppMenuObserver.java +++ b/src/com/android/browser/appmenu/AppMenuObserver.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; /** * Allows monitoring of application menu actions. diff --git a/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java b/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java index 00dcdfcc..e094a826 100644 --- a/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java +++ b/src/com/android/browser/appmenu/AppMenuPropertiesDelegate.java @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.appmenu; +package com.android.browser.appmenu; import android.view.Menu; diff --git a/src/com/android/browser/stub/NullController.java b/src/com/android/browser/stub/NullController.java index 149fe4ef..1df77db3 100644 --- a/src/com/android/browser/stub/NullController.java +++ b/src/com/android/browser/stub/NullController.java @@ -149,4 +149,6 @@ public class NullController implements ActivityController { return false; } + public void invalidateOptionsMenu() {} + } |