From 9747791d38d84da972144be97654a4f31095d77b Mon Sep 17 00:00:00 2001 From: Wes Johnston Date: Tue, 19 Nov 2013 11:57:35 -0800 Subject: [PATCH] Bug 768667 - Provide an action mode for compatibility with old Android versions. r=sriram --- mobile/android/base/ActionModeCompat.java | 101 ++++++++++++ mobile/android/base/ActionModeCompatView.java | 151 ++++++++++++++++++ mobile/android/base/BrowserApp.java | 81 ++++++++-- .../base/locales/en-US/android_strings.dtd | 5 + mobile/android/base/menu/GeckoMenu.java | 26 ++- mobile/android/base/moz.build | 12 ++ .../base/resources/drawable-hdpi/ab_done.png | Bin 0 -> 737 bytes .../ab_stacked_transparent_light_holo.9.png | Bin 0 -> 222 bytes .../resources/drawable-hdpi/menu_light.png | Bin 0 -> 148 bytes .../base/resources/drawable-mdpi/ab_done.png | Bin 0 -> 552 bytes .../ab_stacked_transparent_light_holo.9.png | Bin 0 -> 210 bytes .../resources/drawable-mdpi/menu_light.png | Bin 0 -> 131 bytes .../base/resources/drawable-xhdpi/ab_done.png | Bin 0 -> 915 bytes .../ab_stacked_transparent_light_holo.9.png | Bin 0 -> 242 bytes .../resources/drawable-xhdpi/menu_light.png | Bin 0 -> 184 bytes .../base/resources/layout/actionbar.xml | 40 +++++ .../base/resources/layout/gecko_app.xml | 20 ++- .../base/resources/values-v11/styles.xml | 16 ++ .../android/base/resources/values/styles.xml | 33 ++++ .../android/base/resources/values/themes.xml | 1 + mobile/android/base/strings.xml.in | 4 + .../android/base/toolbar/BrowserToolbar.java | 3 +- .../android/base/widget/GeckoPopupMenu.java | 5 +- 23 files changed, 467 insertions(+), 31 deletions(-) create mode 100644 mobile/android/base/ActionModeCompat.java create mode 100644 mobile/android/base/ActionModeCompatView.java create mode 100644 mobile/android/base/resources/drawable-hdpi/ab_done.png create mode 100644 mobile/android/base/resources/drawable-hdpi/ab_stacked_transparent_light_holo.9.png create mode 100644 mobile/android/base/resources/drawable-hdpi/menu_light.png create mode 100644 mobile/android/base/resources/drawable-mdpi/ab_done.png create mode 100644 mobile/android/base/resources/drawable-mdpi/ab_stacked_transparent_light_holo.9.png create mode 100644 mobile/android/base/resources/drawable-mdpi/menu_light.png create mode 100644 mobile/android/base/resources/drawable-xhdpi/ab_done.png create mode 100644 mobile/android/base/resources/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png create mode 100644 mobile/android/base/resources/drawable-xhdpi/menu_light.png create mode 100644 mobile/android/base/resources/layout/actionbar.xml diff --git a/mobile/android/base/ActionModeCompat.java b/mobile/android/base/ActionModeCompat.java new file mode 100644 index 000000000000..19d1fb4928b8 --- /dev/null +++ b/mobile/android/base/ActionModeCompat.java @@ -0,0 +1,101 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import org.mozilla.gecko.widget.GeckoPopupMenu; + +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; + +class ActionModeCompat implements GeckoPopupMenu.OnMenuItemClickListener, + View.OnClickListener { + private final String LOGTAG = "GeckoActionModeCompat"; + + private Callback mCallback; + private ActionModeCompatView mView; + private Presenter mPresenter; + + /* A set of callbacks to be called during this ActionMode's lifecycle. These will control the + * creation, interaction with, and destruction of menuitems for the view */ + public static interface Callback { + /* Called when action mode is first created. Implementors should use this to inflate menu resources. */ + public boolean onCreateActionMode(ActionModeCompat mode, Menu menu); + + /* Called to refresh an action mode's action menu. Called whenever the mode is invalidated. Implementors + * should use this to enable/disable/show/hide menu items. */ + public boolean onPrepareActionMode(ActionModeCompat mode, Menu menu); + + /* Called to report a user click on an action button. */ + public boolean onActionItemClicked(ActionModeCompat mode, MenuItem item); + + /* Called when an action mode is about to be exited and destroyed. */ + public void onDestroyActionMode(ActionModeCompat mode); + } + + /* Presenters handle the actual showing/hiding of the action mode UI in the app. Its their responsibility + * to create an action mode, and assign it Callbacks and ActionModeCompatView's. */ + public static interface Presenter { + /* Called when an action mode should be shown */ + public void startActionModeCompat(final Callback callback); + + /* Called when whatever action mode is showing should be hidden */ + public void endActionModeCompat(); + } + + public ActionModeCompat(Presenter presenter, Callback callback, ActionModeCompatView view) { + mPresenter = presenter; + mCallback = callback; + + mView = view; + mView.initForMode(this); + } + + public void finish() { + // Clearing the menu will also clear the ActionItemBar + mView.getMenu().clear(); + if (mCallback != null) { + mCallback.onDestroyActionMode(this); + } + } + + public CharSequence getTitle() { + return mView.getTitle(); + } + + public void setTitle(CharSequence title) { + mView.setTitle(title); + } + + public void setTitle(int resId) { + mView.setTitle(resId); + } + + public Menu getMenu() { + return mView.getMenu(); + } + + public void invalidate() { + if (mCallback != null) { + mCallback.onPrepareActionMode(this, mView.getMenu()); + } + mView.invalidate(); + } + + /* GeckoPopupMenu.OnMenuItemClickListener */ + @Override + public boolean onMenuItemClick(MenuItem item) { + if (mCallback != null) { + return mCallback.onActionItemClicked(this, item); + } + return false; + } + + /* View.OnClickListener*/ + @Override + public void onClick(View v) { + mPresenter.endActionModeCompat(); + } +} diff --git a/mobile/android/base/ActionModeCompatView.java b/mobile/android/base/ActionModeCompatView.java new file mode 100644 index 000000000000..5e1184a9661a --- /dev/null +++ b/mobile/android/base/ActionModeCompatView.java @@ -0,0 +1,151 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.gecko; + +import org.mozilla.gecko.menu.GeckoMenu; +import org.mozilla.gecko.menu.MenuPopup; +import org.mozilla.gecko.menu.MenuPanel; +import org.mozilla.gecko.menu.MenuItemActionBar; +import org.mozilla.gecko.widget.GeckoPopupMenu; + +import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuInflater; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.view.View; +import android.view.ViewGroup; +import android.content.Context; +import android.widget.TextView; +import android.widget.ImageButton; +import android.widget.Button; +import android.widget.PopupWindow; +import android.util.AttributeSet; + +class ActionModeCompatView extends LinearLayout implements GeckoMenu.ActionItemBarPresenter { + private final String LOGTAG = "GeckoActionModeCompatPresenter"; + + private static final int SPEC = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); + + private Button mTitleView; + private ImageButton mMenuButton; + private ViewGroup mActionButtonBar; + private GeckoPopupMenu mPopupMenu; + + // Maximum number of items to show as actions + private static final int MAX_ACTION_ITEMS = 4; + + private int mActionButtonsWidth = 0; + + public ActionModeCompatView(Context context) { + this(context, null); + } + + public ActionModeCompatView(Context context, AttributeSet attrs) { + this(context, null, 0); + } + + public ActionModeCompatView(Context context, AttributeSet attrs, int style) { + super(context, attrs, style); + } + + @Override + public void onFinishInflate() { + mTitleView = (Button) findViewById(R.id.actionmode_title); + mMenuButton = (ImageButton) findViewById(R.id.actionbar_menu); + mActionButtonBar = (ViewGroup) findViewById(R.id.actionbar_buttons); + + mPopupMenu = new GeckoPopupMenu(getContext(), mMenuButton); + ((GeckoMenu) mPopupMenu.getMenu()).setActionItemBarPresenter(this); + + mMenuButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + openMenu(); + } + }); + } + + public void initForMode(final ActionModeCompat mode) { + mTitleView.setOnClickListener(mode); + mPopupMenu.setOnMenuItemClickListener(mode); + } + + public CharSequence getTitle() { + return mTitleView.getText(); + } + + public void setTitle(CharSequence title) { + mTitleView.setText(title); + } + + public void setTitle(int resId) { + mTitleView.setText(resId); + } + + public Menu getMenu() { + return mPopupMenu.getMenu(); + } + + public void invalidate() { + mMenuButton.setVisibility(mPopupMenu.getMenu().hasVisibleItems() ? View.VISIBLE : View.GONE); + super.invalidate(); + } + + /* GeckoMenu.ActionItemBarPresenter */ + @Override + public boolean addActionItem(View actionItem) { + final int count = mActionButtonBar.getChildCount(); + if (count >= MAX_ACTION_ITEMS) { + return false; + } + + int maxWidth = mActionButtonBar.getMeasuredWidth(); + if (maxWidth == 0) { + mActionButtonBar.measure(SPEC, SPEC); + maxWidth = mActionButtonBar.getMeasuredWidth(); + } + + // Since we don't know how many items will be added, we always reserve space for the overflow menu + mMenuButton.measure(SPEC, SPEC); + maxWidth -= mMenuButton.getMeasuredWidth(); + + if (mActionButtonsWidth <= 0) { + mActionButtonsWidth = 0; + + // Loop over child views, measure them, and add their width to the taken width + for (int i = 0; i < count; i++) { + View v = mActionButtonBar.getChildAt(i); + v.measure(SPEC, SPEC); + mActionButtonsWidth += v.getMeasuredWidth(); + } + } + + actionItem.measure(SPEC, SPEC); + int w = actionItem.getMeasuredWidth(); + if (mActionButtonsWidth + w < maxWidth) { + // We cache the new width of our children. + mActionButtonsWidth += w; + mActionButtonBar.addView(actionItem); + return true; + } + return false; + } + + /* GeckoMenu.ActionItemBarPresenter */ + @Override + public void removeActionItem(View actionItem) { + mActionButtonsWidth -= actionItem.getMeasuredWidth(); + mActionButtonBar.removeView(actionItem); + } + + public void openMenu() { + mPopupMenu.openMenu(); + } + + public void closeMenu() { + mPopupMenu.dismiss(); + } + +} diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 26a6954d7390..859197dea7c1 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -14,6 +14,7 @@ import org.mozilla.gecko.favicons.LoadFaviconTask; import org.mozilla.gecko.gfx.BitmapUtils; import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.ImmutableViewportMetrics; +import org.mozilla.gecko.gfx.LayerMarginsAnimator; import org.mozilla.gecko.health.BrowserHealthRecorder; import org.mozilla.gecko.health.BrowserHealthReporter; import org.mozilla.gecko.home.BrowserSearch; @@ -71,8 +72,10 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewStub; import android.view.animation.Interpolator; +import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Toast; +import android.widget.ViewFlipper; import java.io.File; import java.io.FileNotFoundException; @@ -88,7 +91,8 @@ abstract public class BrowserApp extends GeckoApp BrowserSearch.OnSearchListener, BrowserSearch.OnEditSuggestionListener, HomePager.OnNewTabsListener, - OnUrlOpenListener { + OnUrlOpenListener, + ActionModeCompat.Presenter { private static final String LOGTAG = "GeckoBrowserApp"; private static final String PREF_CHROME_DYNAMICTOOLBAR = "browser.chrome.dynamictoolbar"; @@ -111,10 +115,13 @@ abstract public class BrowserApp extends GeckoApp private BrowserSearch mBrowserSearch; private View mBrowserSearchContainer; + public ViewFlipper mViewFlipper; + public ActionModeCompatView mActionBar; private BrowserToolbar mBrowserToolbar; private HomePager mHomePager; private View mHomePagerContainer; protected Telemetry.Timer mAboutHomeStartupTimer = null; + private ActionModeCompat mActionMode; private static final int GECKO_TOOLS_MENU = -1; private static final int ADDON_MENU_OFFSET = 1000; @@ -265,7 +272,7 @@ abstract public class BrowserApp extends GeckoApp switch (keyCode) { case KeyEvent.KEYCODE_BUTTON_Y: // Toggle/focus the address bar on gamepad-y button. - if (mBrowserToolbar.isVisible()) { + if (mViewFlipper.getVisibility() == View.VISIBLE) { if (isDynamicToolbarEnabled() && !isHomePagerVisible()) { if (mLayerView != null) { mLayerView.getLayerMarginsAnimator().hideMargins(false); @@ -425,6 +432,9 @@ abstract public class BrowserApp extends GeckoApp super.onCreate(savedInstanceState); + mViewFlipper = (ViewFlipper) findViewById(R.id.browser_actionbar); + mActionBar = (ActionModeCompatView) findViewById(R.id.actionbar); + mBrowserToolbar = (BrowserToolbar) findViewById(R.id.browser_toolbar); if (Intent.ACTION_VIEW.equals(intent.getAction())) { // Show the target URL immediately in the toolbar @@ -602,6 +612,11 @@ abstract public class BrowserApp extends GeckoApp return; } + if (mActionMode != null) { + endActionModeCompat(); + return; + } + super.onBackPressed(); } @@ -660,7 +675,7 @@ abstract public class BrowserApp extends GeckoApp mLayerView.getLayerClient().setOnMetricsChangedListener(this); } setToolbarMargin(0); - mHomePagerContainer.setPadding(0, mBrowserToolbar.getHeight(), 0, 0); + mHomePagerContainer.setPadding(0, mViewFlipper.getHeight(), 0, 0); } else { // Immediately show the toolbar when disabling the dynamic // toolbar. @@ -668,8 +683,8 @@ abstract public class BrowserApp extends GeckoApp mLayerView.getLayerClient().setOnMetricsChangedListener(null); } mHomePagerContainer.setPadding(0, 0, 0, 0); - if (mBrowserToolbar != null) { - mBrowserToolbar.scrollTo(0, 0); + if (mViewFlipper != null) { + mViewFlipper.scrollTo(0, 0); } } @@ -902,7 +917,7 @@ abstract public class BrowserApp extends GeckoApp @Override public void onMetricsChanged(ImmutableViewportMetrics aMetrics) { - if (isHomePagerVisible() || mBrowserToolbar == null) { + if (isHomePagerVisible() || mViewFlipper == null) { return; } @@ -911,7 +926,7 @@ abstract public class BrowserApp extends GeckoApp if (aMetrics.getPageHeight() <= aMetrics.getHeight()) { if (mDynamicToolbarCanScroll) { mDynamicToolbarCanScroll = false; - if (!mBrowserToolbar.isVisible()) { + if (mViewFlipper.getVisibility() != View.VISIBLE) { ThreadUtils.postToUiThread(new Runnable() { public void run() { mLayerView.getLayerMarginsAnimator().showMargins(false); @@ -923,7 +938,7 @@ abstract public class BrowserApp extends GeckoApp mDynamicToolbarCanScroll = true; } - final View toolbarLayout = mBrowserToolbar; + final View toolbarLayout = mViewFlipper; final int marginTop = Math.round(aMetrics.marginTop); ThreadUtils.postToUiThread(new Runnable() { public void run() { @@ -958,8 +973,8 @@ abstract public class BrowserApp extends GeckoApp public void refreshToolbarHeight() { int height = 0; - if (mBrowserToolbar != null) { - height = mBrowserToolbar.getHeight(); + if (mViewFlipper != null) { + height = mViewFlipper.getHeight(); } if (!isDynamicToolbarEnabled() || isHomePagerVisible()) { @@ -992,9 +1007,9 @@ abstract public class BrowserApp extends GeckoApp @Override public void run() { if (aShow) { - mBrowserToolbar.show(); + mViewFlipper.setVisibility(View.VISIBLE); } else { - mBrowserToolbar.hide(); + mViewFlipper.setVisibility(View.GONE); if (hasTabsSideBar()) { hideTabs(); } @@ -1010,8 +1025,8 @@ abstract public class BrowserApp extends GeckoApp ThreadUtils.postToUiThread(new Runnable() { @Override public void run() { - mBrowserToolbar.show(); - mBrowserToolbar.requestFocusFromTouch(); + mViewFlipper.setVisibility(View.VISIBLE); + mViewFlipper.requestFocusFromTouch(); } }); } @@ -1974,13 +1989,13 @@ abstract public class BrowserApp extends GeckoApp @Override public void run() { if (fullscreen) { - mBrowserToolbar.hide(); + mViewFlipper.setVisibility(View.GONE); if (isDynamicToolbarEnabled()) { mLayerView.getLayerMarginsAnimator().hideMargins(true); mLayerView.getLayerMarginsAnimator().setMaxMargins(0, 0, 0, 0); } } else { - mBrowserToolbar.show(); + mViewFlipper.setVisibility(View.VISIBLE); if (isDynamicToolbarEnabled()) { mLayerView.getLayerMarginsAnimator().showMargins(true); mLayerView.getLayerMarginsAnimator().setMaxMargins(0, mToolbarHeight, 0, 0); @@ -2461,4 +2476,38 @@ abstract public class BrowserApp extends GeckoApp Log.w(LOGTAG, "No candidate updater found; ignoring launch request."); return false; } + + /* Implementing ActionModeCompat.Presenter */ + @Override + public void startActionModeCompat(final ActionModeCompat.Callback callback) { + // If actionMode is null, we're not currently showing one. Flip to the action mode view + if (mActionMode == null) { + mViewFlipper.showNext(); + LayerMarginsAnimator margins = mLayerView.getLayerMarginsAnimator(); + margins.setMaxMargins(0, mViewFlipper.getHeight(), 0, 0); + margins.setMarginsPinned(true); + margins.showMargins(false); + } else { + // Otherwise, we're already showing an action mode. Just finish it and show the new one + mActionMode.finish(); + } + + mActionMode = new ActionModeCompat(BrowserApp.this, callback, mActionBar); + if (callback.onCreateActionMode(mActionMode, mActionMode.getMenu())) { + mActionMode.invalidate(); + } + } + + /* Implementing ActionModeCompat.Presenter */ + @Override + public void endActionModeCompat() { + if (mActionMode == null) { + return; + } + + mActionMode.finish(); + mActionMode = null; + mLayerView.getLayerMarginsAnimator().setMarginsPinned(false); + mViewFlipper.showPrevious(); + } } diff --git a/mobile/android/base/locales/en-US/android_strings.dtd b/mobile/android/base/locales/en-US/android_strings.dtd index 72e1ae1ae5b6..e6b04fa9766d 100644 --- a/mobile/android/base/locales/en-US/android_strings.dtd +++ b/mobile/android/base/locales/en-US/android_strings.dtd @@ -372,3 +372,8 @@ just addresses the organization to follow, e.g. "This site is run by " --> + + + + diff --git a/mobile/android/base/menu/GeckoMenu.java b/mobile/android/base/menu/GeckoMenu.java index a3f49dac1a73..49f60044dcc1 100644 --- a/mobile/android/base/menu/GeckoMenu.java +++ b/mobile/android/base/menu/GeckoMenu.java @@ -66,7 +66,7 @@ public class GeckoMenu extends ListView */ public static interface ActionItemBarPresenter { // Add an action-item. - public void addActionItem(View actionItem); + public boolean addActionItem(View actionItem); // Remove an action-item. public void removeActionItem(View actionItem); @@ -151,7 +151,7 @@ public class GeckoMenu extends ListView mItems.add(menuItem); } - private void addActionItem(final GeckoMenuItem menuItem) { + private boolean addActionItem(final GeckoMenuItem menuItem) { menuItem.setOnShowAsActionChangedListener(this); if (mActionItems.size() == 0 && @@ -173,6 +173,8 @@ public class GeckoMenu extends ListView mActionItems.put(menuItem, actionView); mActionItemBarPresenter.addActionItem(actionView); mItems.add(menuItem); + + return true; } @Override @@ -224,6 +226,12 @@ public class GeckoMenu extends ListView mAdapter.clear(); mItems.clear(); + + if (mActionItemBarPresenter != null) { + for (View item : mActionItems.values()) { + mActionItemBarPresenter.removeActionItem(item); + } + } mActionItems.clear(); } @@ -266,7 +274,7 @@ public class GeckoMenu extends ListView @Override public boolean hasVisibleItems() { for (GeckoMenuItem menuItem : mItems) { - if (menuItem.isVisible()) + if (menuItem.isVisible() && !mActionItems.containsKey(menuItem)) return true; } @@ -362,10 +370,11 @@ public class GeckoMenu extends ListView public void onShowAsActionChanged(GeckoMenuItem item, boolean isActionItem) { removeItem(item.getItemId()); - if (isActionItem) - addActionItem(item); - else - addItem(item); + if (isActionItem && addActionItem(item)) { + return; + } + + addItem(item); } public void onItemChanged(GeckoMenuItem item) { @@ -476,11 +485,12 @@ public class GeckoMenu extends ListView } @Override - public void addActionItem(View actionItem) { + public boolean addActionItem(View actionItem) { LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(actionItem.getLayoutParams()); params.weight = 1.0f; actionItem.setLayoutParams(params); addView(actionItem); + return true; } @Override diff --git a/mobile/android/base/moz.build b/mobile/android/base/moz.build index 16d0f461d1e3..c4eefdb1c78c 100644 --- a/mobile/android/base/moz.build +++ b/mobile/android/base/moz.build @@ -82,6 +82,8 @@ if CONFIG['MOZ_WEBRTC']: gbjar = add_java_jar('gecko-browser') gbjar.sources += [ + 'ActionModeCompat.java', + 'ActionModeCompatView.java', 'ActivityHandlerHelper.java', 'AlertNotification.java', 'animation/AnimatorProxy.java', @@ -404,6 +406,8 @@ ANDROID_RESFILES += [ 'resources/drawable-hdpi-v11/ic_menu_share.png', 'resources/drawable-hdpi-v11/ic_menu_tools.png', 'resources/drawable-hdpi-v11/ic_status_logo.png', + 'resources/drawable-hdpi/ab_done.png', + 'resources/drawable-hdpi/ab_stacked_transparent_light_holo.9.png', 'resources/drawable-hdpi/abouthome_thumbnail.png', 'resources/drawable-hdpi/alert_addon.png', 'resources/drawable-hdpi/alert_app.png', @@ -461,6 +465,7 @@ ANDROID_RESFILES += [ 'resources/drawable-hdpi/menu_item_check.png', 'resources/drawable-hdpi/menu_item_more.png', 'resources/drawable-hdpi/menu_item_uncheck.png', + 'resources/drawable-hdpi/menu_light.png', 'resources/drawable-hdpi/menu_panel_bg.9.png', 'resources/drawable-hdpi/menu_pb.png', 'resources/drawable-hdpi/menu_popup_arrow_bottom.png', @@ -542,6 +547,8 @@ ANDROID_RESFILES += [ 'resources/drawable-mdpi-v11/ic_menu_share.png', 'resources/drawable-mdpi-v11/ic_menu_tools.png', 'resources/drawable-mdpi-v11/ic_status_logo.png', + 'resources/drawable-mdpi/ab_done.png', + 'resources/drawable-mdpi/ab_stacked_transparent_light_holo.9.png', 'resources/drawable-mdpi/abouthome_thumbnail.png', 'resources/drawable-mdpi/alert_addon.png', 'resources/drawable-mdpi/alert_app.png', @@ -602,6 +609,7 @@ ANDROID_RESFILES += [ 'resources/drawable-mdpi/menu_item_check.png', 'resources/drawable-mdpi/menu_item_more.png', 'resources/drawable-mdpi/menu_item_uncheck.png', + 'resources/drawable-mdpi/menu_light.png', 'resources/drawable-mdpi/menu_panel_bg.9.png', 'resources/drawable-mdpi/menu_pb.png', 'resources/drawable-mdpi/menu_popup_arrow_bottom.png', @@ -678,6 +686,8 @@ ANDROID_RESFILES += [ 'resources/drawable-xhdpi-v11/ic_menu_share.png', 'resources/drawable-xhdpi-v11/ic_menu_tools.png', 'resources/drawable-xhdpi-v11/ic_status_logo.png', + 'resources/drawable-xhdpi/ab_done.png', + 'resources/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png', 'resources/drawable-xhdpi/abouthome_thumbnail.png', 'resources/drawable-xhdpi/alert_addon.png', 'resources/drawable-xhdpi/alert_app.png', @@ -733,6 +743,7 @@ ANDROID_RESFILES += [ 'resources/drawable-xhdpi/menu_item_check.png', 'resources/drawable-xhdpi/menu_item_more.png', 'resources/drawable-xhdpi/menu_item_uncheck.png', + 'resources/drawable-xhdpi/menu_light.png', 'resources/drawable-xhdpi/menu_panel_bg.9.png', 'resources/drawable-xhdpi/menu_pb.png', 'resources/drawable-xhdpi/menu_popup_arrow_bottom.png', @@ -830,6 +841,7 @@ ANDROID_RESFILES += [ 'resources/layout-xlarge-v11/home_history_tabs_indicator.xml', 'resources/layout-xlarge-v11/remote_tabs_child.xml', 'resources/layout-xlarge-v11/remote_tabs_group.xml', + 'resources/layout/actionbar.xml', 'resources/layout/arrow_popup.xml', 'resources/layout/autocomplete_list.xml', 'resources/layout/autocomplete_list_item.xml', diff --git a/mobile/android/base/resources/drawable-hdpi/ab_done.png b/mobile/android/base/resources/drawable-hdpi/ab_done.png new file mode 100644 index 0000000000000000000000000000000000000000..ed03f620f8ef9e969d0471ab76329038e25c9f0d GIT binary patch literal 737 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA0wn)(8}a}trX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfizez!?|}o;S3CnFFjoxLn02py%z6(IY8q0$M=`{k_{&Q=;t<2 zt8!*r>&D`|W2$+>pS=eAb}M##+^cbdA4dCLPr0$oL~Mm8Bn#4$+9@L$(#*Pp%fW0&@t4F~+Q4$6OeIrG`|nG22@uVa-C zJ=H0n)NABBE9V2ZrDh$}Ob?>#U7^{{%b z^;_|*S@)*|RLscvyw85$_Y2}8p?L-UY)vO;|NFUQJ(sNEA?BESpVrme#d7mboB7l} z-Tl+e|M{(6F|!lpnSU$jtXi?CXvKcs<;$n_y<4FKOaZDTt`Q|Ei6yC4$wjF^iowXh z&`{UFLf61N#L&#jz{twj7|6CVFbMhoZ8M67-29Zxv`Q2WrdForKm^fXYnBlV)F276 tAviy+q&%@GmBBG3KPgqgGdD3kH7GSPrLyp3str&PgQu&X%Q~loCIB{EJ2wCT literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-hdpi/ab_stacked_transparent_light_holo.9.png b/mobile/android/base/resources/drawable-hdpi/ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..55f8ae5a633f19ce0bb45c19619f5d1206a000b8 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^Y9P$P1|(P5zFY^S*pj^6T^Rm@;DWu&Cj&(|3p^r= z85p>QL70(Y)*K0-AbW|YuPggqZdP^~Vb?!-B|xEUPZ!6Kh{JDhY~*YR;AwfdyZwP& z*|vQ3=Uca43Opy-A|m)tTA}8Ng6kZY(2a9d^kzBeA3EWydY~CJYD@<);T3K F0RSlSOHu#; literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-hdpi/menu_light.png b/mobile/android/base/resources/drawable-hdpi/menu_light.png new file mode 100644 index 0000000000000000000000000000000000000000..bb6aef1d069a14a7fc1cea9780c919c61679e4fa GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtXipc%kc@k8uWjUIP~c#3xZ62X z=G4p^oaPsfxfS0Jish)R3f(&WG9yqa14Evg(y_dGGlfCy2iXqR3?>_SEs{VyhV?DH iJ0OaDc|iOR772{!kNsXaOPT8&i0|p@=d#Wzp$Py$I4IEo literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-mdpi/ab_done.png b/mobile/android/base/resources/drawable-mdpi/ab_done.png new file mode 100644 index 0000000000000000000000000000000000000000..b28b3b54f4c81d482f797f31936cbd4013c093b5 GIT binary patch literal 552 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE0wix1Z>k4UOiAAEE)4(M`_JqL@;D1TB8!2v z2N=7Z%(epwmK8Xr18D^?ZvQoBE&~Ijfv1aOh{y4_S9ba-JBqkHTrZXEaifjpNYW7o zp-Ubd&IgJo2<&v8$G35^;Tskk#t2~^NlC?&yDV(Ca&uB1b9CBkO)cqrw|D8TKToRF zI(8j)Hm_*m)V}Gu(AmZ?>+lr!|Ew$fc6F-Mb^2PC^>5kCb?-yw@xD*CTf6%^rv51n zu|M&RMY8TuK!x`HjjgjxbG!Ig&nSGQ(EnVUqiU&qoaH15q1mNr`vuRlFlL+adKX`+ zs(G(GZ+*gGNpURMpV)N-wqLW)~-JKU!1N^uTZarp(au zRVr*pp2gnEY&GXI)J=?c?L+7E14!w(i?Kf2&j6te3n$Zi&Cq1Pnyg64!{5l*E!$ ztK_0oAjM#0U}&goV4-VZ9%5)_Wng4wYz$;u85o58|F#)LLvDUbW?ChR22(3jb0C6f zurQ*`~AJfKj#r;B5V$MLt<47pkZcw8>-RNBFB z9sT`DRqon9-aFqp)QI)>r~E3IF+piXChr2S3ClmPxY-}S``U!knZ`?kxwKX+XyVd( z!N>IGYDfOscV~+~UGF`na`W6v>)wFN50C6*cpo5Db#1z?4A3eDPgg&ebxsLQ0CY%8 A^#A|> literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-mdpi/menu_light.png b/mobile/android/base/resources/drawable-mdpi/menu_light.png new file mode 100644 index 0000000000000000000000000000000000000000..01d681697f799729aa60bcc03878b8718ef5f705 GIT binary patch literal 131 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzFHaZ8kch)?uW#gKP~c&9OkaNH zNWhsXa}P0HP*CC8e>x;QVw%w1wevX{81fiqT9$oZHH(4a215zM2{s3I28IOo7eJ#J d>KPlRN5&o6d@ywr|9haR44$rjF6*2UngC}HDAND{ literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-xhdpi/ab_done.png b/mobile/android/base/resources/drawable-xhdpi/ab_done.png new file mode 100644 index 0000000000000000000000000000000000000000..bb19810bc2062509e4e4968099a359ad73818728 GIT binary patch literal 915 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I0wfs{c7_5;rX+877l!}s{b%+Ad7K3vk;OpT z1B~5HX4`=T%L*LRfwTh{zxw0jNgl<&3j(^ zeD(x}!be9sh1LD$__>xwFX-mty1-MRJ?GVgBPRYo&#phmts!D?ltV3&FI%+a$=z1Z zV;YHl1iMSDgJ+|>#46F---v^ z=n46F|IdfFb=)S0I4Coo@!g}n4Nex)S*)#RZPN@k9D49tzo1o|L;8h-cSg(aGrNAg7qQ^lmAJNnY2BwD zmg$yB$_Kc(9`bFT@$ln4rdg7D8~IZ-f3I60`0mq%qw5167@Xn!BqR{_Lfuy~aYE2x zQ4_Q6{SU<2c z;lT8&TH+c}l9E`GYL#4+3Zxi}3=9o*4J>pG%tH*#tPG5-jE#Y8D+7a&|KB#FXvob^ z$xN$6(O_z2Y7RsY4Yp<(!9Wd?ARB`7(@M${i&7aJQ}UBi6+Ckj(^G>|6H_V+Po~-c P6)||a`njxgN@xNAiwS~- literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png b/mobile/android/base/resources/drawable-xhdpi/ab_stacked_transparent_light_holo.9.png new file mode 100644 index 0000000000000000000000000000000000000000..28aeaa77b7fdfd3dde728b6f19956767fe230b51 GIT binary patch literal 242 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-wj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwYn_bLGrL)Krq^{o6#W5t~-rHLnc^eFPTrOI-9FZ&8 z^5)2%Eg=S{E~c=^EPU~wb&-1X$~P*j&XuX`{G_XXvC{VItV7>&uP$+9Vq)PCP;h8q zV8q3!a<~8K8&Q2=1!@ZjI$>TXL%ryt=7@f1lSKVXJ`V4dmgQu&X J%Q~loCIE)8Oo#vg literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/drawable-xhdpi/menu_light.png b/mobile/android/base/resources/drawable-xhdpi/menu_light.png new file mode 100644 index 0000000000000000000000000000000000000000..930ca8d95e8bee5a1240fba645d9dab919abd734 GIT binary patch literal 184 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=^`0({Ar-gYUf;;epuoZ6aJO@& z%&D0-IKvGL&8p&qV;O7KuliPO1yl(K>(rHwor_8Hg9|Y9Gj8!^hz0Vk4~QZ}ABcvv nF)(akj$uTI?LshtEWgbR4Rf6*RPme*0Ev6L`njxgN@xNAEX^ml literal 0 HcmV?d00001 diff --git a/mobile/android/base/resources/layout/actionbar.xml b/mobile/android/base/resources/layout/actionbar.xml new file mode 100644 index 000000000000..8d2f3afbe3ed --- /dev/null +++ b/mobile/android/base/resources/layout/actionbar.xml @@ -0,0 +1,40 @@ + + + + + + + +