1 /*
2  * Copyright 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.ui.recyclerview;
18 
19 import android.graphics.drawable.Drawable;
20 
21 import androidx.annotation.NonNull;
22 import androidx.annotation.Nullable;
23 
24 import com.android.car.ui.CarUiText;
25 
26 import java.util.Collections;
27 import java.util.List;
28 
29 /**
30  * Definition of list items that can be inserted into {@link CarUiListItemAdapter}.
31  */
32 public class CarUiContentListItem extends CarUiListItem {
33 
34     /**
35      * Callback to be invoked when the checked state of a list item changed.
36      */
37     public interface OnCheckedChangeListener {
38         /**
39          * Called when the checked state of a list item has changed.
40          *
41          * @param item      whose checked state changed.
42          * @param isChecked new checked state of list item.
43          */
onCheckedChanged(@onNull CarUiContentListItem item, boolean isChecked)44         void onCheckedChanged(@NonNull CarUiContentListItem item, boolean isChecked);
45     }
46 
47     /**
48      * Callback to be invoked when an item is clicked.
49      */
50     public interface OnClickListener {
51         /**
52          * Called when the item has been clicked.
53          *
54          * @param item whose checked state changed.
55          */
onClick(@onNull CarUiContentListItem item)56         void onClick(@NonNull CarUiContentListItem item);
57     }
58 
59     public enum IconType {
60         /**
61          * For an icon type of CONTENT, the primary icon is a larger than {@code STANDARD}.
62          */
63         CONTENT,
64         /**
65          * For an icon type of STANDARD, the primary icon is the standard size.
66          */
67         STANDARD,
68         /**
69          * For an icon type of AVATAR, the primary icon is masked to provide an icon with a modified
70          * shape.
71          */
72         AVATAR
73     }
74 
75     /**
76      * Enum of secondary action types of a list item.
77      */
78     public enum Action {
79         /**
80          * For an action value of NONE, no action element is shown for a list item.
81          */
82         NONE,
83         /**
84          * For an action value of SWITCH, a switch is shown for the action element of the list
85          * item.
86          */
87         SWITCH,
88         /**
89          * For an action value of CHECK_BOX, a checkbox is shown for the action element of the list
90          * item.
91          */
92         CHECK_BOX,
93         /**
94          * For an action value of RADIO_BUTTON, a radio button is shown for the action element of
95          * the list item.
96          */
97         RADIO_BUTTON,
98         /**
99          * For an action value of ICON, an icon is shown for the action element of the list item.
100          */
101         ICON,
102         /**
103          * For an action value CHEVRON, a chevron is shown for the action element of the list item.
104          */
105         CHEVRON
106     }
107 
108     @Nullable
109     private Drawable mIcon;
110     @Nullable
111     private Drawable mSupplementalIcon;
112     @Nullable
113     private CarUiText mTitle;
114     @Nullable
115     private List<CarUiText> mBody;
116     @NonNull
117     private final Action mAction;
118     @NonNull
119     private IconType mPrimaryIconType;
120     private boolean mIsActionDividerVisible;
121     private boolean mIsChecked;
122     private boolean mIsEnabled = true;
123     private boolean mIsActivated;
124     @Nullable
125     private OnClickListener mOnClickListener;
126     @Nullable
127     private OnCheckedChangeListener mOnCheckedChangeListener;
128     @Nullable
129     private OnClickListener mSupplementalIconOnClickListener;
130     private boolean mIsSecure;
131 
CarUiContentListItem(@onNull Action action)132     public CarUiContentListItem(@NonNull Action action) {
133         mAction = action;
134         mPrimaryIconType = IconType.STANDARD;
135     }
136 
137     /**
138      * Returns the title of the item.
139      */
140     @Nullable
getTitle()141     public CarUiText getTitle() {
142         return mTitle;
143     }
144 
145     /**
146      * Sets the title of the item.
147      *
148      * @param title text to display as title.
149      */
setTitle(@ullable CharSequence title)150     public void setTitle(@Nullable CharSequence title) {
151         mTitle = new CarUiText.Builder(title).build();
152     }
153 
154     /**
155      * Sets the title of the item.
156      *
157      * @param text text to display as title
158      */
setTitle(@ullable CarUiText text)159     public void setTitle(@Nullable CarUiText text) {
160         mTitle = text;
161     }
162 
163     /**
164      * Returns the body of the item.
165      */
166     @Nullable
getBody()167     public List<CarUiText> getBody() {
168         return mBody;
169     }
170 
171     /**
172      * Sets the body of the item.
173      *
174      * @param body text to display as body text.
175      */
setBody(@ullable CharSequence body)176     public void setBody(@Nullable CharSequence body) {
177         if (body == null) {
178             mBody = null;
179             return;
180         }
181 
182         mBody = Collections.singletonList(new CarUiText.Builder(body).build());
183     }
184 
185     /**
186      * Sets the body of the item.
187      *
188      * @param body text to display as body text.
189      */
setBody(@ullable CarUiText body)190     public void setBody(@Nullable CarUiText body) {
191         if (body == null) {
192             mBody = null;
193             return;
194         }
195 
196         mBody = Collections.singletonList(body);
197     }
198 
199     /**
200      * Sets the body of the item.
201      *
202      * @param textList list of text to display as body text. Each {@link CarUiText} in the list will
203      *                 be rendered on a new line, separated by a line break.
204      */
setBody(@ullable List<CarUiText> textList)205     public void setBody(@Nullable List<CarUiText> textList) {
206         mBody = textList;
207     }
208 
209     /**
210      * Returns the icon of the item.
211      */
212     @Nullable
getIcon()213     public Drawable getIcon() {
214         return mIcon;
215     }
216 
217     /**
218      * Sets the icon of the item.
219      *
220      * @param icon the icon to display.
221      */
setIcon(@ullable Drawable icon)222     public void setIcon(@Nullable Drawable icon) {
223         mIcon = icon;
224     }
225 
226     /**
227      * Returns the primary icon type for the item.
228      */
229     @NonNull
getPrimaryIconType()230     public IconType getPrimaryIconType() {
231         return mPrimaryIconType;
232     }
233 
234     /**
235      * Sets the primary icon type for the item.
236      *
237      * @param icon the icon type for the item.
238      */
setPrimaryIconType(@onNull IconType icon)239     public void setPrimaryIconType(@NonNull IconType icon) {
240         mPrimaryIconType = icon;
241     }
242 
243     /**
244      * Returns {@code true} if the item is activated.
245      */
isActivated()246     public boolean isActivated() {
247         return mIsActivated;
248     }
249 
250     /**
251      * Sets the activated state of the item.
252      *
253      * @param activated the activated state for the item.
254      */
setActivated(boolean activated)255     public void setActivated(boolean activated) {
256         mIsActivated = activated;
257     }
258 
259     /**
260      * Returns {@code true} if the item is enabled.
261      */
isEnabled()262     public boolean isEnabled() {
263         return mIsEnabled;
264     }
265 
266     /**
267      * Sets the enabled state of the item.
268      *
269      * @param enabled the enabled state for the item.
270      */
setEnabled(boolean enabled)271     public void setEnabled(boolean enabled) {
272         mIsEnabled = enabled;
273     }
274 
275     /**
276      * Returns {@code true} if the item is checked. Will always return {@code false} when the action
277      * type for the item is {@code Action.NONE}.
278      */
isChecked()279     public boolean isChecked() {
280         return mIsChecked;
281     }
282 
283     /**
284      * Sets the checked state of the item.
285      *
286      * @param checked the checked state for the item.
287      */
setChecked(boolean checked)288     public void setChecked(boolean checked) {
289         if (checked == mIsChecked) {
290             return;
291         }
292 
293         // Checked state can only be set when action type is checkbox, radio button or switch.
294         if (mAction == Action.CHECK_BOX || mAction == Action.SWITCH
295                 || mAction == Action.RADIO_BUTTON) {
296             mIsChecked = checked;
297 
298             if (mOnCheckedChangeListener != null) {
299                 mOnCheckedChangeListener.onCheckedChanged(this, mIsChecked);
300             }
301         }
302     }
303 
304     /**
305      * Sets the visibility of the action divider.
306      *
307      * @param visible visibility of the action divider.
308      */
setActionDividerVisible(boolean visible)309     public void setActionDividerVisible(boolean visible) {
310         mIsActionDividerVisible = visible;
311     }
312 
313     /**
314      * Returns {@code true} if the action divider is visible.
315      */
isActionDividerVisible()316     public boolean isActionDividerVisible() {
317         return mIsActionDividerVisible;
318     }
319 
320     /**
321      * Returns the action type for the item.
322      */
323     @NonNull
getAction()324     public Action getAction() {
325         return mAction;
326     }
327 
328     /**
329      * Returns the supplemental icon for the item.
330      */
331     @Nullable
getSupplementalIcon()332     public Drawable getSupplementalIcon() {
333         if (mAction != Action.ICON) {
334             return null;
335         }
336 
337         return mSupplementalIcon;
338     }
339 
340     /**
341      * Sets supplemental icon to be displayed in a list item.
342      *
343      * @param icon the Drawable to set as the icon, or null to clear the content.
344      */
setSupplementalIcon(@ullable Drawable icon)345     public void setSupplementalIcon(@Nullable Drawable icon) {
346         setSupplementalIcon(icon, null);
347     }
348 
349     /**
350      * Sets supplemental icon to be displayed in a list item.
351      *
352      * @param icon     the Drawable to set as the icon, or null to clear the content.
353      * @param listener the callback that is invoked when the icon is clicked.
354      */
setSupplementalIcon(@ullable Drawable icon, @Nullable OnClickListener listener)355     public void setSupplementalIcon(@Nullable Drawable icon,
356             @Nullable OnClickListener listener) {
357         if (mAction != Action.ICON) {
358             throw new IllegalStateException(
359                     "Cannot set supplemental icon on list item that does not have an action of "
360                             + "type ICON");
361         }
362 
363         mSupplementalIcon = icon;
364         mSupplementalIconOnClickListener = listener;
365     }
366 
367     @Nullable
getSupplementalIconOnClickListener()368     public OnClickListener getSupplementalIconOnClickListener() {
369         return mSupplementalIconOnClickListener;
370     }
371 
372     /**
373      * Registers a callback to be invoked when the item is clicked.
374      *
375      * @param listener callback to be invoked when item is clicked.
376      */
setOnItemClickedListener(@ullable OnClickListener listener)377     public void setOnItemClickedListener(@Nullable OnClickListener listener) {
378         mOnClickListener = listener;
379     }
380 
381     /**
382      * Returns the {@link OnClickListener} registered for this item.
383      */
384     @Nullable
getOnClickListener()385     public OnClickListener getOnClickListener() {
386         return mOnClickListener;
387     }
388 
389     /**
390      * Registers a callback to be invoked when the checked state of list item changes.
391      *
392      * <p>Checked state changes can take place when the action type is {@code Action.SWITCH} or
393      * {@code Action.CHECK_BOX}.
394      *
395      * @param listener callback to be invoked when the checked state shown in the UI changes.
396      */
setOnCheckedChangeListener(@ullable OnCheckedChangeListener listener)397     public void setOnCheckedChangeListener(@Nullable OnCheckedChangeListener listener) {
398         mOnCheckedChangeListener = listener;
399     }
400 
401     /**
402      * Returns the {@link OnCheckedChangeListener} registered for this item.
403      */
404     @Nullable
getOnCheckedChangeListener()405     public OnCheckedChangeListener getOnCheckedChangeListener() {
406         return mOnCheckedChangeListener;
407     }
408 
409     /**
410      * Sets if the list item is secure or not. If it is secure, it won't sent any
411      * click events if there is a full or partial overlay on the screen when
412      * they're clicked.
413      *
414      * @param secure If the list item is secure or not.
415      */
setSecure(boolean secure)416     public void setSecure(boolean secure) {
417         mIsSecure = secure;
418     }
419 
420     /**
421      * Returns if this is a security-sensitive list item or not. See {@link #setSecure}.
422      */
isSecure()423     public boolean isSecure() {
424         return mIsSecure;
425     }
426 }
427