18262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/*
28262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Copyright (C) 2013 The Android Open Source Project
38262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
48262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Licensed under the Apache License, Version 2.0 (the "License");
58262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * you may not use this file except in compliance with the License.
68262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * You may obtain a copy of the License at
78262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
88262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *      http://www.apache.org/licenses/LICENSE-2.0
98262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Unless required by applicable law or agreed to in writing, software
118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * distributed under the License is distributed on an "AS IS" BASIS,
128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * See the License for the specific language governing permissions and
148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * limitations under the License.
158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */
168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu;
188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.AlertDialog;
208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.Dialog;
218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.DialogInterface;
228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.os.IBinder;
23da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R;
248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.KeyEvent;
258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.View;
268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.Window;
278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.view.WindowManager;
288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns/**
308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Helper for menus that appear as Dialogs (context and submenus).
318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns *
328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @hide
338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */
348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnspublic class MenuDialogHelper implements DialogInterface.OnKeyListener,
358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        DialogInterface.OnClickListener,
368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        DialogInterface.OnDismissListener,
378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        MenuPresenter.Callback {
388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private MenuBuilder mMenu;
398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private AlertDialog mDialog;
408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    ListMenuPresenter mPresenter;
418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    private MenuPresenter.Callback mPresenterCallback;
428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public MenuDialogHelper(MenuBuilder menu) {
448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mMenu = menu;
458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Shows menu as a dialog.
498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *
508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * @param windowToken Optional token to assign to the window.
518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void show(IBinder windowToken) {
538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Many references to mMenu, create local reference
548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        final MenuBuilder menu = mMenu;
558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Get the builder for the dialog
578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext());
588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
59176a17e30644b1d5a4206cc462268d151e43949bChris Banes        // Need to force Light Menu theme as list_menu_item_layout is usually against a dark bg and
60176a17e30644b1d5a4206cc462268d151e43949bChris Banes        // AlertDialog's bg is white
61ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes        mPresenter = new ListMenuPresenter(R.layout.abc_list_menu_item_layout,
62a2b9cdba583eed47107c1c97bd555c9a181860c2Chris Banes                R.style.Theme_AppCompat_CompactMenu_Dialog);
638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mPresenter.setCallback(this);
658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mMenu.addMenuPresenter(mPresenter);
668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        builder.setAdapter(mPresenter.getAdapter(), this);
678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Set the title
698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        final View headerView = menu.getHeaderView();
708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (headerView != null) {
718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            // Menu's client has given a custom header view, use it
728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            builder.setCustomTitle(headerView);
738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        } else {
748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            // Otherwise use the (text) title and icon
758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle());
768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Set the key listener
798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        builder.setOnKeyListener(this);
808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Show the menu
828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mDialog = builder.create();
838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mDialog.setOnDismissListener(this);
848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes();
868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (windowToken != null) {
888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            lp.token = windowToken;
898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
918262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mDialog.show();
938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) {
978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            if (event.getAction() == KeyEvent.ACTION_DOWN
988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    && event.getRepeatCount() == 0) {
998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Window win = mDialog.getWindow();
1008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (win != null) {
1018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    View decor = win.getDecorView();
1028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    if (decor != null) {
1038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        if (ds != null) {
1058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            ds.startTracking(event, this);
1068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            return true;
1078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        }
1088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    }
1098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
1108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) {
1118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                Window win = mDialog.getWindow();
1128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                if (win != null) {
1138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    View decor = win.getDecorView();
1148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    if (decor != null) {
1158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        if (ds != null && ds.isTracking(event)) {
1178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            mMenu.close(true);
1188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            dialog.dismiss();
1198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                            return true;
1208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                        }
1218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                    }
1228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns                }
1238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            }
1248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        // Menu shortcut matching
1278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        return mMenu.performShortcut(keyCode, event, 0);
1288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void setPresenterCallback(MenuPresenter.Callback cb) {
1328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mPresenterCallback = cb;
1338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    /**
1368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * Dismisses the menu's dialog.
1378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     *
1388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     * @see Dialog#dismiss()
1398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns     */
1408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void dismiss() {
1418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (mDialog != null) {
1428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            mDialog.dismiss();
1438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    @Override
1478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void onDismiss(DialogInterface dialog) {
1488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mPresenter.onCloseMenu(mMenu, true);
1498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    @Override
1528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
1538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (allMenusAreClosing || menu == mMenu) {
1548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            dismiss();
1558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (mPresenterCallback != null) {
1578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            mPresenterCallback.onCloseMenu(menu, allMenusAreClosing);
1588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    @Override
1628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public boolean onOpenSubMenu(MenuBuilder subMenu) {
1638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        if (mPresenterCallback != null) {
1648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns            return mPresenterCallback.onOpenSubMenu(subMenu);
1658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        }
1668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        return false;
1678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns
1698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    public void onClick(DialogInterface dialog, int which) {
1708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns        mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0);
1718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns    }
1728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns}
173