MenuDialogHelper.java revision 696cba573e651b0e4f18a4718627c8ccecb3bda0
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;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MenuDialogHelper(MenuBuilder menu) {
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mMenu = menu;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Shows menu as a dialog.
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param windowToken Optional token to assign to the window.
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void show(IBinder windowToken) {
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Many references to mMenu, create local reference
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final MenuBuilder menu = mMenu;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Get the builder for the dialog
55696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final AlertDialog.Builder builder = new AlertDialog.Builder(menu.getContext());
56696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
57696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter = new ListMenuPresenter(builder.getContext(),
58696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell                com.android.internal.R.layout.list_menu_item_layout);
59696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
60696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.setCallback(this);
61696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mMenu.addMenuPresenter(mPresenter);
62696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        builder.setAdapter(mPresenter.getAdapter(), this);
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the title
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View headerView = menu.getHeaderView();
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (headerView != null) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Menu's client has given a custom header view, use it
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            builder.setCustomTitle(headerView);
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Otherwise use the (text) title and icon
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            builder.setIcon(menu.getHeaderIcon()).setTitle(menu.getHeaderTitle());
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Set the key listener
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        builder.setOnKeyListener(this);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Show the menu
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDialog = builder.create();
79696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mDialog.setOnDismissListener(this);
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        WindowManager.LayoutParams lp = mDialog.getWindow().getAttributes();
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (windowToken != null) {
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            lp.token = windowToken;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDialog.show();
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
928d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn        if (keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BACK) {
938d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn            if (event.getAction() == KeyEvent.ACTION_DOWN
948d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    && event.getRepeatCount() == 0) {
958d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                Window win = mDialog.getWindow();
968d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                if (win != null) {
978d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    View decor = win.getDecorView();
988d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    if (decor != null) {
998d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1008d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        if (ds != null) {
1018d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                            ds.startTracking(event, this);
1028d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                            return true;
1038d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                        }
1048d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                    }
1058d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn                }
1066024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell            } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled()) {
1076024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                Window win = mDialog.getWindow();
1086024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                if (win != null) {
1096024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    View decor = win.getDecorView();
1106024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    if (decor != null) {
1116024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        KeyEvent.DispatcherState ds = decor.getKeyDispatcherState();
1126024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        if (ds != null && ds.isTracking(event)) {
1136024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            mMenu.close(true);
1146024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            dialog.dismiss();
1156024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                            return true;
1166024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                        }
1176024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                    }
1186024ca5c90203b6c33acc6adfbf7e4e613549a0aAdam Powell                }
1198d37426c754e9822feaa8c6cc0b7c13e8523e217Dianne Hackborn            }
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Menu shortcut matching
1239c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy        return mMenu.performShortcut(keyCode, event, 0);
1249c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Dismisses the menu's dialog.
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see Dialog#dismiss()
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void dismiss() {
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDialog != null) {
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDialog.dismiss();
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
137696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
138696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
139696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onDismiss(DialogInterface dialog) {
140696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.onCloseMenu(mMenu, true);
141696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
142696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
143696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
144696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
145696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (allMenusAreClosing || menu == mMenu) {
146696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            dismiss();
147696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        }
148696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
149696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
150696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
151696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public boolean onOpenSubMenu(MenuBuilder subMenu) {
152696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        return false;
153696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
154696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onClick(DialogInterface dialog, int which) {
156696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mMenu.performItemAction((MenuItemImpl) mPresenter.getAdapter().getItem(which), 0);
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
159