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.settings.common; 18 19 import android.content.Context; 20 import android.content.res.Resources; 21 import android.graphics.drawable.Drawable; 22 import android.text.TextUtils; 23 import android.view.View; 24 import android.widget.ImageView; 25 import android.widget.TextView; 26 import android.widget.Toast; 27 28 import androidx.annotation.DrawableRes; 29 import androidx.annotation.StringRes; 30 import androidx.annotation.VisibleForTesting; 31 32 import com.android.car.settings.R; 33 import com.android.car.ui.utils.CarUiUtils; 34 35 import java.lang.ref.WeakReference; 36 37 /** 38 * Class representing a button item for an {@link ActionButtonsPreference} 39 */ 40 public class ActionButtonInfo { 41 private static final Logger LOG = new Logger(ActionButtonInfo.class); 42 private final Context mContext; 43 private View mButtonView; 44 private ImageView mButtonIconView; 45 private TextView mButtonTextView; 46 private CharSequence mText; 47 private Drawable mIcon; 48 private View.OnClickListener mListener; 49 private boolean mIsPreferenceRestricted = false; 50 private boolean mIsEnabled = true; 51 private boolean mIsVisible = true; 52 private WeakReference<ButtonInfoChangeListener> mButtonInfoChangeListener; 53 private String mMessageToShowWhenUxRestrictedPreferenceClicked; 54 ActionButtonInfo(Context context, ButtonInfoChangeListener changeListener)55 ActionButtonInfo(Context context, ButtonInfoChangeListener changeListener) { 56 mContext = context; 57 mButtonInfoChangeListener = new WeakReference<>(changeListener); 58 mMessageToShowWhenUxRestrictedPreferenceClicked = context.getString( 59 R.string.car_ui_restricted_while_driving); 60 } 61 62 /** 63 * Set the visibility state. 64 */ setVisible(boolean isVisible)65 public ActionButtonInfo setVisible(boolean isVisible) { 66 if (isVisible != mIsVisible) { 67 mIsVisible = isVisible; 68 update(); 69 } 70 return this; 71 } 72 73 /** 74 * Sets the text to be displayed. 75 */ setText(@tringRes int textResId)76 public ActionButtonInfo setText(@StringRes int textResId) { 77 final String newText = mContext.getString(textResId); 78 if (!TextUtils.equals(newText, mText)) { 79 mText = newText; 80 update(); 81 } 82 return this; 83 } 84 85 /** 86 * Sets the drawable to be displayed above of text. 87 */ setIcon(@rawableRes int iconResId)88 public ActionButtonInfo setIcon(@DrawableRes int iconResId) { 89 if (iconResId == 0) { 90 return this; 91 } 92 93 final Drawable icon; 94 try { 95 icon = mContext.getDrawable(iconResId); 96 mIcon = icon; 97 update(); 98 } catch (Resources.NotFoundException exception) { 99 LOG.e("Resource does not exist: " + iconResId); 100 } 101 return this; 102 } 103 104 /** 105 * Set the enabled state. 106 */ setEnabled(boolean isEnabled)107 public ActionButtonInfo setEnabled(boolean isEnabled) { 108 if (isEnabled != mIsEnabled) { 109 mIsEnabled = isEnabled; 110 update(); 111 } 112 return this; 113 } 114 115 /** 116 * Register a callback to be invoked when clicked. 117 */ setOnClickListener( View.OnClickListener listener)118 public ActionButtonInfo setOnClickListener( 119 View.OnClickListener listener) { 120 if (listener != mListener) { 121 mListener = listener; 122 update(); 123 } 124 return this; 125 } 126 setButtonView(View view)127 ActionButtonInfo setButtonView(View view) { 128 mButtonView = view; 129 return this; 130 } 131 setButtonTextView(TextView textView)132 ActionButtonInfo setButtonTextView(TextView textView) { 133 mButtonTextView = textView; 134 return this; 135 } 136 setButtonIconView(ImageView iconView)137 ActionButtonInfo setButtonIconView(ImageView iconView) { 138 mButtonIconView = iconView; 139 return this; 140 } 141 setPreferenceRestricted(boolean isRestricted)142 ActionButtonInfo setPreferenceRestricted(boolean isRestricted) { 143 mIsPreferenceRestricted = isRestricted; 144 return this; 145 } 146 147 /** 148 * Get the current button text. 149 */ 150 @VisibleForTesting getText()151 public CharSequence getText() { 152 return mText; 153 } 154 155 /** 156 * Get the current button icon. 157 */ 158 @VisibleForTesting getIcon()159 public Drawable getIcon() { 160 return mIcon; 161 } 162 163 /** 164 * Get the current button click listener. 165 */ 166 @VisibleForTesting getOnClickListener()167 public View.OnClickListener getOnClickListener() { 168 return mListener; 169 } 170 171 /** 172 * Get the current button enabled state. 173 */ 174 @VisibleForTesting isEnabled()175 public boolean isEnabled() { 176 return mIsEnabled; 177 } 178 179 /** 180 * Get the current button visibility. 181 */ 182 @VisibleForTesting isVisible()183 public boolean isVisible() { 184 return shouldBeVisible(); 185 } 186 setUpButton()187 void setUpButton() { 188 mButtonTextView.setText(mText); 189 mButtonIconView.setImageDrawable(mIcon); 190 mButtonView.setOnClickListener(this::performClick); 191 192 boolean enabled = isEnabled() || mIsPreferenceRestricted; 193 mButtonView.setEnabled(enabled); 194 CarUiUtils.makeAllViewsEnabledAndUxRestricted(mButtonView, isEnabled(), 195 mIsPreferenceRestricted); 196 197 mButtonIconView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE); 198 199 if (shouldBeVisible()) { 200 mButtonView.setVisibility(View.VISIBLE); 201 } else { 202 mButtonView.setVisibility(View.GONE); 203 } 204 } 205 206 @VisibleForTesting performClick(View v)207 void performClick(View v) { 208 if (!isEnabled()) { 209 return; 210 } 211 if (mListener == null) { 212 return; 213 } 214 if (mIsPreferenceRestricted) { 215 if (!TextUtils.isEmpty(mMessageToShowWhenUxRestrictedPreferenceClicked)) { 216 Toast.makeText(mContext, mMessageToShowWhenUxRestrictedPreferenceClicked, 217 Toast.LENGTH_LONG).show(); 218 } 219 return; 220 } 221 mListener.onClick(v); 222 } 223 224 /** 225 * By default, four buttons are visible. 226 * However, there are two cases which button should be invisible. 227 * 228 * 1. User set invisible for this button. ex: mIsVisible = false. 229 * 2. User didn't set any title or icon. 230 */ shouldBeVisible()231 private boolean shouldBeVisible() { 232 return mIsVisible && (!TextUtils.isEmpty(mText) || mIcon != null); 233 } 234 update()235 private void update() { 236 ButtonInfoChangeListener listener = mButtonInfoChangeListener.get(); 237 if (listener != null) { 238 listener.onButtonInfoChange(this); 239 } 240 } 241 242 /** 243 * Listener that is notified when a button has been updated. 244 */ 245 interface ButtonInfoChangeListener { onButtonInfoChange(ActionButtonInfo buttonInfo)246 void onButtonInfoChange(ActionButtonInfo buttonInfo); 247 } 248 } 249