FloatingToolbar: Support for menu groups.

1. Menu groups are now separated by dividers
2. Update to menu item spacing as specified in new UX mocks
3. TextView-Editor now passes the "assist" menu as a group
4. "Share" menu reordered after "Cut/Copy/Paste" as per UX mocks update.

Test: Manual tests.
Bug: 34777048
Bug: 34777833
Change-Id: I3d435d8a38e5b146a54706f12dbf3ff629c504bf
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 8cb2d23..45b5570 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -149,10 +149,10 @@
     private static final int MENU_ITEM_ORDER_ASSIST = 1;
     private static final int MENU_ITEM_ORDER_UNDO = 2;
     private static final int MENU_ITEM_ORDER_REDO = 3;
-    private static final int MENU_ITEM_ORDER_SHARE = 4;
-    private static final int MENU_ITEM_ORDER_CUT = 5;
-    private static final int MENU_ITEM_ORDER_COPY = 6;
-    private static final int MENU_ITEM_ORDER_PASTE = 7;
+    private static final int MENU_ITEM_ORDER_CUT = 4;
+    private static final int MENU_ITEM_ORDER_COPY = 5;
+    private static final int MENU_ITEM_ORDER_PASTE = 6;
+    private static final int MENU_ITEM_ORDER_SHARE = 7;
     private static final int MENU_ITEM_ORDER_PASTE_AS_PLAIN_TEXT = 8;
     private static final int MENU_ITEM_ORDER_SELECT_ALL = 9;
     private static final int MENU_ITEM_ORDER_REPLACE = 10;
@@ -3876,7 +3876,7 @@
                 final Intent intent = textClassificationResult.getIntent();
                 if ((icon != null || !TextUtils.isEmpty(label))
                         && (onClickListener != null || intent != null)) {
-                    menu.add(Menu.NONE, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
+                    menu.add(TextView.ID_ASSIST, TextView.ID_ASSIST, MENU_ITEM_ORDER_ASSIST, label)
                             .setIcon(icon)
                             .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
                 }
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 58e694a..854d013 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -32,6 +32,7 @@
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.Size;
+import android.util.TypedValue;
 import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -1113,6 +1114,7 @@
             mMainPanel.removeAllViews();
             mMainPanel.setPaddingRelative(0, 0, 0, 0);
 
+            int lastGroupId = -1;
             boolean isFirstItem = true;
             while (!remainingMenuItems.isEmpty()) {
                 final MenuItem menuItem = remainingMenuItems.peek();
@@ -1125,11 +1127,11 @@
                             menuItemButton.getPaddingTop(),
                             menuItemButton.getPaddingEnd(),
                             menuItemButton.getPaddingBottom());
-                    isFirstItem = false;
                 }
 
                 // Adding additional end padding for the last button to even out button spacing.
-                if (remainingMenuItems.size() == 1) {
+                boolean isLastItem = remainingMenuItems.size() == 1;
+                if (isLastItem) {
                     menuItemButton.setPaddingRelative(
                             menuItemButton.getPaddingStart(),
                             menuItemButton.getPaddingTop(),
@@ -1138,25 +1140,64 @@
                 }
 
                 menuItemButton.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
-                int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+                final int menuItemButtonWidth = Math.min(menuItemButton.getMeasuredWidth(), toolbarWidth);
+
+                final boolean isNewGroup = !isFirstItem && lastGroupId != menuItem.getGroupId();
+                final int extraPadding = isNewGroup ? menuItemButton.getPaddingEnd() * 2 : 0;
+
                 // Check if we can fit an item while reserving space for the overflowButton.
                 boolean canFitWithOverflow =
-                        menuItemButtonWidth <= availableWidth - mOverflowButtonSize.getWidth();
+                        menuItemButtonWidth <=
+                                availableWidth - mOverflowButtonSize.getWidth() - extraPadding;
                 boolean canFitNoOverflow =
-                        remainingMenuItems.size() == 1 && menuItemButtonWidth <= availableWidth;
+                        isLastItem && menuItemButtonWidth <= availableWidth - extraPadding;
                 if (canFitWithOverflow || canFitNoOverflow) {
+                    if (isNewGroup) {
+                        final View border = createBorder(mContext);
+                        final int borderWidth = border.getLayoutParams().width;
+
+                        // Add extra padding to the end of the previous button.
+                        // Half of the extra padding (less borderWidth) goes to the previous button.
+                        View previousButton = mMainPanel.getChildAt(mMainPanel.getChildCount() - 1);
+                        final int prevPaddingEnd = previousButton.getPaddingEnd()
+                                + extraPadding / 2 - borderWidth;
+                        previousButton.setPaddingRelative(
+                                previousButton.getPaddingStart(),
+                                previousButton.getPaddingTop(),
+                                prevPaddingEnd,
+                                previousButton.getPaddingBottom());
+                        final ViewGroup.LayoutParams prevParams = previousButton.getLayoutParams();
+                        prevParams.width += extraPadding / 2 - borderWidth;
+                        previousButton.setLayoutParams(prevParams);
+
+                        // Add extra padding to the start of this button.
+                        // Other half of the extra padding goes to this button.
+                        final int paddingStart = menuItemButton.getPaddingStart()
+                                + extraPadding / 2;
+                        menuItemButton.setPaddingRelative(
+                                paddingStart,
+                                menuItemButton.getPaddingTop(),
+                                menuItemButton.getPaddingEnd(),
+                                menuItemButton.getPaddingBottom());
+
+                        // Include a border.
+                        mMainPanel.addView(border);
+                    }
+
                     setButtonTagAndClickListener(menuItemButton, menuItem);
                     mMainPanel.addView(menuItemButton);
-                    ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
-                    params.width = menuItemButtonWidth;
+                    final ViewGroup.LayoutParams params = menuItemButton.getLayoutParams();
+                    params.width = menuItemButtonWidth + extraPadding / 2;
                     menuItemButton.setLayoutParams(params);
-                    availableWidth -= menuItemButtonWidth;
+                    availableWidth -= menuItemButtonWidth + extraPadding;
                     remainingMenuItems.pop();
                 } else {
                     // Reserve space for overflowButton.
                     mMainPanel.setPaddingRelative(0, 0, mOverflowButtonSize.getWidth(), 0);
                     break;
                 }
+                lastGroupId = menuItem.getGroupId();
+                isFirstItem = false;
             }
             mMainPanelSize = measure(mMainPanel);
             return remainingMenuItems;
@@ -1688,6 +1729,23 @@
         return popupWindow;
     }
 
+    private static View createBorder(Context context) {
+        // TODO: Inflate this instead.
+        View border = new View(context);
+        int _1dp = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, 1, context.getResources().getDisplayMetrics());
+        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+                _1dp, ViewGroup.LayoutParams.MATCH_PARENT);
+        params.setMarginsRelative(0, _1dp * 10, 0, _1dp * 10);
+        border.setLayoutParams(params);
+        border.setBackgroundColor(Color.parseColor("#9E9E9E"));
+        border.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        border.setEnabled(false);
+        border.setFocusable(false);
+        border.setContentDescription(null);
+        return border;
+    }
+
     /**
      * Creates an "appear" animation for the specified view.
      *
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9824051..b24bd54 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -461,12 +461,12 @@
     <dimen name="floating_toolbar_height">48dp</dimen>
     <dimen name="floating_toolbar_menu_image_button_width">56dp</dimen>
     <dimen name="floating_toolbar_menu_image_button_vertical_padding">12dp</dimen>
-    <dimen name="floating_toolbar_menu_button_side_padding">16dp</dimen>
+    <dimen name="floating_toolbar_menu_button_side_padding">11dp</dimen>
     <dimen name="floating_toolbar_overflow_image_button_width">60dp</dimen>
     <dimen name="floating_toolbar_overflow_side_padding">18dp</dimen>
     <dimen name="floating_toolbar_text_size">14sp</dimen>
     <dimen name="floating_toolbar_menu_button_minimum_width">48dp</dimen>
-    <dimen name="floating_toolbar_preferred_width">328dp</dimen>
+    <dimen name="floating_toolbar_preferred_width">400dp</dimen>
     <dimen name="floating_toolbar_minimum_overflow_height">96dp</dimen>
     <dimen name="floating_toolbar_maximum_overflow_height">192dp</dimen>
     <dimen name="floating_toolbar_horizontal_margin">16dp</dimen>