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