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 
17 package com.android.tv.settings;
18 
19 import android.graphics.drawable.Icon;
20 import android.os.Bundle;
21 import android.text.TextUtils;
22 import android.view.ContextThemeWrapper;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 import android.view.ViewGroup;
26 import android.widget.Button;
27 import android.widget.ImageView;
28 import android.widget.TextView;
29 
30 import androidx.fragment.app.Fragment;
31 
32 /**
33  * Full screen dialog fragment.
34  *
35  * Use {@link DialogBuilder} to set up the arguments to the fragment.
36  * To be used with the {@link R.style#TvSettingsDialog_FullScreen} theme.
37  */
38 public class FullScreenDialogFragment extends Fragment {
39     /** Constant for {@link #onButtonPressed(int)} indicating the positive button was pressed. */
40     public static final int ACTION_POSITIVE = 0;
41     /** Constant for {@link #onButtonPressed(int)} indicating the negative button was pressed. */
42     public static final int ACTION_NEGATIVE = 1;
43 
44     private static final String ARGUMENT_ICON = "ARGUMENT_ICON";
45     private static final String ARGUMENT_TITLE = "ARGUMENT_TITLE";
46     private static final String ARGUMENT_MESSAGE = "ARGUMENT_MESSAGE";
47     private static final String ARGUMENT_HINT_ICON = "ARGUMENT_HINT_ICON";
48     private static final String ARGUMENT_HINT_TEXT = "ARGUMENT_HINT_TEXT";
49     private static final String ARGUMENT_POSITIVE_BUTTON_LABEL = "ARGUMENT_POSITIVE_BUTTON_LABEL";
50     private static final String ARGUMENT_NEGATIVE_BUTTON_LABEL = "ARGUMENT_NEGATIVE_BUTTON_LABEL";
51 
52     /** Builder that sets up arguments to the dialog fragment */
53     public static final class DialogBuilder {
54         private final Bundle mArgs = new Bundle();
55 
56         /** Builder that sets up arguments to the dialog fragment */
DialogBuilder()57         public DialogBuilder() {
58         }
59 
60         /** Sets the icon of the dialog */
setIcon(Icon icon)61         public DialogBuilder setIcon(Icon icon) {
62             mArgs.putParcelable(ARGUMENT_ICON, icon);
63             return this;
64         }
65 
66         /** Sets the title of the dialog */
setTitle(String title)67         public DialogBuilder setTitle(String title) {
68             mArgs.putString(ARGUMENT_TITLE, title);
69             return this;
70         }
71 
72         /** Sets the message of the dialog */
setMessage(String message)73         public DialogBuilder setMessage(String message) {
74             mArgs.putString(ARGUMENT_MESSAGE, message);
75             return this;
76         }
77 
78         /** Sets the hint icon (shown below the message) of the dialog */
setHintIcon(Icon hintIcon)79         public DialogBuilder setHintIcon(Icon hintIcon) {
80             mArgs.putParcelable(ARGUMENT_HINT_ICON, hintIcon);
81             return this;
82         }
83 
84         /** Sets the hint text (shown below the message) of the dialog */
setHintText(String hintText)85         public DialogBuilder setHintText(String hintText) {
86             mArgs.putString(ARGUMENT_HINT_TEXT, hintText);
87             return this;
88         }
89 
90         /** Sets the label of the positive button */
setPositiveButton(String positiveButtonLabel)91         public DialogBuilder setPositiveButton(String positiveButtonLabel) {
92             mArgs.putString(ARGUMENT_POSITIVE_BUTTON_LABEL, positiveButtonLabel);
93             return this;
94         }
95 
96         /** Sets the label of the negative button */
setNegativeButton(String negativeButtonLabel)97         public DialogBuilder setNegativeButton(String negativeButtonLabel) {
98             mArgs.putString(ARGUMENT_NEGATIVE_BUTTON_LABEL, negativeButtonLabel);
99             return this;
100         }
101 
102         /** Returns arguments for the dialog fragment */
build()103         public Bundle build() {
104             return mArgs;
105         }
106     }
107 
108     @Override
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)109     public View onCreateView(LayoutInflater inflater, ViewGroup container,
110             Bundle savedInstanceState) {
111         LayoutInflater themedInflater = inflater.cloneInContext(
112                 new ContextThemeWrapper(inflater.getContext(),
113                         R.style.TvSettingsDialog_FullScreen));
114         View view = themedInflater.inflate(R.layout.full_screen_dialog, container, false);
115 
116         ImageView iconView = view.findViewById(R.id.dialog_icon);
117         TextView titleView = view.findViewById(R.id.dialog_title);
118         TextView messageView = view.findViewById(R.id.dialog_message);
119         ViewGroup customViewContainer = view.findViewById(R.id.custom_view_container);
120         ImageView hintIconView = view.findViewById(R.id.hint_icon);
121         TextView hintTextView = view.findViewById(R.id.hint_text);
122         ViewGroup hintContainerView = view.findViewById(R.id.hint_container);
123         Button positiveButton = view.findViewById(R.id.positive_button);
124         Button negativeButton = view.findViewById(R.id.negative_button);
125 
126         final Bundle args = getArguments();
127         final Icon icon = args.getParcelable(ARGUMENT_ICON, Icon.class);
128         if (icon != null) {
129             iconView.setVisibility(View.VISIBLE);
130             iconView.setImageIcon(icon);
131         }
132 
133         titleView.setText(args.getString(ARGUMENT_TITLE));
134         CharSequence message = getMessage();
135         if (!TextUtils.isEmpty(message)) {
136             messageView.setText(message);
137         } else {
138             messageView.setVisibility(View.GONE);
139         }
140 
141         View customView = createCustomView(customViewContainer);
142         if (customView != null) {
143             customViewContainer.addView(customView);
144         } else {
145             customViewContainer.setVisibility(View.GONE);
146         }
147 
148         final Icon hintIcon = args.getParcelable(ARGUMENT_HINT_ICON, Icon.class);
149         final String hintText = args.getString(ARGUMENT_HINT_TEXT);
150         final boolean hasHint = !TextUtils.isEmpty(hintText);
151         hintContainerView.setVisibility(hasHint ? View.VISIBLE : View.GONE);
152         if (hasHint) {
153             hintTextView.setText(hintText);
154             if (hintIcon != null) {
155                 hintIconView.setVisibility(View.VISIBLE);
156                 hintIconView.setImageIcon(hintIcon);
157             }
158         }
159 
160         final String positiveButtonLabel = args.getString(ARGUMENT_POSITIVE_BUTTON_LABEL);
161         positiveButton.setVisibility(
162                 TextUtils.isEmpty(positiveButtonLabel) ? View.GONE : View.VISIBLE);
163         positiveButton.setText(positiveButtonLabel);
164         positiveButton.setOnClickListener((v) -> onButtonPressed(ACTION_POSITIVE));
165 
166         final String negativeButtonLabel = args.getString(ARGUMENT_NEGATIVE_BUTTON_LABEL);
167         negativeButton.setVisibility(
168                 TextUtils.isEmpty(negativeButtonLabel) ? View.GONE : View.VISIBLE);
169         negativeButton.setText(negativeButtonLabel);
170         negativeButton.setOnClickListener((v) -> onButtonPressed(ACTION_NEGATIVE));
171 
172 
173         return view;
174     }
175 
176     /** Returns the dialog message. */
getMessage()177     public CharSequence getMessage() {
178         return getArguments().getString(ARGUMENT_MESSAGE);
179     }
180 
181     /** Returns the custom view (shown below the message) */
createCustomView(ViewGroup parent)182     public View createCustomView(ViewGroup parent) {
183         return null;
184     }
185 
186     /**
187      * Called when a dialog button was pressed.
188      *
189      * @param action Indicates which button was pressed
190      * @see #ACTION_POSITIVE
191      * @see #ACTION_NEGATIVE
192      */
onButtonPressed(int action)193     public void onButtonPressed(int action) {
194     }
195 }
196