1 /* 2 * Copyright (C) 2020 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.ui.preference; 18 19 import static com.android.car.ui.core.CarUi.MIN_TARGET_API; 20 21 import android.annotation.TargetApi; 22 import android.content.Context; 23 import android.content.res.TypedArray; 24 import android.util.AttributeSet; 25 26 import androidx.annotation.CallSuper; 27 import androidx.annotation.LayoutRes; 28 import androidx.annotation.NonNull; 29 import androidx.annotation.Nullable; 30 import androidx.annotation.StyleableRes; 31 import androidx.preference.Preference; 32 33 import com.android.car.ui.R; 34 35 import java.util.function.Consumer; 36 37 /** 38 * A base class for several types of preferences, that all have a main click action along 39 * with a secondary action. 40 */ 41 @SuppressWarnings("AndroidJdkLibsChecker") 42 @TargetApi(MIN_TARGET_API) 43 public abstract class CarUiTwoActionBasePreference extends CarUiPreference { 44 45 protected boolean mSecondaryActionEnabled = true; 46 protected boolean mSecondaryActionVisible = true; 47 CarUiTwoActionBasePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)48 public CarUiTwoActionBasePreference(Context context, 49 AttributeSet attrs, 50 int defStyleAttr, int defStyleRes) { 51 super(context, attrs, defStyleAttr, defStyleRes); 52 init(attrs); 53 } 54 CarUiTwoActionBasePreference(Context context, AttributeSet attrs, int defStyleAttr)55 public CarUiTwoActionBasePreference(Context context, AttributeSet attrs, int defStyleAttr) { 56 super(context, attrs, defStyleAttr); 57 init(attrs); 58 } 59 CarUiTwoActionBasePreference(Context context, AttributeSet attrs)60 public CarUiTwoActionBasePreference(Context context, AttributeSet attrs) { 61 super(context, attrs); 62 init(attrs); 63 } 64 CarUiTwoActionBasePreference(Context context)65 public CarUiTwoActionBasePreference(Context context) { 66 super(context); 67 init(null); 68 } 69 70 @CallSuper init(@ullable AttributeSet attrs)71 protected void init(@Nullable AttributeSet attrs) { 72 setShowChevron(false); 73 74 TypedArray a = getContext() 75 .obtainStyledAttributes(attrs, R.styleable.CarUiTwoActionBasePreference); 76 try { 77 disallowResourceIds(a, 78 R.styleable.CarUiTwoActionBasePreference_carUiLayout, 79 R.styleable.CarUiTwoActionBasePreference_android_layout, 80 R.styleable.CarUiTwoActionBasePreference_widgetLayout, 81 R.styleable.CarUiTwoActionBasePreference_android_widgetLayout); 82 } finally { 83 a.recycle(); 84 } 85 86 a = getContext().obtainStyledAttributes(attrs, 87 R.styleable.CarUiTwoActionPreference); 88 89 try { 90 mSecondaryActionVisible = a.getBoolean( 91 R.styleable.CarUiTwoActionPreference_actionShown, true); 92 mSecondaryActionEnabled = a.getBoolean( 93 R.styleable.CarUiTwoActionPreference_actionEnabled, true); 94 } finally { 95 a.recycle(); 96 } 97 } 98 99 /** 100 * Returns whether or not the secondary action is enabled. 101 */ isSecondaryActionEnabled()102 public boolean isSecondaryActionEnabled() { 103 return mSecondaryActionEnabled && isEnabled(); 104 } 105 106 /** 107 * Sets whether or not the secondary action is enabled. This is secondary to the overall 108 * {@link #setEnabled(boolean)} of the preference 109 */ setSecondaryActionEnabled(boolean enabled)110 public void setSecondaryActionEnabled(boolean enabled) { 111 mSecondaryActionEnabled = enabled; 112 notifyChanged(); 113 } 114 115 /** 116 * Returns whether or not the secondary action is visible. 117 */ isSecondaryActionVisible()118 public boolean isSecondaryActionVisible() { 119 return mSecondaryActionVisible; 120 } 121 122 /** 123 * Sets whether or not the secondary action is visible. 124 */ setSecondaryActionVisible(boolean visible)125 public void setSecondaryActionVisible(boolean visible) { 126 mSecondaryActionVisible = visible; 127 notifyChanged(); 128 } 129 130 /** 131 * Like {@link #onClick()}, but for the secondary action. 132 */ performSecondaryActionClick()133 public void performSecondaryActionClick() { 134 if (isSecondaryActionEnabled()) { 135 if (isUxRestricted()) { 136 Consumer<Preference> restrictedListener = getOnClickWhileRestrictedListener(); 137 if (restrictedListener != null) { 138 restrictedListener.accept(this); 139 } 140 } else { 141 performSecondaryActionClickInternal(); 142 } 143 } else if (isClickableWhileDisabled()) { 144 if (getDisabledClickListener() != null) { 145 getDisabledClickListener().accept(this); 146 } 147 } 148 } 149 performSecondaryActionClickInternal()150 protected abstract void performSecondaryActionClickInternal(); 151 setLayoutResourceInternal(@ayoutRes int layoutResId)152 protected void setLayoutResourceInternal(@LayoutRes int layoutResId) { 153 super.setLayoutResource(layoutResId); 154 } 155 156 @Override setLayoutResource(@ayoutRes int layoutResId)157 public void setLayoutResource(@LayoutRes int layoutResId) { 158 throw new UnsupportedOperationException(); 159 } 160 161 @Override setWidgetLayoutResource(@ayoutRes int widgetLayoutResId)162 public void setWidgetLayoutResource(@LayoutRes int widgetLayoutResId) { 163 throw new UnsupportedOperationException(); 164 } 165 disallowResourceIds(@onNull TypedArray a, @StyleableRes int ...indices)166 private static void disallowResourceIds(@NonNull TypedArray a, @StyleableRes int ...indices) { 167 for (int index : indices) { 168 if (a.hasValue(index)) { 169 throw new AssertionError("Setting this attribute is not allowed: " 170 + a.getResources().getResourceName(index)); 171 } 172 } 173 } 174 } 175