blob: cda2c5f3b7c5dc98f7744a6a0a4ac29b9e3f80d0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 android.app;
18
Adam Powell04fe6eb2013-05-31 14:39:48 -070019import android.content.pm.ApplicationInfo;
20import android.content.pm.PackageManager;
Adam Powelldec9dfd2010-08-09 15:27:54 -070021import com.android.internal.app.ActionBarImpl;
svetoslavganov75986cf2009-05-14 22:28:01 -070022import com.android.internal.policy.PolicyManager;
23
Karl Rosaen53d24af2009-07-14 14:58:10 -070024import android.content.ComponentName;
Adam Powell6e346362010-07-23 10:18:23 -070025import android.content.Context;
Karl Rosaen7bafed82009-09-04 11:15:21 -070026import android.content.ContextWrapper;
Adam Powell6e346362010-07-23 10:18:23 -070027import android.content.DialogInterface;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.graphics.drawable.Drawable;
29import android.net.Uri;
svetoslavganov75986cf2009-05-14 22:28:01 -070030import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Handler;
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -080032import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.os.Message;
Adam Powell89fc3ac2011-11-01 18:00:44 -070034import android.util.Log;
Adam Powell2fbf4de62010-09-30 15:46:46 -070035import android.util.TypedValue;
Adam Powelldec9dfd2010-08-09 15:27:54 -070036import android.view.ActionMode;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.view.ContextMenu;
Adam Powell6e346362010-07-23 10:18:23 -070038import android.view.ContextMenu.ContextMenuInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.view.ContextThemeWrapper;
40import android.view.Gravity;
41import android.view.KeyEvent;
svetoslavganov75986cf2009-05-14 22:28:01 -070042import android.view.LayoutInflater;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.view.Menu;
44import android.view.MenuItem;
45import android.view.MotionEvent;
46import android.view.View;
Adam Powell6e346362010-07-23 10:18:23 -070047import android.view.View.OnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.ViewGroup;
Adam Powell6e346362010-07-23 10:18:23 -070049import android.view.ViewGroup.LayoutParams;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.view.Window;
51import android.view.WindowManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070052import android.view.accessibility.AccessibilityEvent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053
54import java.lang.ref.WeakReference;
55
56/**
57 * Base class for Dialogs.
58 *
59 * <p>Note: Activities provide a facility to manage the creation, saving and
60 * restoring of dialogs. See {@link Activity#onCreateDialog(int)},
61 * {@link Activity#onPrepareDialog(int, Dialog)},
62 * {@link Activity#showDialog(int)}, and {@link Activity#dismissDialog(int)}. If
63 * these methods are used, {@link #getOwnerActivity()} will return the Activity
64 * that managed this dialog.
65 *
66 * <p>Often you will want to have a Dialog display on top of the current
67 * input method, because there is no reason for it to accept text. You can
68 * do this by setting the {@link WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM
69 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM} window flag (assuming
70 * your Dialog takes input focus, as it the default) with the following code:
71 *
72 * <pre>
Joe Fernandez558459f2011-10-13 16:47:36 -070073 * getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
74 * WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);</pre>
75 *
76 * <div class="special reference">
77 * <h3>Developer Guides</h3>
78 * <p>For more information about creating dialogs, read the
79 * <a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a> developer guide.</p>
80 * </div>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 */
82public class Dialog implements DialogInterface, Window.Callback,
83 KeyEvent.Callback, OnCreateContextMenuListener {
Adam Powell89fc3ac2011-11-01 18:00:44 -070084 private static final String TAG = "Dialog";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 private Activity mOwnerActivity;
86
87 final Context mContext;
88 final WindowManager mWindowManager;
89 Window mWindow;
90 View mDecor;
Adam Powelldec9dfd2010-08-09 15:27:54 -070091 private ActionBarImpl mActionBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 /**
93 * This field should be made private, so it is hidden from the SDK.
94 * {@hide}
95 */
96 protected boolean mCancelable = true;
svetoslavganov75986cf2009-05-14 22:28:01 -070097
Dianne Hackbornf812fee2011-01-25 14:54:29 -080098 private String mCancelAndDismissTaken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private Message mCancelMessage;
100 private Message mDismissMessage;
Romain Guy045163a2009-07-14 13:59:33 -0700101 private Message mShowMessage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 private OnKeyListener mOnKeyListener;
104
105 private boolean mCreated = false;
106 private boolean mShowing = false;
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800107 private boolean mCanceled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109 private final Handler mHandler = new Handler();
110
Romain Guy7883c972010-03-01 16:39:17 -0800111 private static final int DISMISS = 0x43;
112 private static final int CANCEL = 0x44;
113 private static final int SHOW = 0x45;
114
115 private Handler mListenersHandler;
116
Adam Powellcfe9aee2011-11-01 14:56:27 -0700117 private ActionMode mActionMode;
118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 private final Runnable mDismissAction = new Runnable() {
120 public void run() {
121 dismissDialog();
122 }
123 };
124
125 /**
126 * Create a Dialog window that uses the default dialog frame style.
127 *
128 * @param context The Context the Dialog is to run it. In particular, it
129 * uses the window manager and theme in this context to
130 * present its UI.
131 */
132 public Dialog(Context context) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800133 this(context, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134 }
135
136 /**
137 * Create a Dialog window that uses a custom dialog style.
138 *
139 * @param context The Context in which the Dialog should run. In particular, it
140 * uses the window manager and theme from this context to
141 * present its UI.
142 * @param theme A style resource describing the theme to use for the
143 * window. See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">Style
144 * and Theme Resources</a> for more information about defining and using
145 * styles. This theme is applied on top of the current theme in
146 * <var>context</var>. If 0, the default dialog theme will be used.
147 */
148 public Dialog(Context context, int theme) {
Dianne Hackborne79b5542011-01-27 15:18:46 -0800149 this(context, theme, true);
150 }
151
Jeff Browna492c3a2012-08-23 19:48:44 -0700152 Dialog(Context context, int theme, boolean createContextThemeWrapper) {
153 if (createContextThemeWrapper) {
154 if (theme == 0) {
155 TypedValue outValue = new TypedValue();
156 context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme,
157 outValue, true);
158 theme = outValue.resourceId;
159 }
160 mContext = new ContextThemeWrapper(context, theme);
161 } else {
162 mContext = context;
Adam Powell2fbf4de62010-09-30 15:46:46 -0700163 }
164
Christian Mehlmaueref367522010-05-31 23:08:30 +0200165 mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 Window w = PolicyManager.makeNewWindow(mContext);
167 mWindow = w;
168 w.setCallback(this);
169 w.setWindowManager(mWindowManager, null, null);
170 w.setGravity(Gravity.CENTER);
Romain Guy045163a2009-07-14 13:59:33 -0700171 mListenersHandler = new ListenersHandler(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 }
Jeff Browna492c3a2012-08-23 19:48:44 -0700173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 /**
175 * @deprecated
176 * @hide
177 */
178 @Deprecated
179 protected Dialog(Context context, boolean cancelable,
180 Message cancelCallback) {
181 this(context);
182 mCancelable = cancelable;
183 mCancelMessage = cancelCallback;
184 }
185
186 protected Dialog(Context context, boolean cancelable,
187 OnCancelListener cancelListener) {
188 this(context);
189 mCancelable = cancelable;
190 setOnCancelListener(cancelListener);
191 }
192
193 /**
194 * Retrieve the Context this Dialog is running in.
195 *
Adam Powellc49c1732010-09-28 16:03:15 -0700196 * @return Context The Context used by the Dialog.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 */
198 public final Context getContext() {
199 return mContext;
200 }
201
202 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700203 * Retrieve the {@link ActionBar} attached to this dialog, if present.
204 *
205 * @return The ActionBar attached to the dialog or null if no ActionBar is present.
206 */
207 public ActionBar getActionBar() {
208 return mActionBar;
209 }
210
211 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 * Sets the Activity that owns this dialog. An example use: This Dialog will
213 * use the suggested volume control stream of the Activity.
214 *
215 * @param activity The Activity that owns this dialog.
216 */
217 public final void setOwnerActivity(Activity activity) {
218 mOwnerActivity = activity;
219
220 getWindow().setVolumeControlStream(mOwnerActivity.getVolumeControlStream());
221 }
222
223 /**
224 * Returns the Activity that owns this Dialog. For example, if
225 * {@link Activity#showDialog(int)} is used to show this Dialog, that
226 * Activity will be the owner (by default). Depending on how this dialog was
227 * created, this may return null.
228 *
229 * @return The Activity that owns this Dialog.
230 */
231 public final Activity getOwnerActivity() {
232 return mOwnerActivity;
233 }
234
235 /**
236 * @return Whether the dialog is currently showing.
237 */
238 public boolean isShowing() {
239 return mShowing;
240 }
241
242 /**
243 * Start the dialog and display it on screen. The window is placed in the
244 * application layer and opaque. Note that you should not override this
245 * method to do initialization when the dialog is shown, instead implement
246 * that in {@link #onStart}.
247 */
248 public void show() {
249 if (mShowing) {
svetoslavganov75986cf2009-05-14 22:28:01 -0700250 if (mDecor != null) {
Adam Powelle67a9dc2010-08-17 17:28:56 -0700251 if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
252 mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
253 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700254 mDecor.setVisibility(View.VISIBLE);
255 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 return;
257 }
258
Dianne Hackborn8b4cac12011-01-03 13:58:14 -0800259 mCanceled = false;
260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 if (!mCreated) {
262 dispatchOnCreate(null);
263 }
264
265 onStart();
266 mDecor = mWindow.getDecorView();
Adam Powelldec9dfd2010-08-09 15:27:54 -0700267
268 if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
Adam Powell04fe6eb2013-05-31 14:39:48 -0700269 final ApplicationInfo info = mContext.getApplicationInfo();
270 mWindow.setDefaultIcon(info.icon);
271 mWindow.setDefaultLogo(info.logo);
Adam Powelldec9dfd2010-08-09 15:27:54 -0700272 mActionBar = new ActionBarImpl(this);
273 }
274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 WindowManager.LayoutParams l = mWindow.getAttributes();
276 if ((l.softInputMode
277 & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
278 WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
279 nl.copyFrom(l);
280 nl.softInputMode |=
281 WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
282 l = nl;
283 }
Romain Guy045163a2009-07-14 13:59:33 -0700284
Romain Guy7eec2bc2010-03-29 13:00:07 -0700285 try {
286 mWindowManager.addView(mDecor, l);
287 mShowing = true;
288
289 sendShowMessage();
290 } finally {
291 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 }
293
294 /**
295 * Hide the dialog, but do not dismiss it.
296 */
297 public void hide() {
svetoslavganov75986cf2009-05-14 22:28:01 -0700298 if (mDecor != null) {
299 mDecor.setVisibility(View.GONE);
300 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 }
302
303 /**
304 * Dismiss this dialog, removing it from the screen. This method can be
305 * invoked safely from any thread. Note that you should not override this
306 * method to do cleanup when the dialog is dismissed, instead implement
307 * that in {@link #onStop}.
308 */
Craig Mautner92098c72013-06-10 11:27:26 -0700309 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310 public void dismiss() {
Svetoslav Ganov44bfdd82012-01-26 10:00:18 -0800311 if (Looper.myLooper() == mHandler.getLooper()) {
312 dismissDialog();
313 } else {
314 mHandler.post(mDismissAction);
315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
317
Adam Powell89fc3ac2011-11-01 18:00:44 -0700318 void dismissDialog() {
Romain Guy08a4ac32010-03-16 11:40:40 -0700319 if (mDecor == null || !mShowing) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 return;
321 }
322
Adam Powell89fc3ac2011-11-01 18:00:44 -0700323 if (mWindow.isDestroyed()) {
324 Log.e(TAG, "Tried to dismissDialog() but the Dialog's window was already destroyed!");
325 return;
326 }
327
Romain Guyd2671e12010-03-11 18:06:42 -0800328 try {
Craig Mautner92098c72013-06-10 11:27:26 -0700329 mWindowManager.removeViewImmediate(mDecor);
Romain Guyd2671e12010-03-11 18:06:42 -0800330 } finally {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700331 if (mActionMode != null) {
332 mActionMode.finish();
333 }
Romain Guyd2671e12010-03-11 18:06:42 -0800334 mDecor = null;
335 mWindow.closeAllPanels();
336 onStop();
337 mShowing = false;
Craig Mautner92098c72013-06-10 11:27:26 -0700338
Romain Guyd2671e12010-03-11 18:06:42 -0800339 sendDismissMessage();
340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 }
342
343 private void sendDismissMessage() {
344 if (mDismissMessage != null) {
345 // Obtain a new message so this dialog can be re-used
346 Message.obtain(mDismissMessage).sendToTarget();
347 }
348 }
svetoslavganov75986cf2009-05-14 22:28:01 -0700349
Romain Guy045163a2009-07-14 13:59:33 -0700350 private void sendShowMessage() {
351 if (mShowMessage != null) {
352 // Obtain a new message so this dialog can be re-used
353 Message.obtain(mShowMessage).sendToTarget();
354 }
355 }
356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 // internal method to make sure mcreated is set properly without requiring
358 // users to call through to super in onCreate
359 void dispatchOnCreate(Bundle savedInstanceState) {
Romain Guy6de4aed2009-07-08 10:54:45 -0700360 if (!mCreated) {
361 onCreate(savedInstanceState);
362 mCreated = true;
363 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 }
365
366 /**
Chet Haase49afa5b2010-08-23 11:39:53 -0700367 * Similar to {@link Activity#onCreate}, you should initialize your dialog
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 * in this method, including calling {@link #setContentView}.
369 * @param savedInstanceState If this dialog is being reinitalized after a
370 * the hosting activity was previously shut down, holds the result from
371 * the most recent call to {@link #onSaveInstanceState}, or null if this
372 * is the first time.
373 */
374 protected void onCreate(Bundle savedInstanceState) {
375 }
376
377 /**
378 * Called when the dialog is starting.
379 */
380 protected void onStart() {
Adam Powell50efbed2011-02-08 16:20:15 -0800381 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 }
383
384 /**
385 * Called to tell you that you're stopping.
386 */
387 protected void onStop() {
Adam Powell50efbed2011-02-08 16:20:15 -0800388 if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 }
390
391 private static final String DIALOG_SHOWING_TAG = "android:dialogShowing";
392 private static final String DIALOG_HIERARCHY_TAG = "android:dialogHierarchy";
393
394 /**
395 * Saves the state of the dialog into a bundle.
396 *
397 * The default implementation saves the state of its view hierarchy, so you'll
398 * likely want to call through to super if you override this to save additional
399 * state.
400 * @return A bundle with the state of the dialog.
401 */
402 public Bundle onSaveInstanceState() {
403 Bundle bundle = new Bundle();
404 bundle.putBoolean(DIALOG_SHOWING_TAG, mShowing);
405 if (mCreated) {
406 bundle.putBundle(DIALOG_HIERARCHY_TAG, mWindow.saveHierarchyState());
407 }
408 return bundle;
409 }
410
411 /**
412 * Restore the state of the dialog from a previously saved bundle.
413 *
414 * The default implementation restores the state of the dialog's view
415 * hierarchy that was saved in the default implementation of {@link #onSaveInstanceState()},
416 * so be sure to call through to super when overriding unless you want to
417 * do all restoring of state yourself.
418 * @param savedInstanceState The state of the dialog previously saved by
419 * {@link #onSaveInstanceState()}.
420 */
421 public void onRestoreInstanceState(Bundle savedInstanceState) {
422 final Bundle dialogHierarchyState = savedInstanceState.getBundle(DIALOG_HIERARCHY_TAG);
423 if (dialogHierarchyState == null) {
424 // dialog has never been shown, or onCreated, nothing to restore.
425 return;
426 }
427 dispatchOnCreate(savedInstanceState);
428 mWindow.restoreHierarchyState(dialogHierarchyState);
429 if (savedInstanceState.getBoolean(DIALOG_SHOWING_TAG)) {
430 show();
431 }
432 }
433
434 /**
435 * Retrieve the current Window for the activity. This can be used to
436 * directly access parts of the Window API that are not available
437 * through Activity/Screen.
438 *
439 * @return Window The current window, or null if the activity is not
440 * visual.
441 */
442 public Window getWindow() {
443 return mWindow;
444 }
445
446 /**
447 * Call {@link android.view.Window#getCurrentFocus} on the
448 * Window if this Activity to return the currently focused view.
449 *
450 * @return View The current View with focus or null.
451 *
452 * @see #getWindow
453 * @see android.view.Window#getCurrentFocus
454 */
455 public View getCurrentFocus() {
456 return mWindow != null ? mWindow.getCurrentFocus() : null;
457 }
458
459 /**
460 * Finds a view that was identified by the id attribute from the XML that
461 * was processed in {@link #onStart}.
462 *
463 * @param id the identifier of the view to find
464 * @return The view if found or null otherwise.
465 */
466 public View findViewById(int id) {
467 return mWindow.findViewById(id);
468 }
469
470 /**
471 * Set the screen content from a layout resource. The resource will be
472 * inflated, adding all top-level views to the screen.
473 *
474 * @param layoutResID Resource ID to be inflated.
475 */
476 public void setContentView(int layoutResID) {
477 mWindow.setContentView(layoutResID);
478 }
479
480 /**
481 * Set the screen content to an explicit view. This view is placed
482 * directly into the screen's view hierarchy. It can itself be a complex
483 * view hierarhcy.
484 *
485 * @param view The desired content to display.
486 */
487 public void setContentView(View view) {
488 mWindow.setContentView(view);
489 }
490
491 /**
492 * Set the screen content to an explicit view. This view is placed
493 * directly into the screen's view hierarchy. It can itself be a complex
494 * view hierarhcy.
495 *
496 * @param view The desired content to display.
497 * @param params Layout parameters for the view.
498 */
499 public void setContentView(View view, ViewGroup.LayoutParams params) {
500 mWindow.setContentView(view, params);
501 }
502
503 /**
504 * Add an additional content view to the screen. Added after any existing
505 * ones in the screen -- existing views are NOT removed.
506 *
507 * @param view The desired content to display.
508 * @param params Layout parameters for the view.
509 */
510 public void addContentView(View view, ViewGroup.LayoutParams params) {
511 mWindow.addContentView(view, params);
512 }
513
514 /**
515 * Set the title text for this dialog's window.
516 *
517 * @param title The new text to display in the title.
518 */
519 public void setTitle(CharSequence title) {
520 mWindow.setTitle(title);
521 mWindow.getAttributes().setTitle(title);
522 }
523
524 /**
525 * Set the title text for this dialog's window. The text is retrieved
526 * from the resources with the supplied identifier.
527 *
528 * @param titleId the title's text resource identifier
529 */
530 public void setTitle(int titleId) {
531 setTitle(mContext.getText(titleId));
532 }
533
534 /**
535 * A key was pressed down.
536 *
537 * <p>If the focused view didn't want this event, this method is called.
538 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700539 * <p>The default implementation consumed the KEYCODE_BACK to later
540 * handle it in {@link #onKeyUp}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 *
542 * @see #onKeyUp
543 * @see android.view.KeyEvent
544 */
545 public boolean onKeyDown(int keyCode, KeyEvent event) {
546 if (keyCode == KeyEvent.KEYCODE_BACK) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700547 event.startTracking();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 return true;
549 }
550
551 return false;
552 }
553
554 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700555 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
556 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
557 * the event).
558 */
559 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
560 return false;
561 }
562
563 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 * A key was released.
565 *
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700566 * <p>The default implementation handles KEYCODE_BACK to close the
567 * dialog.
568 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 * @see #onKeyDown
570 * @see KeyEvent
571 */
572 public boolean onKeyUp(int keyCode, KeyEvent event) {
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700573 if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
574 && !event.isCanceled()) {
575 onBackPressed();
576 return true;
577 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 return false;
579 }
580
581 /**
582 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
583 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
584 * the event).
585 */
586 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
587 return false;
588 }
589
590 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700591 * Called when the dialog has detected the user's press of the back
592 * key. The default implementation simply cancels the dialog (only if
593 * it is cancelable), but you can override this to do whatever you want.
594 */
595 public void onBackPressed() {
596 if (mCancelable) {
597 cancel();
598 }
599 }
Jeff Brown64da12a2011-01-04 19:57:47 -0800600
601 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +0900602 * Called when a key shortcut event is not handled by any of the views in the Dialog.
Jeff Brown64da12a2011-01-04 19:57:47 -0800603 * Override this method to implement global key shortcuts for the Dialog.
604 * Key shortcuts can also be implemented by setting the
605 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
606 *
607 * @param keyCode The value in event.getKeyCode().
608 * @param event Description of the key event.
609 * @return True if the key shortcut was handled.
610 */
611 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
612 return false;
613 }
614
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700615 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 * Called when a touch screen event was not handled by any of the views
617 * under it. This is most useful to process touch events that happen outside
618 * of your window bounds, where there is no view to receive it.
619 *
620 * @param event The touch screen event being processed.
621 * @return Return true if you have consumed the event, false if you haven't.
622 * The default implementation will cancel the dialog when a touch
623 * happens outside of the window bounds.
624 */
625 public boolean onTouchEvent(MotionEvent event) {
Dianne Hackborncfaf8872011-01-18 13:57:54 -0800626 if (mCancelable && mShowing && mWindow.shouldCloseOnTouch(mContext, event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 cancel();
628 return true;
629 }
630
631 return false;
632 }
633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 /**
635 * Called when the trackball was moved and not handled by any of the
636 * views inside of the activity. So, for example, if the trackball moves
637 * while focus is on a button, you will receive a call here because
638 * buttons do not normally do anything with trackball events. The call
639 * here happens <em>before</em> trackball movements are converted to
640 * DPAD key events, which then get sent back to the view hierarchy, and
641 * will be processed at the point for things like focus navigation.
642 *
643 * @param event The trackball event being processed.
644 *
645 * @return Return true if you have consumed the event, false if you haven't.
646 * The default implementation always returns false.
647 */
648 public boolean onTrackballEvent(MotionEvent event) {
649 return false;
650 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800651
652 /**
653 * Called when a generic motion event was not handled by any of the
654 * views inside of the dialog.
655 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -0800656 * Generic motion events describe joystick movements, mouse hovers, track pad
657 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -0800658 * {@link MotionEvent#getSource() source} of the motion event specifies
659 * the class of input that was received. Implementations of this method
660 * must examine the bits in the source before processing the event.
661 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -0800662 * </p><p>
663 * Generic motion events with source class
664 * {@link android.view.InputDevice#SOURCE_CLASS_POINTER}
665 * are delivered to the view under the pointer. All other generic motion events are
666 * delivered to the focused view.
667 * </p><p>
668 * See {@link View#onGenericMotionEvent(MotionEvent)} for an example of how to
669 * handle this event.
Jeff Browncb1404e2011-01-15 18:14:15 -0800670 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -0800671 *
672 * @param event The generic motion event being processed.
673 *
674 * @return Return true if you have consumed the event, false if you haven't.
675 * The default implementation always returns false.
676 */
677 public boolean onGenericMotionEvent(MotionEvent event) {
678 return false;
679 }
680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
682 if (mDecor != null) {
683 mWindowManager.updateViewLayout(mDecor, params);
684 }
685 }
686
687 public void onContentChanged() {
688 }
689
690 public void onWindowFocusChanged(boolean hasFocus) {
691 }
692
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700693 public void onAttachedToWindow() {
694 }
695
696 public void onDetachedFromWindow() {
697 }
698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800699 /**
700 * Called to process key events. You can override this to intercept all
701 * key events before they are dispatched to the window. Be sure to call
702 * this implementation for key events that should be handled normally.
703 *
704 * @param event The key event.
705 *
706 * @return boolean Return true if this event was consumed.
707 */
708 public boolean dispatchKeyEvent(KeyEvent event) {
709 if ((mOnKeyListener != null) && (mOnKeyListener.onKey(this, event.getKeyCode(), event))) {
710 return true;
711 }
712 if (mWindow.superDispatchKeyEvent(event)) {
713 return true;
714 }
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700715 return event.dispatch(this, mDecor != null
716 ? mDecor.getKeyDispatcherState() : null, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 }
718
719 /**
Jeff Brown64da12a2011-01-04 19:57:47 -0800720 * Called to process a key shortcut event.
721 * You can override this to intercept all key shortcut events before they are
722 * dispatched to the window. Be sure to call this implementation for key shortcut
723 * events that should be handled normally.
724 *
725 * @param event The key shortcut event.
726 * @return True if this event was consumed.
727 */
728 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
729 if (mWindow.superDispatchKeyShortcutEvent(event)) {
730 return true;
731 }
732 return onKeyShortcut(event.getKeyCode(), event);
733 }
734
735 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 * Called to process touch screen events. You can override this to
737 * intercept all touch screen events before they are dispatched to the
738 * window. Be sure to call this implementation for touch screen events
739 * that should be handled normally.
740 *
741 * @param ev The touch screen event.
742 *
743 * @return boolean Return true if this event was consumed.
744 */
745 public boolean dispatchTouchEvent(MotionEvent ev) {
746 if (mWindow.superDispatchTouchEvent(ev)) {
747 return true;
748 }
749 return onTouchEvent(ev);
750 }
751
752 /**
753 * Called to process trackball events. You can override this to
754 * intercept all trackball events before they are dispatched to the
755 * window. Be sure to call this implementation for trackball events
756 * that should be handled normally.
757 *
758 * @param ev The trackball event.
759 *
760 * @return boolean Return true if this event was consumed.
761 */
762 public boolean dispatchTrackballEvent(MotionEvent ev) {
763 if (mWindow.superDispatchTrackballEvent(ev)) {
764 return true;
765 }
766 return onTrackballEvent(ev);
767 }
768
Jeff Browncb1404e2011-01-15 18:14:15 -0800769 /**
770 * Called to process generic motion events. You can override this to
771 * intercept all generic motion events before they are dispatched to the
772 * window. Be sure to call this implementation for generic motion events
773 * that should be handled normally.
774 *
775 * @param ev The generic motion event.
776 *
777 * @return boolean Return true if this event was consumed.
778 */
779 public boolean dispatchGenericMotionEvent(MotionEvent ev) {
780 if (mWindow.superDispatchGenericMotionEvent(ev)) {
781 return true;
782 }
783 return onGenericMotionEvent(ev);
784 }
785
svetoslavganov75986cf2009-05-14 22:28:01 -0700786 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
787 event.setClassName(getClass().getName());
788 event.setPackageName(mContext.getPackageName());
789
790 LayoutParams params = getWindow().getAttributes();
Romain Guy980a9382010-01-08 15:06:28 -0800791 boolean isFullScreen = (params.width == LayoutParams.MATCH_PARENT) &&
792 (params.height == LayoutParams.MATCH_PARENT);
svetoslavganov75986cf2009-05-14 22:28:01 -0700793 event.setFullScreen(isFullScreen);
794
795 return false;
796 }
797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 /**
799 * @see Activity#onCreatePanelView(int)
800 */
801 public View onCreatePanelView(int featureId) {
802 return null;
803 }
804
805 /**
806 * @see Activity#onCreatePanelMenu(int, Menu)
807 */
808 public boolean onCreatePanelMenu(int featureId, Menu menu) {
809 if (featureId == Window.FEATURE_OPTIONS_PANEL) {
810 return onCreateOptionsMenu(menu);
811 }
812
813 return false;
814 }
815
816 /**
817 * @see Activity#onPreparePanel(int, View, Menu)
818 */
819 public boolean onPreparePanel(int featureId, View view, Menu menu) {
820 if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
821 boolean goforit = onPrepareOptionsMenu(menu);
822 return goforit && menu.hasVisibleItems();
823 }
824 return true;
825 }
826
827 /**
828 * @see Activity#onMenuOpened(int, Menu)
829 */
830 public boolean onMenuOpened(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800831 if (featureId == Window.FEATURE_ACTION_BAR) {
832 mActionBar.dispatchMenuVisibilityChanged(true);
833 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800834 return true;
835 }
836
837 /**
838 * @see Activity#onMenuItemSelected(int, MenuItem)
839 */
840 public boolean onMenuItemSelected(int featureId, MenuItem item) {
841 return false;
842 }
843
844 /**
845 * @see Activity#onPanelClosed(int, Menu)
846 */
847 public void onPanelClosed(int featureId, Menu menu) {
Adam Powell8515ee82010-11-30 14:09:55 -0800848 if (featureId == Window.FEATURE_ACTION_BAR) {
849 mActionBar.dispatchMenuVisibilityChanged(false);
850 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 }
852
853 /**
854 * It is usually safe to proxy this call to the owner activity's
855 * {@link Activity#onCreateOptionsMenu(Menu)} if the client desires the same
856 * menu for this Dialog.
857 *
858 * @see Activity#onCreateOptionsMenu(Menu)
859 * @see #getOwnerActivity()
860 */
861 public boolean onCreateOptionsMenu(Menu menu) {
862 return true;
863 }
864
865 /**
866 * It is usually safe to proxy this call to the owner activity's
867 * {@link Activity#onPrepareOptionsMenu(Menu)} if the client desires the
868 * same menu for this Dialog.
869 *
870 * @see Activity#onPrepareOptionsMenu(Menu)
871 * @see #getOwnerActivity()
872 */
873 public boolean onPrepareOptionsMenu(Menu menu) {
874 return true;
875 }
876
877 /**
878 * @see Activity#onOptionsItemSelected(MenuItem)
879 */
880 public boolean onOptionsItemSelected(MenuItem item) {
881 return false;
882 }
883
884 /**
885 * @see Activity#onOptionsMenuClosed(Menu)
886 */
887 public void onOptionsMenuClosed(Menu menu) {
888 }
889
890 /**
891 * @see Activity#openOptionsMenu()
892 */
893 public void openOptionsMenu() {
894 mWindow.openPanel(Window.FEATURE_OPTIONS_PANEL, null);
895 }
896
897 /**
898 * @see Activity#closeOptionsMenu()
899 */
900 public void closeOptionsMenu() {
901 mWindow.closePanel(Window.FEATURE_OPTIONS_PANEL);
902 }
903
904 /**
Adam Powelle67a9dc2010-08-17 17:28:56 -0700905 * @see Activity#invalidateOptionsMenu()
906 */
907 public void invalidateOptionsMenu() {
908 mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
909 }
910
911 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800912 * @see Activity#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)
913 */
914 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
915 }
916
917 /**
918 * @see Activity#registerForContextMenu(View)
919 */
920 public void registerForContextMenu(View view) {
921 view.setOnCreateContextMenuListener(this);
922 }
923
924 /**
925 * @see Activity#unregisterForContextMenu(View)
926 */
927 public void unregisterForContextMenu(View view) {
928 view.setOnCreateContextMenuListener(null);
929 }
930
931 /**
932 * @see Activity#openContextMenu(View)
933 */
934 public void openContextMenu(View view) {
935 view.showContextMenu();
936 }
937
938 /**
939 * @see Activity#onContextItemSelected(MenuItem)
940 */
941 public boolean onContextItemSelected(MenuItem item) {
942 return false;
943 }
944
945 /**
946 * @see Activity#onContextMenuClosed(Menu)
947 */
948 public void onContextMenuClosed(Menu menu) {
949 }
950
951 /**
952 * This hook is called when the user signals the desire to start a search.
953 */
954 public boolean onSearchRequested() {
Karl Rosaen53d24af2009-07-14 14:58:10 -0700955 final SearchManager searchManager = (SearchManager) mContext
956 .getSystemService(Context.SEARCH_SERVICE);
957
Bjorn Bringertb8144a92010-02-22 20:48:57 +0000958 // associate search with owner activity
Karl Rosaen7bafed82009-09-04 11:15:21 -0700959 final ComponentName appName = getAssociatedActivity();
lge-aosp06ca9972011-03-15 10:25:57 +0900960 if (appName != null && searchManager.getSearchableInfo(appName) != null) {
Bjorn Bringertb8144a92010-02-22 20:48:57 +0000961 searchManager.startSearch(null, false, appName, null, false);
962 dismiss();
963 return true;
964 } else {
965 return false;
966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 }
968
Adam Powelldebf3be2010-11-15 18:58:48 -0800969 public ActionMode onWindowStartingActionMode(ActionMode.Callback callback) {
Adam Powelldec9dfd2010-08-09 15:27:54 -0700970 if (mActionBar != null) {
971 return mActionBar.startActionMode(callback);
972 }
Adam Powell6e346362010-07-23 10:18:23 -0700973 return null;
974 }
975
Adam Powellcfe9aee2011-11-01 14:56:27 -0700976 /**
977 * {@inheritDoc}
978 *
979 * Note that if you override this method you should always call through
980 * to the superclass implementation by calling super.onActionModeStarted(mode).
981 */
Adam Powelldebf3be2010-11-15 18:58:48 -0800982 public void onActionModeStarted(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700983 mActionMode = mode;
Adam Powelldebf3be2010-11-15 18:58:48 -0800984 }
985
Adam Powellcfe9aee2011-11-01 14:56:27 -0700986 /**
987 * {@inheritDoc}
988 *
989 * Note that if you override this method you should always call through
990 * to the superclass implementation by calling super.onActionModeFinished(mode).
991 */
Adam Powelldebf3be2010-11-15 18:58:48 -0800992 public void onActionModeFinished(ActionMode mode) {
Adam Powellcfe9aee2011-11-01 14:56:27 -0700993 if (mode == mActionMode) {
994 mActionMode = null;
995 }
Adam Powelldebf3be2010-11-15 18:58:48 -0800996 }
997
Karl Rosaen7bafed82009-09-04 11:15:21 -0700998 /**
Adam Powelldec9dfd2010-08-09 15:27:54 -0700999 * @return The activity associated with this dialog, or null if there is no associated activity.
Karl Rosaen7bafed82009-09-04 11:15:21 -07001000 */
1001 private ComponentName getAssociatedActivity() {
1002 Activity activity = mOwnerActivity;
1003 Context context = getContext();
1004 while (activity == null && context != null) {
1005 if (context instanceof Activity) {
1006 activity = (Activity) context; // found it!
1007 } else {
1008 context = (context instanceof ContextWrapper) ?
1009 ((ContextWrapper) context).getBaseContext() : // unwrap one level
1010 null; // done
1011 }
1012 }
1013 return activity == null ? null : activity.getComponentName();
1014 }
1015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016
1017 /**
1018 * Request that key events come to this dialog. Use this if your
1019 * dialog has no views with focus, but the dialog still wants
1020 * a chance to process key events.
1021 *
1022 * @param get true if the dialog should receive key events, false otherwise
1023 * @see android.view.Window#takeKeyEvents
1024 */
1025 public void takeKeyEvents(boolean get) {
1026 mWindow.takeKeyEvents(get);
1027 }
1028
1029 /**
1030 * Enable extended window features. This is a convenience for calling
1031 * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
1032 *
1033 * @param featureId The desired feature as defined in
1034 * {@link android.view.Window}.
1035 * @return Returns true if the requested feature is supported and now
1036 * enabled.
1037 *
1038 * @see android.view.Window#requestFeature
1039 */
1040 public final boolean requestWindowFeature(int featureId) {
1041 return getWindow().requestFeature(featureId);
1042 }
1043
1044 /**
1045 * Convenience for calling
1046 * {@link android.view.Window#setFeatureDrawableResource}.
1047 */
1048 public final void setFeatureDrawableResource(int featureId, int resId) {
1049 getWindow().setFeatureDrawableResource(featureId, resId);
1050 }
1051
1052 /**
1053 * Convenience for calling
1054 * {@link android.view.Window#setFeatureDrawableUri}.
1055 */
1056 public final void setFeatureDrawableUri(int featureId, Uri uri) {
1057 getWindow().setFeatureDrawableUri(featureId, uri);
1058 }
1059
1060 /**
1061 * Convenience for calling
1062 * {@link android.view.Window#setFeatureDrawable(int, Drawable)}.
1063 */
1064 public final void setFeatureDrawable(int featureId, Drawable drawable) {
1065 getWindow().setFeatureDrawable(featureId, drawable);
1066 }
1067
1068 /**
1069 * Convenience for calling
1070 * {@link android.view.Window#setFeatureDrawableAlpha}.
1071 */
1072 public final void setFeatureDrawableAlpha(int featureId, int alpha) {
1073 getWindow().setFeatureDrawableAlpha(featureId, alpha);
1074 }
1075
1076 public LayoutInflater getLayoutInflater() {
1077 return getWindow().getLayoutInflater();
1078 }
1079
1080 /**
1081 * Sets whether this dialog is cancelable with the
1082 * {@link KeyEvent#KEYCODE_BACK BACK} key.
1083 */
1084 public void setCancelable(boolean flag) {
1085 mCancelable = flag;
1086 }
1087
1088 /**
1089 * Sets whether this dialog is canceled when touched outside the window's
1090 * bounds. If setting to true, the dialog is set to be cancelable if not
1091 * already set.
1092 *
1093 * @param cancel Whether the dialog should be canceled when touched outside
1094 * the window.
1095 */
1096 public void setCanceledOnTouchOutside(boolean cancel) {
1097 if (cancel && !mCancelable) {
1098 mCancelable = true;
1099 }
1100
Dianne Hackborncfaf8872011-01-18 13:57:54 -08001101 mWindow.setCloseOnTouchOutside(cancel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 }
1103
1104 /**
1105 * Cancel the dialog. This is essentially the same as calling {@link #dismiss()}, but it will
1106 * also call your {@link DialogInterface.OnCancelListener} (if registered).
1107 */
1108 public void cancel() {
Dianne Hackborn8b4cac12011-01-03 13:58:14 -08001109 if (!mCanceled && mCancelMessage != null) {
1110 mCanceled = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 // Obtain a new message so this dialog can be re-used
1112 Message.obtain(mCancelMessage).sendToTarget();
1113 }
1114 dismiss();
1115 }
1116
1117 /**
1118 * Set a listener to be invoked when the dialog is canceled.
Adam Powell7f02dc52012-08-27 13:35:16 -07001119 *
1120 * <p>This will only be invoked when the dialog is canceled.
1121 * Cancel events alone will not capture all ways that
1122 * the dialog might be dismissed. If the creator needs
1123 * to know when a dialog is dismissed in general, use
1124 * {@link #setOnDismissListener}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 *
1126 * @param listener The {@link DialogInterface.OnCancelListener} to use.
1127 */
1128 public void setOnCancelListener(final OnCancelListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001129 if (mCancelAndDismissTaken != null) {
1130 throw new IllegalStateException(
1131 "OnCancelListener is already taken by "
1132 + mCancelAndDismissTaken + " and can not be replaced.");
1133 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001135 mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001136 } else {
1137 mCancelMessage = null;
1138 }
1139 }
1140
1141 /**
1142 * Set a message to be sent when the dialog is canceled.
1143 * @param msg The msg to send when the dialog is canceled.
1144 * @see #setOnCancelListener(android.content.DialogInterface.OnCancelListener)
1145 */
1146 public void setCancelMessage(final Message msg) {
1147 mCancelMessage = msg;
1148 }
1149
1150 /**
1151 * Set a listener to be invoked when the dialog is dismissed.
1152 * @param listener The {@link DialogInterface.OnDismissListener} to use.
1153 */
1154 public void setOnDismissListener(final OnDismissListener listener) {
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001155 if (mCancelAndDismissTaken != null) {
1156 throw new IllegalStateException(
1157 "OnDismissListener is already taken by "
1158 + mCancelAndDismissTaken + " and can not be replaced.");
1159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 if (listener != null) {
Romain Guy045163a2009-07-14 13:59:33 -07001161 mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 } else {
1163 mDismissMessage = null;
1164 }
1165 }
1166
1167 /**
Romain Guy045163a2009-07-14 13:59:33 -07001168 * Sets a listener to be invoked when the dialog is shown.
Ficus Kirkpatrick130a8b72010-01-14 15:39:43 -08001169 * @param listener The {@link DialogInterface.OnShowListener} to use.
Romain Guy045163a2009-07-14 13:59:33 -07001170 */
1171 public void setOnShowListener(OnShowListener listener) {
1172 if (listener != null) {
1173 mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
1174 } else {
1175 mShowMessage = null;
1176 }
1177 }
1178
1179 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 * Set a message to be sent when the dialog is dismissed.
1181 * @param msg The msg to send when the dialog is dismissed.
1182 */
1183 public void setDismissMessage(final Message msg) {
1184 mDismissMessage = msg;
1185 }
1186
Dianne Hackbornf812fee2011-01-25 14:54:29 -08001187 /** @hide */
1188 public boolean takeCancelAndDismissListeners(String msg, final OnCancelListener cancel,
1189 final OnDismissListener dismiss) {
1190 if (mCancelAndDismissTaken != null) {
1191 mCancelAndDismissTaken = null;
1192 } else if (mCancelMessage != null || mDismissMessage != null) {
1193 return false;
1194 }
1195
1196 setOnCancelListener(cancel);
1197 setOnDismissListener(dismiss);
1198 mCancelAndDismissTaken = msg;
1199
1200 return true;
1201 }
1202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 /**
1204 * By default, this will use the owner Activity's suggested stream type.
1205 *
1206 * @see Activity#setVolumeControlStream(int)
1207 * @see #setOwnerActivity(Activity)
1208 */
1209 public final void setVolumeControlStream(int streamType) {
1210 getWindow().setVolumeControlStream(streamType);
1211 }
1212
1213 /**
1214 * @see Activity#getVolumeControlStream()
1215 */
1216 public final int getVolumeControlStream() {
1217 return getWindow().getVolumeControlStream();
1218 }
1219
1220 /**
1221 * Sets the callback that will be called if a key is dispatched to the dialog.
1222 */
1223 public void setOnKeyListener(final OnKeyListener onKeyListener) {
1224 mOnKeyListener = onKeyListener;
1225 }
1226
Romain Guy045163a2009-07-14 13:59:33 -07001227 private static final class ListenersHandler extends Handler {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 private WeakReference<DialogInterface> mDialog;
1229
Romain Guy045163a2009-07-14 13:59:33 -07001230 public ListenersHandler(Dialog dialog) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 mDialog = new WeakReference<DialogInterface>(dialog);
1232 }
1233
1234 @Override
1235 public void handleMessage(Message msg) {
1236 switch (msg.what) {
1237 case DISMISS:
1238 ((OnDismissListener) msg.obj).onDismiss(mDialog.get());
1239 break;
1240 case CANCEL:
1241 ((OnCancelListener) msg.obj).onCancel(mDialog.get());
1242 break;
Romain Guy045163a2009-07-14 13:59:33 -07001243 case SHOW:
1244 ((OnShowListener) msg.obj).onShow(mDialog.get());
1245 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001246 }
1247 }
1248 }
1249}