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

Commit 00aa5103 authored by Alan Viverette's avatar Alan Viverette
Browse files

Reduce CascadingMenuPopup's reliance on internal ListView state

Bundles cascading menu information and stores it in a stack representing
the hierarchy of added menus.

Bug: 23970448
Change-Id: I1621d9eb30ff173767b6ebad2a1977127c42d0ad
parent 978db409
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -788,7 +788,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
            // Not a submenu, but treat it like one.
            // Not a submenu, but treat it like one.
            super.onSubMenuSelected(null);
            super.onSubMenuSelected(null);
        } else {
        } else {
            mMenu.close(false);
            mMenu.close(false /* closeAllMenus */);
        }
        }
    }
    }


@@ -981,7 +981,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
        @Override
        @Override
        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
            if (menu instanceof SubMenuBuilder) {
            if (menu instanceof SubMenuBuilder) {
                ((SubMenuBuilder) menu).getRootMenu().close(false);
                menu.getRootMenu().close(false /* closeAllMenus */);
            }
            }
            final Callback cb = getCallback();
            final Callback cb = getCallback();
            if (cb != null) {
            if (cb != null) {
+7 −20
Original line number Original line Diff line number Diff line
@@ -127,13 +127,15 @@ public class DropDownListView extends ListView {
    }
    }


    @Override
    @Override
    protected boolean shouldShowSelector() {
    boolean shouldShowSelector() {
        View selectedView = getSelectedView();
        return isHovered() || super.shouldShowSelector();
        return selectedView != null && selectedView.isEnabled() || super.shouldShowSelector();
    }
    }


    @Override
    @Override
    public boolean onHoverEvent(MotionEvent ev) {
    public boolean onHoverEvent(MotionEvent ev) {
        // Allow the super class to handle hover state management first.
        final boolean handled = super.onHoverEvent(ev);

        final int action = ev.getActionMasked();
        final int action = ev.getActionMasked();
        if (action == MotionEvent.ACTION_HOVER_ENTER
        if (action == MotionEvent.ACTION_HOVER_ENTER
                || action == MotionEvent.ACTION_HOVER_MOVE) {
                || action == MotionEvent.ACTION_HOVER_MOVE) {
@@ -154,26 +156,11 @@ public class DropDownListView extends ListView {
            // Do not cancel the selected position if the selection is visible by other reasons.
            // Do not cancel the selected position if the selection is visible by other reasons.
            if (!super.shouldShowSelector()) {
            if (!super.shouldShowSelector()) {
                setSelectedPositionInt(INVALID_POSITION);
                setSelectedPositionInt(INVALID_POSITION);
                setNextSelectedPositionInt(INVALID_POSITION);
            }
            }
        }
        }
        return super.onHoverEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int x = (int) event.getX();
        final int y = (int) event.getY();
        final int position = pointToPosition(x, y);
        if (position == INVALID_POSITION) {
            return super.onTouchEvent(event);
        }

        if (position != mSelectedPosition) {
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);
        }


        return super.onTouchEvent(event);
        return handled;
    }
    }


    /**
    /**
+21 −1
Original line number Original line Diff line number Diff line
@@ -2,6 +2,9 @@ package android.widget;


import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuBuilder;


import android.annotation.NonNull;
import android.view.MenuItem;

/**
/**
 * An interface notified when a menu item is hovered. Useful for cases when hover should trigger
 * An interface notified when a menu item is hovered. Useful for cases when hover should trigger
 * some behavior at a higher level, like managing the opening and closing of submenus.
 * some behavior at a higher level, like managing the opening and closing of submenus.
@@ -9,5 +12,22 @@ import com.android.internal.view.menu.MenuBuilder;
 * @hide
 * @hide
 */
 */
public interface MenuItemHoverListener {
public interface MenuItemHoverListener {
    public void onItemHovered(MenuBuilder menu, int position);
    /**
     * Called when hover exits a menu item.
     * <p>
     * If hover is moving to another item, this method will be called before
     * {@link #onItemHoverEnter(MenuBuilder, MenuItem)} for the newly-hovered item.
     *
     * @param menu the item's parent menu
     * @param item the hovered menu item
     */
    void onItemHoverExit(@NonNull MenuBuilder menu, @NonNull MenuItem item);

    /**
     * Called when hover enters a menu item.
     *
     * @param menu the item's parent menu
     * @param item the hovered menu item
     */
    void onItemHoverEnter(@NonNull MenuBuilder menu, @NonNull MenuItem item);
}
}
+52 −28
Original line number Original line Diff line number Diff line
@@ -16,12 +16,14 @@


package android.widget;
package android.widget;


import android.annotation.NonNull;
import android.content.Context;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources;
import android.transition.Transition;
import android.transition.Transition;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;


@@ -72,10 +74,18 @@ public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverLis
    }
    }


    @Override
    @Override
    public void onItemHovered(MenuBuilder menu, int position) {
    public void onItemHoverEnter(@NonNull MenuBuilder menu, @NonNull MenuItem item) {
        // Forward up the chain
        // Forward up the chain
        if (mHoverListener != null) {
        if (mHoverListener != null) {
            mHoverListener.onItemHovered(menu, position);
            mHoverListener.onItemHoverEnter(menu, item);
        }
    }

    @Override
    public void onItemHoverExit(@NonNull MenuBuilder menu, @NonNull MenuItem item) {
        // Forward up the chain
        if (mHoverListener != null) {
            mHoverListener.onItemHoverExit(menu, item);
        }
        }
    }
    }


@@ -87,6 +97,7 @@ public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverLis
        final int mRetreatKey;
        final int mRetreatKey;


        private MenuItemHoverListener mHoverListener;
        private MenuItemHoverListener mHoverListener;
        private MenuItem mHoveredMenuItem;


        public MenuDropDownListView(Context context, boolean hijackFocus) {
        public MenuDropDownListView(Context context, boolean hijackFocus) {
            super(context, hijackFocus);
            super(context, hijackFocus);
@@ -115,8 +126,7 @@ public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverLis
        public boolean onKeyDown(int keyCode, KeyEvent event) {
        public boolean onKeyDown(int keyCode, KeyEvent event) {
            ListMenuItemView selectedItem = (ListMenuItemView) getSelectedView();
            ListMenuItemView selectedItem = (ListMenuItemView) getSelectedView();
            if (selectedItem != null && keyCode == mAdvanceKey) {
            if (selectedItem != null && keyCode == mAdvanceKey) {
                if (selectedItem.isEnabled() &&
                if (selectedItem.isEnabled() && selectedItem.getItemData().hasSubMenu()) {
                        ((ListMenuItemView) selectedItem).getItemData().hasSubMenu()) {
                    performItemClick(
                    performItemClick(
                            selectedItem,
                            selectedItem,
                            getSelectedItemPosition(),
                            getSelectedItemPosition(),
@@ -127,7 +137,8 @@ public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverLis
                setSelectedPositionInt(INVALID_POSITION);
                setSelectedPositionInt(INVALID_POSITION);
                setNextSelectedPositionInt(INVALID_POSITION);
                setNextSelectedPositionInt(INVALID_POSITION);


                ((MenuAdapter) getAdapter()).getAdapterMenu().close();
                // Close only the top-level menu.
                ((MenuAdapter) getAdapter()).getAdapterMenu().close(false /* closeAllMenus */);
                return true;
                return true;
            }
            }
            return super.onKeyDown(keyCode, event);
            return super.onKeyDown(keyCode, event);
@@ -135,36 +146,49 @@ public class MenuPopupWindow extends ListPopupWindow implements MenuItemHoverLis


        @Override
        @Override
        public boolean onHoverEvent(MotionEvent ev) {
        public boolean onHoverEvent(MotionEvent ev) {
            boolean dispatchHover = false;
            // Dispatch any changes in hovered item index to the listener.
            final int position = pointToPosition((int) ev.getX(), (int) ev.getY());
            if (mHoverListener != null) {
                // The adapter may be wrapped. Adjust the index if necessary.
                final int headersCount;
                final MenuAdapter menuAdapter;
                final ListAdapter adapter = getAdapter();
                if (adapter instanceof HeaderViewListAdapter) {
                    final HeaderViewListAdapter headerAdapter = (HeaderViewListAdapter) adapter;
                    headersCount = headerAdapter.getHeadersCount();
                    menuAdapter = (MenuAdapter) headerAdapter.getWrappedAdapter();
                } else {
                    headersCount = 0;
                    menuAdapter = (MenuAdapter) adapter;
                }


            final int action = ev.getActionMasked();
                // Find the menu item for the view at the event coordinates.
            if (action == MotionEvent.ACTION_HOVER_ENTER
                MenuItem menuItem = null;
                    || action == MotionEvent.ACTION_HOVER_MOVE) {
                if (ev.getAction() != MotionEvent.ACTION_HOVER_EXIT) {
                if (position != INVALID_POSITION && position != mSelectedPosition) {
                    final int position = pointToPosition((int) ev.getX(), (int) ev.getY());
                    final View hoveredItem = getChildAt(position - getFirstVisiblePosition());
                    if (position != INVALID_POSITION) {
                    if (hoveredItem.isEnabled()) {
                        final int itemPosition = position - headersCount;
                        dispatchHover = true;
                        if (itemPosition >= 0 && itemPosition < menuAdapter.getCount()) {
                            menuItem = menuAdapter.getItem(itemPosition);
                        }
                        }
                    }
                    }
                }
                }


            boolean superVal = super.onHoverEvent(ev);
                final MenuItem oldMenuItem = mHoveredMenuItem;

                if (oldMenuItem != menuItem) {
            if (dispatchHover && mHoverListener != null) {
                    final MenuBuilder menu = menuAdapter.getAdapterMenu();
                ListAdapter adapter = getAdapter();
                    if (oldMenuItem != null) {
                MenuAdapter menuAdapter;
                        mHoverListener.onItemHoverExit(menu, oldMenuItem);
                if (adapter instanceof HeaderViewListAdapter) {
                    menuAdapter = (MenuAdapter) ((HeaderViewListAdapter) adapter)
                            .getWrappedAdapter();
                } else {
                    menuAdapter = (MenuAdapter) adapter;
                    }
                    }


                mHoverListener.onItemHovered(menuAdapter.getAdapterMenu(), position);
                    mHoveredMenuItem = menuItem;

                    if (menuItem != null) {
                        mHoverListener.onItemHoverEnter(menu, menuItem);
                    }
                }
            }
            }


            return superVal;
            return super.onHoverEvent(ev);
        }
        }
    }
    }
}
}
 No newline at end of file
+316 −198

File changed.

Preview size limit exceeded, changes collapsed.

Loading