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 1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.view.menu; 188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.app.Dialog; 208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.content.DialogInterface; 218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johnsimport android.os.IBinder; 22f57dafaf598bd6d328eef5d376c042a75ec878f5Chris Banesimport android.support.v7.app.AlertDialog; 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 */ 3266698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banesclass MenuDialogHelper implements DialogInterface.OnKeyListener, 338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns DialogInterface.OnClickListener, 348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns DialogInterface.OnDismissListener, 358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns MenuPresenter.Callback { 368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private MenuBuilder mMenu; 378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private AlertDialog mDialog; 388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns ListMenuPresenter mPresenter; 398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns private MenuPresenter.Callback mPresenterCallback; 408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public MenuDialogHelper(MenuBuilder menu) { 428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu = menu; 438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns /** 468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Shows menu as a dialog. 478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @param windowToken Optional token to assign to the window. 498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void show(IBinder windowToken) { 518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Many references to mMenu, create local reference 528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final MenuBuilder menu = mMenu; 538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Get the builder for the dialog 558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext()); 568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 57f57dafaf598bd6d328eef5d376c042a75ec878f5Chris Banes mPresenter = new ListMenuPresenter(builder.getContext(), 58f57dafaf598bd6d328eef5d376c042a75ec878f5Chris Banes R.layout.abc_list_menu_item_layout); 598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenter.setCallback(this); 618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.addMenuPresenter(mPresenter); 628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setAdapter(mPresenter.getAdapter(), this); 638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Set the title 658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns final View headerView = menu.getHeaderView(); 668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (headerView != null) { 678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Menu's client has given a custom header view, use it 688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setCustomTitle(headerView); 698262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } else { 708262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Otherwise use the (text) title and icon 718262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle()); 728262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 738262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 748262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Set the key listener 758262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns builder.setOnKeyListener(this); 768262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 778262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Show the menu 788262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog = builder.create(); 798262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.setOnDismissListener(this); 808262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 818262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes(); 828262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 838262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (windowToken != null) { 848262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.token = windowToken; 858262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 868262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 878262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 888262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.show(); 898262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 908262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 918262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 928262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) { 938262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (event.getAction() == KeyEvent.ACTION_DOWN 948262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns && event.getRepeatCount() == 0) { 958262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns Window win = mDialog.getWindow(); 968262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (win != null) { 978262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns View decor = win.getDecorView(); 988262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (decor != null) { 998262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 1008262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (ds != null) { 1018262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns ds.startTracking(event, this); 1028262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return true; 1038262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1048262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1058262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1068262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) { 1078262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns Window win = mDialog.getWindow(); 1088262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (win != null) { 1098262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns View decor = win.getDecorView(); 1108262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (decor != null) { 1118262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 1128262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (ds != null && ds.isTracking(event)) { 1138262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.close(true); 1148262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns dialog.dismiss(); 1158262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return true; 1168262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1178262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1188262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1198262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1208262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1218262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1228262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns // Menu shortcut matching 1238262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return mMenu.performShortcut(keyCode, event, 0); 1248262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1258262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1268262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1278262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void setPresenterCallback(MenuPresenter.Callback cb) { 1288262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenterCallback = cb; 1298262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1308262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1318262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns /** 1328262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * Dismisses the menu's dialog. 1338262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * 1348262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns * @see Dialog#dismiss() 1358262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns */ 1368262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void dismiss() { 1378262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mDialog != null) { 1388262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mDialog.dismiss(); 1398262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1408262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1418262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1428262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1438262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onDismiss(DialogInterface dialog) { 1448262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenter.onCloseMenu(mMenu, true); 1458262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1468262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1478262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1488262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 1498262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (allMenusAreClosing || menu == mMenu) { 1508262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns dismiss(); 1518262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1528262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mPresenterCallback != null) { 1538262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 1548262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1558262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1568262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1578262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns @Override 1588262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public boolean onOpenSubMenu(MenuBuilder subMenu) { 1598262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns if (mPresenterCallback != null) { 1608262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return mPresenterCallback.onOpenSubMenu(subMenu); 1618262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1628262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns return false; 1638262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1648262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns 1658262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns public void onClick(DialogInterface dialog, int which) { 1668262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0); 1678262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns } 1688262949c1a6b7e191020b31fc914972bb0b58ab0Trevor Johns} 169