1/*
2 * Copyright (C) 2015 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 android.support.v14.preference;
18
19import android.app.AlertDialog;
20import android.content.DialogInterface;
21import android.os.Bundle;
22import android.support.annotation.NonNull;
23
24import java.util.ArrayList;
25import java.util.HashSet;
26import java.util.Set;
27
28public class MultiSelectListPreferenceDialogFragment extends PreferenceDialogFragment {
29
30    private static final String SAVE_STATE_VALUES =
31            "MultiSelectListPreferenceDialogFragment.values";
32    private static final String SAVE_STATE_CHANGED =
33            "MultiSelectListPreferenceDialogFragment.changed";
34    private static final String SAVE_STATE_ENTRIES =
35            "MultiSelectListPreferenceDialogFragment.entries";
36    private static final String SAVE_STATE_ENTRY_VALUES =
37            "MultiSelectListPreferenceDialogFragment.entryValues";
38
39    private Set<String> mNewValues = new HashSet<>();
40    private boolean mPreferenceChanged;
41    private CharSequence[] mEntries;
42    private CharSequence[] mEntryValues;
43
44    public static MultiSelectListPreferenceDialogFragment newInstance(String key) {
45        final MultiSelectListPreferenceDialogFragment fragment =
46                new MultiSelectListPreferenceDialogFragment();
47        final Bundle b = new Bundle(1);
48        b.putString(ARG_KEY, key);
49        fragment.setArguments(b);
50        return fragment;
51    }
52
53    @Override
54    public void onCreate(Bundle savedInstanceState) {
55        super.onCreate(savedInstanceState);
56
57        if (savedInstanceState == null) {
58            final MultiSelectListPreference preference = getListPreference();
59
60            if (preference.getEntries() == null || preference.getEntryValues() == null) {
61                throw new IllegalStateException(
62                        "MultiSelectListPreference requires an entries array and " +
63                                "an entryValues array.");
64            }
65
66            mNewValues.clear();
67            mNewValues.addAll(preference.getValues());
68            mPreferenceChanged = false;
69            mEntries = preference.getEntries();
70            mEntryValues = preference.getEntryValues();
71        } else {
72            mNewValues.clear();
73            mNewValues.addAll(savedInstanceState.getStringArrayList(SAVE_STATE_VALUES));
74            mPreferenceChanged = savedInstanceState.getBoolean(SAVE_STATE_CHANGED, false);
75            mEntries = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRIES);
76            mEntryValues = savedInstanceState.getCharSequenceArray(SAVE_STATE_ENTRY_VALUES);
77        }
78    }
79
80    @Override
81    public void onSaveInstanceState(@NonNull Bundle outState) {
82        super.onSaveInstanceState(outState);
83        outState.putStringArrayList(SAVE_STATE_VALUES, new ArrayList<>(mNewValues));
84        outState.putBoolean(SAVE_STATE_CHANGED, mPreferenceChanged);
85        outState.putCharSequenceArray(SAVE_STATE_ENTRIES, mEntries);
86        outState.putCharSequenceArray(SAVE_STATE_ENTRY_VALUES, mEntryValues);
87    }
88
89    private MultiSelectListPreference getListPreference() {
90        return (MultiSelectListPreference) getPreference();
91    }
92
93    @Override
94    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
95        super.onPrepareDialogBuilder(builder);
96
97        final int entryCount = mEntryValues.length;
98        final boolean[] checkedItems = new boolean[entryCount];
99        for (int i = 0; i < entryCount; i++) {
100            checkedItems[i] = mNewValues.contains(mEntryValues[i].toString());
101        }
102        builder.setMultiChoiceItems(mEntries, checkedItems,
103                new DialogInterface.OnMultiChoiceClickListener() {
104                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {
105                        if (isChecked) {
106                            mPreferenceChanged |= mNewValues.add(
107                                    mEntryValues[which].toString());
108                        } else {
109                            mPreferenceChanged |= mNewValues.remove(
110                                    mEntryValues[which].toString());
111                        }
112                    }
113                });
114    }
115
116    @Override
117    public void onDialogClosed(boolean positiveResult) {
118        final MultiSelectListPreference preference = getListPreference();
119        if (positiveResult && mPreferenceChanged) {
120            final Set<String> values = mNewValues;
121            if (preference.callChangeListener(values)) {
122                preference.setValues(values);
123            }
124        }
125        mPreferenceChanged = false;
126    }
127
128}
129