1 /*
2  * Copyright (C) 2023 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 package com.android.settingslib.utils;
17 import android.annotation.IntDef;
18 import android.annotation.StringRes;
19 import android.app.AlertDialog;
20 import android.app.Dialog;
21 import android.content.Context;
22 import android.graphics.drawable.Drawable;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.view.WindowManager;
26 import android.widget.Button;
27 import android.widget.ImageView;
28 import android.widget.LinearLayout;
29 import android.widget.TextView;
30 
31 import com.android.settingslib.R;
32 
33 import java.lang.annotation.Retention;
34 import java.lang.annotation.RetentionPolicy;
35 
36 /**
37  * This class is used to create custom dialog with icon, title, message and custom view that are
38  * horizontally centered.
39  */
40 public class CustomDialogHelper {
41 
42     @Retention(RetentionPolicy.SOURCE)
43     @IntDef({ICON, TITLE, MESSAGE, LAYOUT, BACK_BUTTON, NEGATIVE_BUTTON, POSITIVE_BUTTON})
44     public @interface LayoutComponent {}
45 
46     @Retention(RetentionPolicy.SOURCE)
47     @IntDef({BACK_BUTTON, NEGATIVE_BUTTON, POSITIVE_BUTTON})
48     public @interface LayoutButton {}
49 
50     public static final int ICON = 0;
51     public static final int TITLE = 1;
52     public static final int MESSAGE = 2;
53     public static final int LAYOUT = 3;
54     public static final int BACK_BUTTON = 4;
55     public static final int NEGATIVE_BUTTON = 5;
56     public static final int POSITIVE_BUTTON = 6;
57     private View mDialogContent;
58     private Dialog mDialog;
59     private Context mContext;
60     private LayoutInflater mLayoutInflater;
61     private ImageView mDialogIcon;
62     private TextView mDialogTitle;
63     private TextView mDialogMessage;
64     private LinearLayout mCustomLayout;
65     private Button mPositiveButton;
66     private Button mNegativeButton;
67     private Button mBackButton;
68 
CustomDialogHelper(Context context)69     public CustomDialogHelper(Context context) {
70         mContext = context;
71         mLayoutInflater = LayoutInflater.from(context);
72         mDialogContent = mLayoutInflater.inflate(R.layout.dialog_with_icon, null);
73         mDialogIcon = mDialogContent.findViewById(R.id.dialog_with_icon_icon);
74         mDialogTitle = mDialogContent.findViewById(R.id.dialog_with_icon_title);
75         mDialogMessage = mDialogContent.findViewById(R.id.dialog_with_icon_message);
76         mCustomLayout = mDialogContent.findViewById(R.id.custom_layout);
77         mPositiveButton = mDialogContent.findViewById(R.id.button_ok);
78         mNegativeButton = mDialogContent.findViewById(R.id.button_cancel);
79         mBackButton = mDialogContent.findViewById(R.id.button_back);
80         createDialog();
81     }
82 
83     /**
84      * Creates dialog with content defined in constructor.
85      */
createDialog()86     private void createDialog() {
87         mDialog = new AlertDialog.Builder(mContext)
88                 .setView(mDialogContent)
89                 .setCancelable(true)
90                 .create();
91         mDialog.getWindow()
92                 .setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
93     }
94 
95     /**
96      * Sets title and listener for positive button.
97      */
setPositiveButton(@tringRes int resid, View.OnClickListener onClickListener)98     public CustomDialogHelper setPositiveButton(@StringRes int resid,
99             View.OnClickListener onClickListener) {
100         setButton(POSITIVE_BUTTON, resid, onClickListener);
101         return this;
102     }
103 
104     /**
105      * Sets positive button text.
106      */
setPositiveButtonText(@tringRes int resid)107     public CustomDialogHelper setPositiveButtonText(@StringRes int resid) {
108         mPositiveButton.setText(resid);
109         return this;
110     }
111 
112     /**
113      * Sets title and listener for negative button.
114      */
setNegativeButton(@tringRes int resid, View.OnClickListener onClickListener)115     public CustomDialogHelper setNegativeButton(@StringRes int resid,
116             View.OnClickListener onClickListener) {
117         setButton(NEGATIVE_BUTTON, resid, onClickListener);
118         return this;
119     }
120 
121     /**
122      * Sets negative button text.
123      */
setNegativeButtonText(@tringRes int resid)124     public CustomDialogHelper setNegativeButtonText(@StringRes int resid) {
125         mNegativeButton.setText(resid);
126         return this;
127     }
128 
129     /**
130      * Sets title and listener for back button.
131      */
setBackButton(@tringRes int resid, View.OnClickListener onClickListener)132     public CustomDialogHelper setBackButton(@StringRes int resid,
133             View.OnClickListener onClickListener) {
134         setButton(BACK_BUTTON, resid, onClickListener);
135         return this;
136     }
137 
138     /**
139      * Sets title for back button.
140      */
setBackButtonText(@tringRes int resid)141     public CustomDialogHelper setBackButtonText(@StringRes int resid) {
142         mBackButton.setText(resid);
143         return this;
144     }
145 
setButton(@ayoutButton int whichButton, @StringRes int resid, View.OnClickListener listener)146     private void setButton(@LayoutButton int whichButton, @StringRes int resid,
147             View.OnClickListener listener) {
148         switch (whichButton) {
149             case POSITIVE_BUTTON :
150                 mPositiveButton.setText(resid);
151                 mPositiveButton.setVisibility(View.VISIBLE);
152                 mPositiveButton.setOnClickListener(listener);
153                 break;
154             case NEGATIVE_BUTTON:
155                 mNegativeButton.setText(resid);
156                 mNegativeButton.setVisibility(View.VISIBLE);
157                 mNegativeButton.setOnClickListener(listener);
158                 break;
159             case BACK_BUTTON:
160                 mBackButton.setText(resid);
161                 mBackButton.setVisibility(View.VISIBLE);
162                 mBackButton.setOnClickListener(listener);
163                 break;
164             default:
165                 break;
166         }
167     }
168 
169 
170     /**
171      * Modifies state of button.
172      * //TODO: modify method to allow setting state for any button.
173      */
setButtonEnabled(boolean enabled)174     public CustomDialogHelper setButtonEnabled(boolean enabled) {
175         mPositiveButton.setEnabled(enabled);
176         return this;
177     }
178 
179     /**
180      * Sets title of the dialog.
181      */
setTitle(@tringRes int resid)182     public CustomDialogHelper setTitle(@StringRes int resid) {
183         mDialogTitle.setText(resid);
184         return this;
185     }
186 
187     /**
188      * Sets message of the dialog.
189      */
setMessage(@tringRes int resid)190     public CustomDialogHelper setMessage(@StringRes int resid) {
191         mDialogMessage.setText(resid);
192         return this;
193     }
194 
195     /**
196      * Sets message padding of the dialog.
197      */
setMessagePadding(int dp)198     public CustomDialogHelper setMessagePadding(int dp) {
199         mDialogMessage.setPadding(dp, dp, dp, dp);
200         return this;
201     }
202 
203     /**
204      * Sets icon of the dialog.
205      */
setIcon(Drawable icon)206     public CustomDialogHelper setIcon(Drawable icon) {
207         mDialogIcon.setImageDrawable(icon);
208         return this;
209     }
210 
211     /**
212      * Removes all views that were previously added to the custom layout part.
213      */
clearCustomLayout()214     public CustomDialogHelper clearCustomLayout() {
215         mCustomLayout.removeAllViews();
216         return this;
217     }
218 
219     /**
220      * Hides custom layout.
221      */
hideCustomLayout()222     public void hideCustomLayout() {
223         mCustomLayout.setVisibility(View.GONE);
224     }
225 
226     /**
227      * Shows custom layout.
228      */
showCustomLayout()229     public void showCustomLayout() {
230         mCustomLayout.setVisibility(View.VISIBLE);
231     }
232 
233     /**
234      * Adds view to custom layout.
235      */
addCustomView(View view)236     public CustomDialogHelper addCustomView(View view) {
237         mCustomLayout.addView(view);
238         return this;
239     }
240 
241     /**
242      * Returns dialog.
243      */
getDialog()244     public Dialog getDialog() {
245         return mDialog;
246     }
247 
248     /**
249      * Sets visibility of layout component.
250      * @param element part of the layout visibility of which is being changed.
251      * @param isVisible true if visibility is set to View.VISIBLE
252      * @return this
253      */
setVisibility(@ayoutComponent int element, boolean isVisible)254     public CustomDialogHelper setVisibility(@LayoutComponent int element, boolean isVisible) {
255         int visibility;
256         if (isVisible) {
257             visibility = View.VISIBLE;
258         } else {
259             visibility = View.GONE;
260         }
261         switch (element) {
262             case ICON:
263                 mDialogIcon.setVisibility(visibility);
264                 break;
265             case TITLE:
266                 mDialogTitle.setVisibility(visibility);
267                 break;
268             case MESSAGE:
269                 mDialogMessage.setVisibility(visibility);
270                 break;
271             case BACK_BUTTON:
272                 mBackButton.setVisibility(visibility);
273                 break;
274             case NEGATIVE_BUTTON:
275                 mNegativeButton.setVisibility(visibility);
276                 break;
277             case POSITIVE_BUTTON:
278                 mPositiveButton.setVisibility(visibility);
279                 break;
280             default:
281                 break;
282         }
283         return this;
284     }
285 }
286