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 179598 6a49f6cb358226b712f712b32c0159eb374b4638
parent 179597 8998623049ceccadde6e9c621dc1b5e290fefe4a
child 179599 be018ccdcb8220a0fbc8be391cb67a20f0b6bc11
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersbnicholson
bugs965548
milestone31.0a1
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