1 /*
2  * Copyright 2016, 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 
17 package com.android.managedprovisioning.common;
18 
19 import android.app.Activity;
20 import android.app.AlertDialog;
21 import android.app.Dialog;
22 import android.app.DialogFragment;
23 import android.content.DialogInterface;
24 import android.os.Bundle;
25 
26 /**
27  * Utility class wrapping a {@link AlertDialog} in a {@link DialogFragment}
28  * <p> In order to properly handle Dialog lifecycle we follow the practice of wrapping of them
29  * in a Dialog Fragment.
30  * <p> If buttons are to be used (enabled by setting a button message), the creator {@link Activity}
31  * must implement {@link SimpleDialogListener}.
32  */
33 public class SimpleDialog extends DialogFragment {
34     private static final String TITLE = "title";
35     private static final String MESSAGE = "message";
36     private static final String NEGATIVE_BUTTON_MESSAGE = "negativeButtonMessage";
37     private static final String POSITIVE_BUTTON_MESSAGE = "positiveButtonMessage";
38 
39     /**
40      * Use the {@link Builder} instead. Keeping the constructor public only because
41      * a {@link DialogFragment} must have an empty constructor that is public.
42      */
SimpleDialog()43     public SimpleDialog() {
44     }
45 
46     @Override
onCreateDialog(Bundle savedInstanceState)47     public AlertDialog onCreateDialog(Bundle savedInstanceState) {
48         final SimpleDialogListener dialogListener = (SimpleDialogListener) getActivity();
49 
50         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
51 
52         Bundle args = getArguments();
53         if (args.containsKey(TITLE)) {
54             builder.setTitle(args.getInt(TITLE));
55         }
56 
57         if (args.containsKey(MESSAGE)) {
58             builder.setMessage(args.getInt(MESSAGE));
59         }
60 
61         if (args.containsKey(NEGATIVE_BUTTON_MESSAGE)) {
62             builder.setNegativeButton(args.getInt(NEGATIVE_BUTTON_MESSAGE),
63                     new DialogInterface.OnClickListener() {
64                 @Override
65                 public void onClick(DialogInterface dialog, int which) {
66                     dialogListener.onNegativeButtonClick(SimpleDialog.this);
67                 }
68             });
69         }
70 
71         if (args.containsKey(POSITIVE_BUTTON_MESSAGE)) {
72             builder.setPositiveButton(args.getInt(POSITIVE_BUTTON_MESSAGE),
73                     new DialogInterface.OnClickListener() {
74                 @Override
75                 public void onClick(DialogInterface dialog, int which) {
76                     dialogListener.onPositiveButtonClick(SimpleDialog.this);
77                 }
78             });
79         }
80 
81         return builder.create();
82     }
83 
84     /**
85      * Throws an exception informing of a lack of a handler for a dialog button click
86      * <p> Useful when implementing {@link SimpleDialogListener}
87      */
throwButtonClickHandlerNotImplemented(DialogFragment dialog)88     public static void throwButtonClickHandlerNotImplemented(DialogFragment dialog) {
89         throw new IllegalArgumentException("Button click handler not implemented for dialog: "
90                 + dialog.getTag());
91     }
92 
93     public static class Builder implements DialogBuilder {
94         private Integer mTitle;
95         private Integer mMessage;
96         private Integer mNegativeButtonMessage;
97         private Integer mPositiveButtonMessage;
98         private Boolean mCancelable;
99 
100         /**
101          * Sets the title
102          * @param title Title resource id.
103          */
setTitle(Integer title)104         public Builder setTitle(Integer title) {
105             mTitle = title;
106             return this;
107         }
108 
109         /**
110          * Sets the message
111          * @param message Message resource id.
112          */
setMessage(int message)113         public Builder setMessage(int message) {
114             mMessage = message;
115             return this;
116         }
117 
118         /**
119          * Sets a message for the button.
120          * <p> Makes the button appear (without setting a button message, a button is not displayed)
121          * <p> Callback must be handled by a creator {@link Activity},
122          * which must implement {@link SimpleDialogListener}.
123          * @param negativeButtonMessage Message resource id.
124          */
setNegativeButtonMessage(int negativeButtonMessage)125         public Builder setNegativeButtonMessage(int negativeButtonMessage) {
126             mNegativeButtonMessage = negativeButtonMessage;
127             return this;
128         }
129 
130         /**
131          * Sets a message for the button.
132          * <p> Makes the button appear (without setting a button message, a button is not displayed)
133          * <p> Callback must be handled by a creator {@link Activity},
134          * which must implement {@link SimpleDialogListener}.
135          * @param positiveButtonMessage Message resource id.
136          */
setPositiveButtonMessage(int positiveButtonMessage)137         public Builder setPositiveButtonMessage(int positiveButtonMessage) {
138             mPositiveButtonMessage = positiveButtonMessage;
139             return this;
140         }
141 
142         /**
143          * Sets whether the dialog is cancelable or not.  Default is true.
144          */
setCancelable(boolean cancelable)145         public Builder setCancelable(boolean cancelable) {
146             mCancelable = cancelable;
147             return this;
148         }
149 
150         /**
151          * Creates an {@link SimpleDialog} with the arguments supplied to this builder.
152          */
153         @Override
build()154         public SimpleDialog build() {
155             SimpleDialog instance = new SimpleDialog();
156             Bundle args = new Bundle();
157 
158             if (mTitle != null) {
159                 args.putInt(TITLE, mTitle);
160             }
161 
162             if (mMessage != null) {
163                 args.putInt(MESSAGE, mMessage);
164             }
165 
166             if (mNegativeButtonMessage != null) {
167                 args.putInt(NEGATIVE_BUTTON_MESSAGE, mNegativeButtonMessage);
168             }
169 
170             if (mPositiveButtonMessage != null) {
171                 args.putInt(POSITIVE_BUTTON_MESSAGE, mPositiveButtonMessage);
172             }
173 
174             if (mCancelable != null) {
175                 instance.setCancelable(mCancelable);
176             }
177 
178             instance.setArguments(args);
179             return instance;
180         }
181     }
182 
183     /**
184      * Interface for handling callbacks from {@link SimpleDialog} buttons.
185      *
186      * <p>If multiple dialogs are used in a context of a single {@link Activity},
187      * a consumer of the interface can differentiate between dialogs using
188      * e.g. a {@link DialogFragment#getTag()}, or {@link DialogFragment#getArguments()}.
189      */
190     public interface SimpleDialogListener {
191         /**
192          * Called when a user clicks on the positive dialog button.
193          * <p> To be implemented by a host {@link Activity} object.
194          * @param dialog {@link DialogFragment} where the click happened.
195          */
onPositiveButtonClick(DialogFragment dialog)196         void onPositiveButtonClick(DialogFragment dialog);
197 
198         /**
199          * Called when a user clicks on the negative dialog button.
200          * <p> To be implemented by a host {@link Activity} object.
201          * @param dialog {@link DialogFragment} where the click happened.
202          */
onNegativeButtonClick(DialogFragment dialog)203         void onNegativeButtonClick(DialogFragment dialog);
204     }
205 }