Bug 965548 - Part 3: Add cancel button for phone layout. r=bnicholson
authorMichael Comella <michael.l.comella@gmail.com>
Thu, 17 Apr 2014 13:34:12 -0700
changeset 179085 6a49f6cb358226b712f712b32c0159eb374b4638
parent 179084 8998623049ceccadde6e9c621dc1b5e290fefe4a
child 179086 be018ccdcb8220a0fbc8be391cb67a20f0b6bc11
push id26606
push userryanvm@gmail.com
push dateFri, 18 Apr 2014 02:20:00 +0000
treeherdermozilla-central@ec728bfdbb79 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbnicholson
bugs965548
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 965548 - Part 3: Add cancel button for phone layout. r=bnicholson
mobile/android/base/moz.build
mobile/android/base/resources/drawable/toolbar_separator_pb.xml
mobile/android/base/resources/drawable/toolbar_separator_selector.xml
mobile/android/base/resources/layout/browser_toolbar.xml
mobile/android/base/toolbar/BrowserToolbar.java
mobile/android/base/toolbar/ToolbarEditLayout.java
mobile/android/base/widget/ThemedView.java.in
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -434,16 +434,17 @@ gbjar.generated_sources += [
     'org/mozilla/gecko/SysInfo.java',
     'org/mozilla/gecko/widget/ThemedEditText.java',
     'org/mozilla/gecko/widget/ThemedImageButton.java',
     'org/mozilla/gecko/widget/ThemedImageView.java',
     'org/mozilla/gecko/widget/ThemedLinearLayout.java',
     'org/mozilla/gecko/widget/ThemedRelativeLayout.java',
     'org/mozilla/gecko/widget/ThemedTextSwitcher.java',
     'org/mozilla/gecko/widget/ThemedTextView.java',
+    'org/mozilla/gecko/widget/ThemedView.java',
 ]
 if CONFIG['MOZ_CRASHREPORTER']:
     gbjar.sources += [ 'CrashReporter.java' ]
     ANDROID_RES_DIRS += [ SRCDIR + '/crashreporter/res' ]
 
 gbjar.sources += sync_java_files
 gbjar.generated_sources += sync_generated_java_files
 gbjar.extra_jars = [
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/toolbar_separator_pb.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+
+    <solid android:color="#222"/>
+    <size android:width="1dp" />
+
+</shape>
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/resources/drawable/toolbar_separator_selector.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+
+<!-- Note that android:color="@color/toolbar_separator" (which uses a selector)
+     directly in the <shape> does not appear to work, so instead we select
+     between two shapes with different colors. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:gecko="http://schemas.android.com/apk/res-auto">
+
+    <item gecko:state_private="true" android:drawable="@drawable/toolbar_separator_pb"/>
+    <item android:drawable="@drawable/toolbar_separator"/>
+
+</selector>
--- a/mobile/android/base/resources/layout/browser_toolbar.xml
+++ b/mobile/android/base/resources/layout/browser_toolbar.xml
@@ -81,18 +81,39 @@
                         style="@style/UrlBar.ImageButton.TabCount"
                         android:layout_width="24dip"
                         android:layout_height="24dip"
                         android:layout_marginLeft="40dip"
                         android:layout_marginRight="8dip"
                         android:layout_marginTop="12dip"
                         android:layout_alignRight="@id/tabs"/>
 
+    <!-- Note that the edit components are invisible so that the views
+         depending on their location can properly layout. -->
+    <ImageView android:id="@+id/edit_cancel"
+               style="@style/UrlBar.ImageButton.Icon"
+               android:layout_alignParentRight="true"
+               android:src="@drawable/close_edit_mode"
+               android:contentDescription="@string/edit_mode_cancel"
+               android:visibility="invisible"/>
+
+    <org.mozilla.gecko.widget.ThemedView android:id="@+id/edit_separator"
+                                         android:layout_toLeftOf="@id/edit_cancel"
+                                         android:layout_width="1dip"
+                                         android:layout_height="match_parent"
+                                         android:layout_marginTop="12dp"
+                                         android:layout_marginBottom="12dp"
+                                         android:layout_marginLeft="8dp"
+                                         android:layout_marginRight="2dp"
+                                         android:background="@drawable/toolbar_separator_selector"
+                                         android:visibility="invisible"/>
+
     <org.mozilla.gecko.toolbar.ToolbarEditLayout android:id="@+id/edit_layout"
                   style="@style/UrlBar.Button"
+                  android:layout_toLeftOf="@id/edit_separator"
                   android:layout_marginLeft="4dp"
                   android:layout_marginRight="4dp"
                   android:paddingLeft="8dp"
                   android:visibility="gone"/>
 
     <org.mozilla.gecko.toolbar.ToolbarDisplayLayout android:id="@+id/display_layout"
                   style="@style/UrlBar.Button"
                   android:layout_toLeftOf="@id/tabs"
--- a/mobile/android/base/toolbar/BrowserToolbar.java
+++ b/mobile/android/base/toolbar/BrowserToolbar.java
@@ -15,30 +15,32 @@ import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoApplication;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.LightweightTheme;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
 import org.mozilla.gecko.animation.PropertyAnimator;
+import org.mozilla.gecko.animation.PropertyAnimator.Property;
 import org.mozilla.gecko.animation.PropertyAnimator.PropertyAnimationListener;
 import org.mozilla.gecko.animation.ViewHelper;
 import org.mozilla.gecko.menu.GeckoMenu;
 import org.mozilla.gecko.menu.MenuPopup;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnStopListener;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.OnTitleChangeListener;
 import org.mozilla.gecko.toolbar.ToolbarDisplayLayout.UpdateFlags;
 import org.mozilla.gecko.util.Clipboard;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.HardwareUtils;
 import org.mozilla.gecko.util.MenuUtils;
 import org.mozilla.gecko.widget.ThemedImageButton;
 import org.mozilla.gecko.widget.ThemedImageView;
 import org.mozilla.gecko.widget.ThemedRelativeLayout;
+import org.mozilla.gecko.widget.ThemedView;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
 import android.os.Build;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -127,16 +129,19 @@ public class BrowserToolbar extends Them
     private ToolbarProgressView mProgressBar;
     private TabCounter mTabsCounter;
     private ThemedImageButton mMenu;
     private ThemedImageView mMenuIcon;
     private LinearLayout mActionItemBar;
     private MenuPopup mMenuPopup;
     private List<View> mFocusOrder;
 
+    private final ThemedView editSeparator;
+    private final View editCancel;
+
     private OnActivateListener mActivateListener;
     private OnCommitListener mCommitListener;
     private OnDismissListener mDismissListener;
     private OnFilterListener mFilterListener;
     private OnFocusChangeListener mFocusChangeListener;
     private OnStartEditingListener mStartEditingListener;
     private OnStopEditingListener mStopEditingListener;
 
@@ -202,16 +207,19 @@ public class BrowserToolbar extends Them
         mForward = (ImageButton) findViewById(R.id.forward);
         setButtonEnabled(mForward, false);
 
         mMenu = (ThemedImageButton) findViewById(R.id.menu);
         mMenuIcon = (ThemedImageView) findViewById(R.id.menu_icon);
         mActionItemBar = (LinearLayout) findViewById(R.id.menu_items);
         mHasSoftMenuButton = !HardwareUtils.hasMenuButton();
 
+        editSeparator = (ThemedView) findViewById(R.id.edit_separator);
+        editCancel = findViewById(R.id.edit_cancel);
+
         // We use different layouts on phones and tablets, so adjust the focus
         // order appropriately.
         mFocusOrder = new ArrayList<View>();
         if (HardwareUtils.isTablet()) {
             mFocusOrder.addAll(Arrays.asList(mTabs, mBack, mForward, this));
             mFocusOrder.addAll(mUrlDisplayLayout.getFocusOrder());
             mFocusOrder.addAll(Arrays.asList(mActionItemBar, mMenu));
         } else {
@@ -348,16 +356,23 @@ public class BrowserToolbar extends Them
         });
         mForward.setOnLongClickListener(new Button.OnLongClickListener() {
             @Override
             public boolean onLongClick(View view) {
                 return Tabs.getInstance().getSelectedTab().showForwardHistory();
             }
         });
 
+        editCancel.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                cancelEdit();
+            }
+        });
+
         if (mHasSoftMenuButton) {
             mMenu.setVisibility(View.VISIBLE);
             mMenuIcon.setVisibility(View.VISIBLE);
 
             mMenu.setOnClickListener(new Button.OnClickListener() {
                 @Override
                 public void onClick(View view) {
                     mActivity.openOptionsMenu();
@@ -570,17 +585,20 @@ public class BrowserToolbar extends Them
         mTabs.setNextFocusDownId(nextId);
         mBack.setNextFocusDownId(nextId);
         mForward.setNextFocusDownId(nextId);
         mUrlDisplayLayout.setNextFocusDownId(nextId);
         mMenu.setNextFocusDownId(nextId);
     }
 
     private int getUrlBarEntryTranslation() {
-        return getWidth() - mUrlBarEntry.getRight();
+        // We would ideally use the right-most point of the edit layout instead of the
+        // edit separator and its margin, but it is not inflated when this code initially runs.
+        final LayoutParams lp = (LayoutParams) editSeparator.getLayoutParams();
+        return editSeparator.getLeft() - lp.leftMargin - mUrlBarEntry.getRight();
     }
 
     private int getUrlBarCurveTranslation() {
         return getWidth() - mTabs.getLeft();
     }
 
     private boolean canDoBack(Tab tab) {
         return (tab.canDoBack() && !isEditing());
@@ -815,52 +833,64 @@ public class BrowserToolbar extends Them
         setUrlEditLayoutVisibility(false, null);
     }
 
     private void hideUrlEditLayout(PropertyAnimator animator) {
         setUrlEditLayoutVisibility(false, animator);
     }
 
     private void setUrlEditLayoutVisibility(final boolean showEditLayout, PropertyAnimator animator) {
+        mUrlEditLayout.prepareAnimation(showEditLayout, animator);
+
         final View viewToShow = (showEditLayout ? mUrlEditLayout : mUrlDisplayLayout);
         final View viewToHide = (showEditLayout ? mUrlDisplayLayout : mUrlEditLayout);
 
-        if (showEditLayout) {
-            mUrlEditLayout.prepareShowAnimation(animator);
-        }
-
         if (animator == null) {
             viewToHide.setVisibility(View.GONE);
             viewToShow.setVisibility(View.VISIBLE);
+
+            final int cancelVisibility = (showEditLayout ? View.VISIBLE : View.INVISIBLE);
+            setCancelVisibility(cancelVisibility);
             return;
         }
 
         ViewHelper.setAlpha(viewToShow, 0.0f);
         animator.attach(viewToShow,
                         PropertyAnimator.Property.ALPHA,
                         1.0f);
 
         animator.attach(viewToHide,
                         PropertyAnimator.Property.ALPHA,
                         0.0f);
 
         animator.addPropertyAnimationListener(new PropertyAnimationListener() {
             @Override
             public void onPropertyAnimationStart() {
                 viewToShow.setVisibility(View.VISIBLE);
+                if (!showEditLayout) {
+                    setCancelVisibility(View.INVISIBLE);
+                }
             }
 
             @Override
             public void onPropertyAnimationEnd() {
                 viewToHide.setVisibility(View.GONE);
                 ViewHelper.setAlpha(viewToHide, 1.0f);
+                if (showEditLayout) {
+                    setCancelVisibility(View.VISIBLE);
+                }
             }
         });
     }
 
+    private void setCancelVisibility(final int visibility) {
+        editSeparator.setVisibility(visibility);
+        editCancel.setVisibility(visibility);
+    }
+
     /**
      * Disables and dims all toolbar elements which are not
      * related to editing mode.
      */
     private void updateChildrenForEditing() {
         // This is for the tablet UI only
         if (!HardwareUtils.isTablet()) {
             return;
@@ -1265,16 +1295,17 @@ public class BrowserToolbar extends Them
     @Override
     public void setPrivateMode(boolean isPrivate) {
         super.setPrivateMode(isPrivate);
 
         mTabs.setPrivateMode(isPrivate);
         mMenu.setPrivateMode(isPrivate);
         mMenuIcon.setPrivateMode(isPrivate);
         mUrlEditLayout.setPrivateMode(isPrivate);
+        editSeparator.setPrivateMode(isPrivate);
 
         if (mBack instanceof BackButton) {
             ((BackButton) mBack).setPrivateMode(isPrivate);
         }
 
         if (mForward instanceof ForwardButton) {
             ((ForwardButton) mForward).setPrivateMode(isPrivate);
         }
--- a/mobile/android/base/toolbar/ToolbarEditLayout.java
+++ b/mobile/android/base/toolbar/ToolbarEditLayout.java
@@ -120,17 +120,25 @@ public class ToolbarEditLayout extends T
     }
 
     private void showSoftInput() {
         InputMethodManager imm =
                (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
         imm.showSoftInput(mEditText, InputMethodManager.SHOW_IMPLICIT);
     }
 
-    void prepareShowAnimation(PropertyAnimator animator) {
+    void prepareAnimation(final boolean showing, final PropertyAnimator animator) {
+        if (showing) {
+            prepareShowAnimation(animator);
+        } else {
+            prepareHideAnimation(animator);
+        }
+    }
+
+    private void prepareShowAnimation(final PropertyAnimator animator) {
         if (animator == null) {
             mEditText.requestFocus();
             showSoftInput();
             return;
         }
 
         animator.addPropertyAnimationListener(new PropertyAnimationListener() {
             @Override
@@ -142,16 +150,35 @@ public class ToolbarEditLayout extends T
             @Override
             public void onPropertyAnimationEnd() {
                 ViewHelper.setAlpha(mGo, 1.0f);
                 showSoftInput();
             }
         });
     }
 
+    private void prepareHideAnimation(final PropertyAnimator animator) {
+        if (animator == null) {
+            return;
+        }
+
+        animator.addPropertyAnimationListener(new PropertyAnimationListener() {
+            @Override
+            public void onPropertyAnimationStart() {
+                ViewHelper.setAlpha(mGo, 0.0f);
+            }
+
+            @Override
+            public void onPropertyAnimationEnd() {
+                // The enclosing view is invisible, so unhide the go button.
+                ViewHelper.setAlpha(mGo, 1.0f);
+            }
+        });
+    }
+
     void setOnCommitListener(OnCommitListener listener) {
         mCommitListener = listener;
         mEditText.setOnCommitListener(listener);
     }
 
     void setOnDismissListener(OnDismissListener listener) {
         mEditText.setOnDismissListener(listener);
     }
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/widget/ThemedView.java.in
@@ -0,0 +1,4 @@
+#filter substitution
+#define VIEW_NAME_SUFFIX View
+#define BASE_TYPE android.view.View
+#include ThemedView.java.frag