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/**
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helper for menus that appear as Dialogs (context and submenus).
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
33696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powellpublic class MenuDialogHelper implements DialogInterface.OnKeyListener,
34696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        DialogInterface.OnClickListener,
35696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        DialogInterface.OnDismissListener,
36696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        MenuPresenter.Callback {
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private MenuBuilder mMenu;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private AlertDialog mDialog;
39696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    ListMenuPresenter mPresenter;
40d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell    private MenuPresenter.Callback mPresenterCallback;
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuDialogHelper(MenuBuilder menu) {
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMenu = menu;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shows menu as a dialog.
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param windowToken Optional token to assign to the window.
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show(IBinder windowToken) {
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Many references to mMenu, create local reference
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuBuilder menu = mMenu;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the builder for the dialog
56696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext());
57696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
58696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter = new ListMenuPresenter(builder.getContext(),
59696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                com.android.internal.R.layout.list_menu_item_layout);
60696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
61696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.setCallback(this);
62696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mMenu.addMenuPresenter(mPresenter);
63696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        builder.setAdapter(mPresenter.getAdapter(), this);
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the title
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View headerView = menu.getHeaderView();
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (headerView != null) {
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Menu's client has given a custom header view, use it
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            builder.setCustomTitle(headerView);
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Otherwise use the (text) title and icon
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle());
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the key listener
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.setOnKeyListener(this);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Show the menu
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDialog = builder.create();
80696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mDialog.setOnDismissListener(this);
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes();
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (windowToken != null) {
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            lp.token = windowToken;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDialog.show();
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
938d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn        if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) {
948d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn            if (event.getAction() == KeyEvent.ACTION_DOWN
958d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    && event.getRepeatCount() == 0) {
968d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                Window win = mDialog.getWindow();
978d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                if (win != null) {
988d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    View decor = win.getDecorView();
998d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    if (decor != null) {
1008d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1018d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        if (ds != null) {
1028d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                            ds.startTracking(event, this);
1038d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                            return true;
1048d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        }
1058d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    }
1068d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                }
1076024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell            } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) {
1086024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                Window win = mDialog.getWindow();
1096024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                if (win != null) {
1106024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    View decor = win.getDecorView();
1116024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    if (decor != null) {
1126024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1136024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        if (ds != null && ds.isTracking(event)) {
1146024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            mMenu.close(true);
1156024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            dialog.dismiss();
1166024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            return true;
1176024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        }
1186024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    }
1196024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                }
1208d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn            }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Menu shortcut matching
1249c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy        return mMenu.performShortcut(keyCode, event, 0);
1259c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
128d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell    public void setPresenterCallback(MenuPresenter.Callback cb) {
129d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell        mPresenterCallback = cb;
130d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell    }
131d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Dismisses the menu's dialog.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see Dialog#dismiss()
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dismiss() {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDialog != null) {
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDialog.dismiss();
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
142696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
143696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
144696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onDismiss(DialogInterface dialog) {
145696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.onCloseMenu(mMenu, true);
146696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
147696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
148696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
149696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
150696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (allMenusAreClosing || menu == mMenu) {
151696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            dismiss();
152696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
153d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell        if (mPresenterCallback != null) {
154d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell            mPresenterCallback.onCloseMenu(menu, allMenusAreClosing);
155d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell        }
156696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
157696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
158696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
159696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean onOpenSubMenu(MenuBuilder subMenu) {
160d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell        if (mPresenterCallback != null) {
161d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell            return mPresenterCallback.onOpenSubMenu(subMenu);
162d1f4207ba577e2ac3f39a719f8ee4bb9f4940dc1Adam Powell        }
163696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
164696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
165696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onClick(DialogInterface dialog, int which) {
167696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
170