19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.view.menu; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Dialog; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 258d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackbornimport android.view.Window; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 29021627eb5875372dea57ba91fa782fffbfbbc559Alan Viverette * Presents a menu as a modal dialog. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 31021627eb5875372dea57ba91fa782fffbfbbc559Alan Viverettepublic class MenuDialogHelper implements MenuHelper, DialogInterface.OnKeyListener, 32021627eb5875372dea57ba91fa782fffbfbbc559Alan Viverette DialogInterface.OnClickListener, DialogInterface.OnDismissListener, 33696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell MenuPresenter.Callback { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private MenuBuilder mMenu; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AlertDialog mDialog; 36696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell ListMenuPresenter mPresenter; 37d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell private MenuPresenter.Callback mPresenterCallback; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MenuDialogHelper(MenuBuilder menu) { 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mMenu = menu; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Shows menu as a dialog. 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param windowToken Optional token to assign to the window. 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void show(IBinder windowToken) { 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Many references to mMenu, create local reference 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final MenuBuilder menu = mMenu; 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the builder for the dialog 53696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext()); 54696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 55696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenter = new ListMenuPresenter(builder.getContext(), 56696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell com.android.internal.R.layout.list_menu_item_layout); 57696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 58696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenter.setCallback(this); 59696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mMenu.addMenuPresenter(mPresenter); 60696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell builder.setAdapter(mPresenter.getAdapter(), this); 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the title 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View headerView = menu.getHeaderView(); 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (headerView != null) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Menu's client has given a custom header view, use it 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.setCustomTitle(headerView); 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Otherwise use the (text) title and icon 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle()); 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set the key listener 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project builder.setOnKeyListener(this); 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Show the menu 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDialog = builder.create(); 77696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mDialog.setOnDismissListener(this); 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes(); 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (windowToken != null) { 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.token = windowToken; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDialog.show(); 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 908d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) { 918d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (event.getAction() == KeyEvent.ACTION_DOWN 928d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn && event.getRepeatCount() == 0) { 938d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn Window win = mDialog.getWindow(); 948d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (win != null) { 958d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn View decor = win.getDecorView(); 968d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (decor != null) { 978d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 988d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn if (ds != null) { 998d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn ds.startTracking(event, this); 1008d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn return true; 1018d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 1028d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 1038d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 1046024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) { 1056024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell Window win = mDialog.getWindow(); 1066024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell if (win != null) { 1076024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell View decor = win.getDecorView(); 1086024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell if (decor != null) { 1096024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 1106024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell if (ds != null && ds.isTracking(event)) { 11100aa5103e2f71ad3f29f53168e37ef7da8ca03f2Alan Viverette mMenu.close(true /* closeAllMenus */); 1126024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell dialog.dismiss(); 1136024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell return true; 1146024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell } 1156024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell } 1166024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell } 1178d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn } 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Menu shortcut matching 1219c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy return mMenu.performShortcut(keyCode, event, 0); 1229c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 125021627eb5875372dea57ba91fa782fffbfbbc559Alan Viverette @Override 126d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell public void setPresenterCallback(MenuPresenter.Callback cb) { 127d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell mPresenterCallback = cb; 128d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell } 129d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Dismisses the menu's dialog. 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see Dialog#dismiss() 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 135021627eb5875372dea57ba91fa782fffbfbbc559Alan Viverette @Override 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void dismiss() { 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDialog != null) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDialog.dismiss(); 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 141696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 142696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell @Override 143696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void onDismiss(DialogInterface dialog) { 144696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mPresenter.onCloseMenu(mMenu, true); 145696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 146696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 147696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell @Override 148696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 149696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell if (allMenusAreClosing || menu == mMenu) { 150696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell dismiss(); 151696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 152d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell if (mPresenterCallback != null) { 153d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 154d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell } 155696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 156696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 157696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell @Override 158696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell public boolean onOpenSubMenu(MenuBuilder subMenu) { 159d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell if (mPresenterCallback != null) { 160d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell return mPresenterCallback.onOpenSubMenu(subMenu); 161d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell } 162696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell return false; 163696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell } 164696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onClick(DialogInterface dialog, int which) { 166696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 169