1/*
2 * Copyright (C) 2010 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.contacts.util;
18
19import android.app.Activity;
20import android.app.Dialog;
21import android.content.DialogInterface;
22import android.content.DialogInterface.OnDismissListener;
23import android.os.Bundle;
24import android.view.View;
25
26import com.android.contacts.R;
27
28/**
29 * Manages creation and destruction of Dialogs that are to be shown by Views. Unlike how Dialogs
30 * are regularly used, the Dialogs are not recycled but immediately destroyed after dismissal.
31 * To be able to do that, two IDs are required which are used consecutively.
32 * How to use:<ul>
33 * <li>The owning Activity creates on instance of this class, passing itself and two Ids that are
34 *    not used by other Dialogs of the Activity.</li>
35 * <li>Views owning Dialogs must implement {@link DialogManager.DialogShowingView}</li>
36 * <li>After creating the Views, configureManagingViews must be called to configure all views
37 *    that implement {@link DialogManager.DialogShowingView}</li>
38 * <li>In the implementation of {@link Activity#onCreateDialog}, calls for the
39 *    ViewId are forwarded to {@link DialogManager#onCreateDialog(int, Bundle)}</li>
40 * </ul>
41 * To actually show a Dialog, the View uses {@link DialogManager#showDialogInView(View, Bundle)},
42 * passing itself as a first parameter
43 */
44public class DialogManager {
45    private final Activity mActivity;
46    private boolean mUseDialogId2 = false;
47    public final static String VIEW_ID_KEY = "view_id";
48
49    public static final boolean isManagedId(int id) {
50        return (id == R.id.dialog_manager_id_1) || (id == R.id.dialog_manager_id_2);
51    }
52
53    /**
54     * Creates a new instance of this class for the given Activity.
55     * @param activity The activity this object is used for
56     */
57    public DialogManager(final Activity activity) {
58        if (activity == null) throw new IllegalArgumentException("activity must not be null");
59        mActivity = activity;
60    }
61
62    /**
63     * Called by a View to show a dialog. It has to pass itself and a Bundle with extra information.
64     * If the view can show several dialogs, it should distinguish them using an item in the Bundle.
65     * The View needs to have a valid and unique Id. This function modifies the bundle by adding a
66     * new item named {@link DialogManager#VIEW_ID_KEY}
67     */
68    public void showDialogInView(final View view, final Bundle bundle) {
69        final int viewId = view.getId();
70        if (bundle.containsKey(VIEW_ID_KEY)) {
71            throw new IllegalArgumentException("Bundle already contains a " + VIEW_ID_KEY);
72        }
73        if (viewId == View.NO_ID) {
74            throw new IllegalArgumentException("View does not have a proper ViewId");
75        }
76        bundle.putInt(VIEW_ID_KEY, viewId);
77        int dialogId = mUseDialogId2 ? R.id.dialog_manager_id_2 : R.id.dialog_manager_id_1;
78        mActivity.showDialog(dialogId, bundle);
79    }
80
81    /**
82     * Callback function called by the Activity to handle View-managed Dialogs.
83     * This function returns null if the id is not one of the two reserved Ids.
84     */
85    public Dialog onCreateDialog(final int id, final Bundle bundle) {
86        if (id == R.id.dialog_manager_id_1) {
87            mUseDialogId2 = true;
88        } else if (id == R.id.dialog_manager_id_2) {
89            mUseDialogId2 = false;
90        } else {
91            return null;
92        }
93        if (!bundle.containsKey(VIEW_ID_KEY)) {
94            throw new IllegalArgumentException("Bundle does not contain a ViewId");
95        }
96        final int viewId = bundle.getInt(VIEW_ID_KEY);
97        final View view = mActivity.findViewById(viewId);
98        if (view == null || !(view instanceof DialogShowingView)) {
99            return null;
100        }
101        final Dialog dialog = ((DialogShowingView)view).createDialog(bundle);
102        if (dialog == null) {
103            return dialog;
104        }
105
106        // As we will never re-use this dialog, we can completely kill it here
107        dialog.setOnDismissListener(new OnDismissListener() {
108            public void onDismiss(DialogInterface dialogInterface) {
109                mActivity.removeDialog(id);
110            }
111        });
112        return dialog;
113    }
114
115    /**
116     * Interface to implemented by Views that show Dialogs
117     */
118    public interface DialogShowingView {
119        /**
120         * Callback function to create a Dialog. Notice that the DialogManager overwrites the
121         * OnDismissListener on the returned Dialog, so the View should not use this Listener itself
122         */
123        Dialog createDialog(Bundle bundle);
124    }
125
126    /**
127     * Interface to implemented by Activities that host View-showing dialogs
128     */
129    public interface DialogShowingViewActivity {
130        DialogManager getDialogManager();
131    }
132}
133