Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d149bc9 authored by Abodunrinwa Toki's avatar Abodunrinwa Toki Committed by Android (Google) Code Review
Browse files

Merge "FloatingToolbar: Rules for ordering menu items." into oc-dev

parents 2d9a1451 6eecdc93
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -146,7 +146,7 @@ public class Editor {
    private static final String UNDO_OWNER_TAG = "Editor";

    // Ordering constants used to place the Action Mode or context menu items in their menu.
    private static final int MENU_ITEM_ORDER_ASSIST = 1;
    private static final int MENU_ITEM_ORDER_ASSIST = 0;
    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_CUT = 4;
@@ -156,8 +156,8 @@ public class Editor {
    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;
    private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 11;
    private static final int MENU_ITEM_ORDER_AUTOFILL = 12;
    private static final int MENU_ITEM_ORDER_AUTOFILL = 11;
    private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 100;

    // Each Editor manages its own undo stack.
    private final UndoManager mUndoManager = new UndoManager();
@@ -6322,9 +6322,10 @@ public class Editor {
         * Adds "PROCESS_TEXT" menu items to the specified menu.
         */
        public void onInitializeMenu(Menu menu) {
            int i = 0;
            final int size = mSupportedActivities.size();
            loadSupportedActivities();
            for (ResolveInfo resolveInfo : mSupportedActivities) {
            for (int i = 0; i < size; i++) {
                final ResolveInfo resolveInfo = mSupportedActivities.get(i);
                menu.add(Menu.NONE, Menu.NONE,
                        Editor.MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i++,
                        getLabel(resolveInfo))
+31 −0
Original line number Diff line number Diff line
@@ -233,6 +233,7 @@ public final class FloatingToolbar {

    private void doShow() {
        List<MenuItem> menuItems = getVisibleAndEnabledMenuItems(mMenu);
        tidy(menuItems);
        if (!isCurrentlyShowing(menuItems) || mWidthChanged) {
            mPopup.dismiss();
            mPopup.layoutMenuItems(menuItems, mMenuItemClickListener, mSuggestedWidth);
@@ -274,6 +275,36 @@ public final class FloatingToolbar {
        return menuItems;
    }

    /**
     * Update the list of menu items to conform to certain requirements.
     */
    private void tidy(List<MenuItem> menuItems) {
        int assistItemIndex = -1;
        Drawable assistItemDrawable = null;

        final int size = menuItems.size();
        for (int i = 0; i < size; i++) {
            final MenuItem menuItem = menuItems.get(i);

            if (menuItem.getItemId() == android.R.id.textAssist) {
                assistItemIndex = i;
                assistItemDrawable = menuItem.getIcon();
            }

            // Remove icons for all menu items with text.
            if (!TextUtils.isEmpty(menuItem.getTitle())) {
                menuItem.setIcon(null);
            }
        }
        if (assistItemIndex > -1) {
            final MenuItem assistMenuItem = menuItems.remove(assistItemIndex);
            // Ensure the assist menu item preserves its icon.
            assistMenuItem.setIcon(assistItemDrawable);
            // Ensure the assist menu item is always the first item.
            menuItems.add(0, assistMenuItem);
        }
    }

    private List<Object> getShowingMenuItemsReferences(List<MenuItem> menuItems) {
        List<Object> references = new ArrayList<Object>();
        for (MenuItem menuItem : menuItems) {
+42 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
import static android.widget.espresso.TextViewAssertions.hasInsertionPointerAtIndex;
import static android.widget.espresso.TextViewAssertions.hasSelection;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarItemIndex;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsDisplayed;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarIsNotDisplayed;
import static android.widget.espresso.FloatingToolbarEspressoUtils.assertFloatingToolbarContainsItem;
@@ -46,6 +47,11 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.is;

import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
import android.widget.espresso.CustomViewActions.RelativeCoordinatesProvider;

import android.support.test.espresso.action.EspressoKey;
@@ -71,7 +77,8 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
    @Override
    public void setUp() throws Exception {
        super.setUp();
        getActivity();
        getActivity().getSystemService(TextClassificationManager.class)
                .setTextClassifier(TextClassifier.NO_OP);
    }

    public void testTypedTextIsOnScreen() throws Exception {
@@ -676,4 +683,38 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
        // hasTransientState should return false when selection is created by API.
        assertFalse(textView.hasTransientState());
    }

    public void testAssistItemIsAtIndexZero() throws Exception {
        getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
        textView.post(() -> textView.setCustomSelectionActionModeCallback(
                new ActionMode.Callback() {
                    @Override
                    public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
                        // Create another item at order position 0 to confirm that it will never be
                        // placed before the textAssist item.
                        menu.add(Menu.NONE, 0 /* id */, 0 /* order */, "Test");
                        return true;
                    }

                    @Override
                    public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
                        return true;
                    }

                    @Override
                    public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
                        return false;
                    }

                    @Override
                    public void onDestroyActionMode(ActionMode actionMode) {}
                }));
        final String text = "droid@android.com";

        onView(withId(R.id.textview)).perform(replaceText(text));
        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('@')));
        sleepForFloatingToolbarPopup();
        assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
    }
}
+39 −0
Original line number Diff line number Diff line
@@ -29,7 +29,13 @@ import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;

import android.view.MenuItem;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import android.support.test.espresso.NoMatchingRootException;
import android.support.test.espresso.NoMatchingViewException;
@@ -122,6 +128,39 @@ public class FloatingToolbarEspressoUtils {
        }
    }

    /**
     * Asserts that the floating toolbar contains a specified item at a specified index.
     *
     * @param menuItemId id of the menu item
     * @param index expected index of the menu item in the floating toolbar
     * @throws AssertionError if the assertion fails
     */
    public static void assertFloatingToolbarItemIndex(final int menuItemId, final int index) {
        onFloatingToolBar().check(matches(new TypeSafeMatcher<View>() {
            private List<Integer> menuItemIds = new ArrayList<>();

            @Override
            public boolean matchesSafely(View view) {
                collectMenuItemIds(view);
                return menuItemIds.size() > index && menuItemIds.get(index) == menuItemId;
            }

            @Override
            public void describeTo(Description description) {}

            private void collectMenuItemIds(View view) {
                if (view.getTag() instanceof MenuItem) {
                    menuItemIds.add(((MenuItem) view.getTag()).getItemId());
                } else if (view instanceof ViewGroup) {
                    ViewGroup viewGroup = (ViewGroup) view;
                    for (int i = 0; i < viewGroup.getChildCount(); i++) {
                        collectMenuItemIds(viewGroup.getChildAt(i));
                    }
                }
            }
        }));
    }

    /**
     * Asserts that the floating toolbar doesn't contain the specified item.
     *