1 /*
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 
17 package com.android.car.settings.common;
18 
19 import android.car.drivingstate.CarUxRestrictions;
20 import android.content.Context;
21 import android.text.TextUtils;
22 
23 import androidx.annotation.NonNull;
24 import androidx.preference.PreferenceGroup;
25 import androidx.preference.TwoStatePreference;
26 
27 import java.util.List;
28 
29 /**
30  * A preference controller which ensure that only one of many {@link TwoStatePreference}
31  * instances can be checked at any given point in time.
32  *
33  * <p>The behavior of this class is not well defined if multiple preferences have the same key.
34  */
35 public abstract class GroupSelectionPreferenceController extends
36         PreferenceController<PreferenceGroup> {
37 
GroupSelectionPreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)38     public GroupSelectionPreferenceController(Context context, String preferenceKey,
39             FragmentController fragmentController, CarUxRestrictions uxRestrictions) {
40         super(context, preferenceKey, fragmentController, uxRestrictions);
41     }
42 
43     @Override
getPreferenceType()44     protected Class<PreferenceGroup> getPreferenceType() {
45         return PreferenceGroup.class;
46     }
47 
48     @Override
updateState(PreferenceGroup preferenceGroup)49     protected final void updateState(PreferenceGroup preferenceGroup) {
50         List<TwoStatePreference> items = getGroupPreferences();
51         preferenceGroup.removeAll();
52         for (TwoStatePreference preference : items) {
53 
54             preference.setOnPreferenceClickListener(pref -> {
55                 if (handleGroupItemSelected(preference)) {
56                     notifyCheckedKeyChanged();
57                 }
58                 return true;
59             });
60             // All changes to the checked state will happen programmatically if using this
61             // class.
62             preference.setOnPreferenceChangeListener((pref, o) -> false);
63             preference.setPersistent(false);
64             preferenceGroup.addPreference(preference);
65         }
66 
67         notifyCheckedKeyChanged();
68     }
69 
70     /** Returns the value of the currently checked key. */
getCurrentCheckedKey()71     protected abstract String getCurrentCheckedKey();
72 
73     /** Returns the list of preferences that should be available to select in this group. */
74     @NonNull
getGroupPreferences()75     protected abstract List<TwoStatePreference> getGroupPreferences();
76 
77     /**
78      * Intercepts a click action on an item in the group. Refreshes the UI immediately if returns
79      * {@code true}. Otherwise {@link #notifyCheckedKeyChanged()} can be used when the selected key
80      * has changed.
81      */
handleGroupItemSelected(TwoStatePreference preference)82     protected boolean handleGroupItemSelected(TwoStatePreference preference) {
83         return true;
84     }
85 
86     /** Refreshes the checked state of the preferences in the {@link PreferenceGroup}. */
notifyCheckedKeyChanged()87     protected void notifyCheckedKeyChanged() {
88         for (int i = 0; i < getPreference().getPreferenceCount(); i++) {
89             TwoStatePreference preference = (TwoStatePreference) getPreference().getPreference(i);
90             preference.setChecked(TextUtils.equals(preference.getKey(), getCurrentCheckedKey()));
91         }
92     }
93 }
94