blob: ddffc904112254309dd0ad6f9109e0f4b00f5f90 [file] [log] [blame]
Heemin Seogbe66bca2019-04-10 15:49:33 -07001/*
2 * Copyright (C) 2019 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.car.developeroptions;
18
19import android.app.Dialog;
20import android.app.settings.SettingsEnums;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.content.DialogInterface.OnClickListener;
24import android.content.Intent;
25import android.os.Bundle;
26import android.util.AttributeSet;
27
28import androidx.appcompat.app.AlertDialog.Builder;
29import androidx.fragment.app.Fragment;
30import androidx.fragment.app.FragmentTransaction;
31import androidx.preference.ListPreference;
32import androidx.preference.ListPreferenceDialogFragmentCompat;
33
34import com.android.car.developeroptions.core.instrumentation.InstrumentedDialogFragment;
35
36public class CustomListPreference extends ListPreference {
37
38 public CustomListPreference(Context context, AttributeSet attrs) {
39 super(context, attrs);
40 }
41
42 public CustomListPreference(Context context, AttributeSet attrs, int defStyleAttr,
43 int defStyleRes) {
44 super(context, attrs, defStyleAttr, defStyleRes);
45 }
46
47 protected void onPrepareDialogBuilder(Builder builder,
48 DialogInterface.OnClickListener listener) {
49 }
50
51 protected void onDialogClosed(boolean positiveResult) {
52 }
53
54 protected void onDialogCreated(Dialog dialog) {
55 }
56
57 protected boolean isAutoClosePreference() {
58 return true;
59 }
60
61 /**
62 * Called when a user is about to choose the given value, to determine if we
63 * should show a confirmation dialog.
64 *
65 * @param value the value the user is about to choose
66 * @return the message to show in a confirmation dialog, or {@code null} to
67 * not request confirmation
68 */
69 protected CharSequence getConfirmationMessage(String value) {
70 return null;
71 }
72
73 protected void onDialogStateRestored(Dialog dialog, Bundle savedInstanceState) {
74 }
75
76 public static class CustomListPreferenceDialogFragment extends
77 ListPreferenceDialogFragmentCompat {
78
79 private static final java.lang.String KEY_CLICKED_ENTRY_INDEX
80 = "settings.CustomListPrefDialog.KEY_CLICKED_ENTRY_INDEX";
81
82 private int mClickedDialogEntryIndex;
83
84 public static ListPreferenceDialogFragmentCompat newInstance(String key) {
85 final ListPreferenceDialogFragmentCompat fragment =
86 new CustomListPreferenceDialogFragment();
87 final Bundle b = new Bundle(1);
88 b.putString(ARG_KEY, key);
89 fragment.setArguments(b);
90 return fragment;
91 }
92
93 private CustomListPreference getCustomizablePreference() {
94 return (CustomListPreference) getPreference();
95 }
96
97 @Override
98 protected void onPrepareDialogBuilder(Builder builder) {
99 super.onPrepareDialogBuilder(builder);
100 mClickedDialogEntryIndex = getCustomizablePreference()
101 .findIndexOfValue(getCustomizablePreference().getValue());
102 getCustomizablePreference().onPrepareDialogBuilder(builder, getOnItemClickListener());
103 if (!getCustomizablePreference().isAutoClosePreference()) {
104 builder.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
105 @Override
106 public void onClick(DialogInterface dialog, int which) {
107 onItemChosen();
108 }
109 });
110 }
111 }
112
113 @Override
114 public Dialog onCreateDialog(Bundle savedInstanceState) {
115 Dialog dialog = super.onCreateDialog(savedInstanceState);
116 if (savedInstanceState != null) {
117 mClickedDialogEntryIndex = savedInstanceState.getInt(KEY_CLICKED_ENTRY_INDEX,
118 mClickedDialogEntryIndex);
119 }
120 getCustomizablePreference().onDialogCreated(dialog);
121 return dialog;
122 }
123
124 @Override
125 public void onSaveInstanceState(Bundle outState) {
126 super.onSaveInstanceState(outState);
127 outState.putInt(KEY_CLICKED_ENTRY_INDEX, mClickedDialogEntryIndex);
128 }
129
130 @Override
131 public void onActivityCreated(Bundle savedInstanceState) {
132 super.onActivityCreated(savedInstanceState);
133 getCustomizablePreference().onDialogStateRestored(getDialog(), savedInstanceState);
134 }
135
136 protected DialogInterface.OnClickListener getOnItemClickListener() {
137 return new DialogInterface.OnClickListener() {
138 @Override
139 public void onClick(DialogInterface dialog, int which) {
140 setClickedDialogEntryIndex(which);
141 if (getCustomizablePreference().isAutoClosePreference()) {
142 onItemChosen();
143 }
144 }
145 };
146 }
147
148 protected void setClickedDialogEntryIndex(int which) {
149 mClickedDialogEntryIndex = which;
150 }
151
152 private String getValue() {
153 final ListPreference preference = getCustomizablePreference();
154 if (mClickedDialogEntryIndex >= 0 && preference.getEntryValues() != null) {
155 return preference.getEntryValues()[mClickedDialogEntryIndex].toString();
156 } else {
157 return null;
158 }
159 }
160
161 /**
162 * Called when user has made a concrete item choice, but we might need
163 * to make a quick detour to confirm that choice with a second dialog.
164 */
165 protected void onItemChosen() {
166 final CharSequence message = getCustomizablePreference()
167 .getConfirmationMessage(getValue());
168 if (message != null) {
169 final Fragment f = new ConfirmDialogFragment();
170 final Bundle args = new Bundle();
171 args.putCharSequence(Intent.EXTRA_TEXT, message);
172 f.setArguments(args);
173 f.setTargetFragment(CustomListPreferenceDialogFragment.this, 0);
174 final FragmentTransaction ft = getFragmentManager().beginTransaction();
175 ft.add(f, getTag() + "-Confirm");
176 ft.commitAllowingStateLoss();
177 } else {
178 onItemConfirmed();
179 }
180 }
181
182 /**
183 * Called when user has made a concrete item choice and we've fully
184 * confirmed they want to move forward (if we took a detour above).
185 */
186 protected void onItemConfirmed() {
187 onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);
188 getDialog().dismiss();
189 }
190
191 @Override
192 public void onDialogClosed(boolean positiveResult) {
193 getCustomizablePreference().onDialogClosed(positiveResult);
194 final ListPreference preference = getCustomizablePreference();
195 final String value = getValue();
196 if (positiveResult && value != null) {
197 if (preference.callChangeListener(value)) {
198 preference.setValue(value);
199 }
200 }
201 }
202 }
203
204 public static class ConfirmDialogFragment extends InstrumentedDialogFragment {
205 @Override
206 public Dialog onCreateDialog(Bundle savedInstanceState) {
207 return new Builder(getActivity())
208 .setMessage(getArguments().getCharSequence(Intent.EXTRA_TEXT))
209 .setPositiveButton(android.R.string.ok, new OnClickListener() {
210 @Override
211 public void onClick(DialogInterface dialog, int which) {
212 final Fragment f = getTargetFragment();
213 if (f != null) {
214 ((CustomListPreferenceDialogFragment) f).onItemConfirmed();
215 }
216 }
217 })
218 .setNegativeButton(android.R.string.cancel, null)
219 .create();
220 }
221
222 @Override
223 public int getMetricsCategory() {
224 return SettingsEnums.DIALOG_CUSTOM_LIST_CONFIRMATION;
225 }
226 }
227}