1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.view.menu; 18 19import android.app.AlertDialog; 20import android.app.Dialog; 21import android.content.DialogInterface; 22import android.os.IBinder; 23import android.view.KeyEvent; 24import android.view.View; 25import android.view.Window; 26import android.view.WindowManager; 27 28/** 29 * Helper for menus that appear as Dialogs (context and submenus). 30 * 31 * @hide 32 */ 33public class MenuDialogHelper implements DialogInterface.OnKeyListener, 34 DialogInterface.OnClickListener, 35 DialogInterface.OnDismissListener, 36 MenuPresenter.Callback { 37 private MenuBuilder mMenu; 38 private AlertDialog mDialog; 39 ListMenuPresenter mPresenter; 40 private MenuPresenter.Callback mPresenterCallback; 41 42 public MenuDialogHelper(MenuBuilder menu) { 43 mMenu = menu; 44 } 45 46 /** 47 * Shows menu as a dialog. 48 * 49 * @param windowToken Optional token to assign to the window. 50 */ 51 public void show(IBinder windowToken) { 52 // Many references to mMenu, create local reference 53 final MenuBuilder menu = mMenu; 54 55 // Get the builder for the dialog 56 final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext()); 57 58 mPresenter = new ListMenuPresenter(builder.getContext(), 59 com.android.internal.R.layout.list_menu_item_layout); 60 61 mPresenter.setCallback(this); 62 mMenu.addMenuPresenter(mPresenter); 63 builder.setAdapter(mPresenter.getAdapter(), this); 64 65 // Set the title 66 final View headerView = menu.getHeaderView(); 67 if (headerView != null) { 68 // Menu's client has given a custom header view, use it 69 builder.setCustomTitle(headerView); 70 } else { 71 // Otherwise use the (text) title and icon 72 builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle()); 73 } 74 75 // Set the key listener 76 builder.setOnKeyListener(this); 77 78 // Show the menu 79 mDialog = builder.create(); 80 mDialog.setOnDismissListener(this); 81 82 WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes(); 83 lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 84 if (windowToken != null) { 85 lp.token = windowToken; 86 } 87 lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; 88 89 mDialog.show(); 90 } 91 92 public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) { 93 if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) { 94 if (event.getAction() == KeyEvent.ACTION_DOWN 95 && event.getRepeatCount() == 0) { 96 Window win = mDialog.getWindow(); 97 if (win != null) { 98 View decor = win.getDecorView(); 99 if (decor != null) { 100 KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 101 if (ds != null) { 102 ds.startTracking(event, this); 103 return true; 104 } 105 } 106 } 107 } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) { 108 Window win = mDialog.getWindow(); 109 if (win != null) { 110 View decor = win.getDecorView(); 111 if (decor != null) { 112 KeyEvent.DispatcherState ds = decor.getKeyDispatcherState(); 113 if (ds != null && ds.isTracking(event)) { 114 mMenu.close(true); 115 dialog.dismiss(); 116 return true; 117 } 118 } 119 } 120 } 121 } 122 123 // Menu shortcut matching 124 return mMenu.performShortcut(keyCode, event, 0); 125 126 } 127 128 public void setPresenterCallback(MenuPresenter.Callback cb) { 129 mPresenterCallback = cb; 130 } 131 132 /** 133 * Dismisses the menu's dialog. 134 * 135 * @see Dialog#dismiss() 136 */ 137 public void dismiss() { 138 if (mDialog != null) { 139 mDialog.dismiss(); 140 } 141 } 142 143 @Override 144 public void onDismiss(DialogInterface dialog) { 145 mPresenter.onCloseMenu(mMenu, true); 146 } 147 148 @Override 149 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 150 if (allMenusAreClosing || menu == mMenu) { 151 dismiss(); 152 } 153 if (mPresenterCallback != null) { 154 mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 155 } 156 } 157 158 @Override 159 public boolean onOpenSubMenu(MenuBuilder subMenu) { 160 if (mPresenterCallback != null) { 161 return mPresenterCallback.onOpenSubMenu(subMenu); 162 } 163 return false; 164 } 165 166 public void onClick(DialogInterface dialog, int which) { 167 mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0); 168 } 169} 170