1/*
2 * Copyright 2018 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 androidx.preference;
18
19import android.content.DialogInterface;
20import android.os.Bundle;
21
22import androidx.annotation.NonNull;
23import androidx.appcompat.app.AlertDialog;
24
25public class ListPreferenceDialogFragmentCompat extends PreferenceDialogFragmentCompat {
26
27    private static final String SAVE_STATE_INDEX = "ListPreferenceDialogFragment.index";
28    private static final String SAVE_STATE_ENTRIES = "ListPreferenceDialogFragment.entries";
29    private static final String SAVE_STATE_ENTRY_VALUES =
30            "ListPreferenceDialogFragment.entryValues";
31
32    private int mClickedDialogEntryIndex;
33    private CharSequence[] mEntries;
34    private CharSequence[] mEntryValues;
35
36    public static ListPreferenceDialogFragmentCompat newInstance(String key) {
37        final ListPreferenceDialogFragmentCompat fragment =
38                new ListPreferenceDialogFragmentCompat();
39        final Bundle b = new Bundle(1);
40        b.putString(ARG_KEY, key);
41        fragment.setArguments(b);
42        return fragment;
43    }
44
45    @Override
46    public void onCreate(Bundle savedInstanceState) {
47        super.onCreate(savedInstanceState);
48        if (savedInstanceState == null) {
49            final ListPreference preference = getListPreference();
50
51            if (preference.getEntries() == null || preference.getEntryValues() == null) {
52                throw new IllegalStateException(
53                        "ListPreference requires an entries array and an entryValues array.");
54            }
55
56            mClickedDialogEntryIndex = preference.findIndexOfValue(preference.getValue());
57            mEntries = preference.getEntries();
58            mEntryValues = preference.getEntryValues();
59        } else {
60            mClickedDialogEntryIndex = savedInstanceState.getInt(SAVE_STATE_INDEX, 0);
61            mEntries = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRIES);
62            mEntryValues = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
63        }
64    }
65
66    @Override
67    public void onSaveInstanceState(@NonNull Bundle outState) {
68        super.onSaveInstanceState(outState);
69        outState.putInt(SAVE_STATE_INDEX, mClickedDialogEntryIndex);
70        outState.putCharSequenceArray(SAVE_STATE_ENTRIES, mEntries);
71        outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
72    }
73
74    private ListPreference getListPreference() {
75        return (ListPreference) getPreference();
76    }
77
78    @Override
79    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
80        super.onPrepareDialogBuilder(builder);
81
82        builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex,
83                new DialogInterface.OnClickListener() {
84                    @Override
85                    public void onClick(DialogInterface dialog, int which) {
86                        mClickedDialogEntryIndex = which;
87
88                        /*
89                         * Clicking on an item simulates the positive button
90                         * click, and dismisses the dialog.
91                         */
92                        ListPreferenceDialogFragmentCompat.this.onClick(dialog,
93                                DialogInterface.BUTTON_POSITIVE);
94                        dialog.dismiss();
95                    }
96                });
97
98        /*
99         * The typical interaction for list-based dialogs is to have
100         * click-on-an-item dismiss the dialog instead of the user having to
101         * press 'Ok'.
102         */
103        builder.setPositiveButton(null, null);
104    }
105
106    @Override
107    public void onDialogClosed(boolean positiveResult) {
108        final ListPreference preference = getListPreference();
109        if (positiveResult && mClickedDialogEntryIndex >= 0) {
110            String value = mEntryValues[mClickedDialogEntryIndex].toString();
111            if (preference.callChangeListener(value)) {
112                preference.setValue(value);
113            }
114        }
115    }
116
117}
118