GuidedAction.java revision bc62e0bf64bc727e7fe983ee1ffe07e266f143c8
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14package android.support.v17.leanback.widget;
15
16import android.support.annotation.DrawableRes;
17import android.support.annotation.StringRes;
18import android.support.v17.leanback.R;
19import android.support.v4.content.ContextCompat;
20
21import android.content.Context;
22import android.content.Intent;
23import android.graphics.drawable.Drawable;
24import android.text.InputType;
25
26import java.util.List;
27
28/**
29 * A data class which represents an action within a {@link
30 * android.support.v17.leanback.app.GuidedStepFragment}. GuidedActions contain at minimum a title
31 * and a description, and typically also an icon.
32 * <p>
33 * A GuidedAction typically represents a single action a user may take, but may also represent a
34 * possible choice out of a group of mutually exclusive choices (similar to radio buttons), or an
35 * information-only label (in which case the item cannot be clicked).
36 * <p>
37 * GuidedActions may optionally be checked. They may also indicate that they will request further
38 * user input on selection, in which case they will be displayed with a chevron indicator.
39 * <p>
40 * GuidedAction recommends to use {@link Builder}. When application subclass GuidedAction, it
41 * can subclass {@link BuilderBase}, implement {@link BuilderBase#build()} where it should
42 * call {@link BuilderBase#applyValues(GuidedAction)}.
43 */
44public class GuidedAction extends Action {
45
46    private static final String TAG = "GuidedAction";
47
48    /**
49     * Special check set Id that is neither checkbox nor radio.
50     */
51    public static final int NO_CHECK_SET = 0;
52    /**
53     * Default checkset Id for radio.
54     */
55    public static final int DEFAULT_CHECK_SET_ID = 1;
56    /**
57     * Checkset Id for checkbox.
58     */
59    public static final int CHECKBOX_CHECK_SET_ID = -1;
60
61    /**
62     * When finishing editing, goes to next action.
63     */
64    public static final long ACTION_ID_NEXT = -2;
65    /**
66     * When finishing editing, stay on current action.
67     */
68    public static final long ACTION_ID_CURRENT = -3;
69
70    /**
71     * Id of standard OK action.
72     */
73    public static final long ACTION_ID_OK = -4;
74
75    /**
76     * Id of standard Cancel action.
77     */
78    public static final long ACTION_ID_CANCEL = -5;
79
80    /**
81     * Id of standard Finish action.
82     */
83    public static final long ACTION_ID_FINISH = -6;
84
85    /**
86     * Id of standard Finish action.
87     */
88    public static final long ACTION_ID_CONTINUE = -7;
89
90    /**
91     * Id of standard Yes action.
92     */
93    public static final long ACTION_ID_YES = -8;
94
95    /**
96     * Id of standard No action.
97     */
98    public static final long ACTION_ID_NO = -9;
99
100    /**
101     * Base builder class to build a {@link GuidedAction} object.  When subclass GuidedAction, you
102     * can override this BuilderBase class, implements {@link #build()} and call
103     * {@link #applyValues(GuidedAction)}.  When using GuidedAction directly, use {@link Builder}.
104     */
105    public abstract static class BuilderBase<T extends GuidedAction> {
106        private Context mContext;
107        private long mId;
108        private CharSequence mTitle;
109        private CharSequence mEditTitle;
110        private CharSequence mDescription;
111        private CharSequence mEditDescription;
112        private Drawable mIcon;
113        private boolean mChecked;
114        private boolean mMultilineDescription;
115        private boolean mHasNext;
116        private boolean mInfoOnly;
117        private boolean mEditable = false;
118        private boolean mDescriptionEditable = false;
119        private int mInputType = InputType.TYPE_CLASS_TEXT;
120        private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
121        private int mEditInputType = InputType.TYPE_CLASS_TEXT;
122        private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT;
123        private int mCheckSetId = NO_CHECK_SET;
124        private boolean mEnabled = true;
125        private boolean mFocusable = true;
126        private List<GuidedAction> mSubActions;
127        private Intent mIntent;
128
129        /**
130         * Creates a BuilderBase for GuidedAction or its subclass.
131         * @param context Context object used to build the GuidedAction.
132         */
133        public BuilderBase(Context context) {
134            mContext = context;
135        }
136
137        /**
138         * Returns Context of this Builder.
139         * @return Context of this Builder.
140         */
141        public Context getContext() {
142            return mContext;
143        }
144
145        /**
146         * Builds the GuidedAction corresponding to this Builder.
147         * @return the GuidedAction as configured through this BuilderBase.
148         */
149        public abstract T build();
150
151        /**
152         * Subclass of BuilderBase should call this function to apply values.
153         * @param action GuidedAction to apply BuilderBase values.
154         */
155        protected final void applyValues(GuidedAction action) {
156            // Base Action values
157            action.setId(mId);
158            action.setLabel1(mTitle);
159            action.setEditTitle(mEditTitle);
160            action.setLabel2(mDescription);
161            action.setEditDescription(mEditDescription);
162            action.setIcon(mIcon);
163
164            // Subclass values
165            action.mIntent = mIntent;
166            action.mEditable = mEditable;
167            action.mDescriptionEditable = mDescriptionEditable;
168            action.mInputType = mInputType;
169            action.mDescriptionInputType = mDescriptionInputType;
170            action.mEditInputType = mEditInputType;
171            action.mDescriptionEditInputType = mDescriptionEditInputType;
172            action.mChecked = mChecked;
173            action.mCheckSetId = mCheckSetId;
174            action.mMultilineDescription = mMultilineDescription;
175            action.mHasNext = mHasNext;
176            action.mInfoOnly = mInfoOnly;
177            action.mEnabled = mEnabled;
178            action.mFocusable = mFocusable;
179            action.mSubActions = mSubActions;
180        }
181
182        /**
183         * Construct a clickable action with associated id and auto assign pre-defined title for the
184         * action. If the id is not supported, the method simply does nothing.
185         * @param id One of {@link GuidedAction#ACTION_ID_OK} {@link GuidedAction#ACTION_ID_CANCEL}
186         * {@link GuidedAction#ACTION_ID_FINISH} {@link GuidedAction#ACTION_ID_CONTINUE}
187         * {@link GuidedAction#ACTION_ID_YES} {@link GuidedAction#ACTION_ID_NO}.
188         * @return The same BuilderBase object.
189         */
190        public BuilderBase<T> clickAction(long id) {
191            if (id == ACTION_ID_OK) {
192                mId = ACTION_ID_OK;
193                mTitle = mContext.getString(android.R.string.ok);
194            } else if (id == ACTION_ID_CANCEL) {
195                mId = ACTION_ID_CANCEL;
196                mTitle = mContext.getString(android.R.string.cancel);
197            } else if (id == ACTION_ID_FINISH) {
198                mId = ACTION_ID_FINISH;
199                mTitle = mContext.getString(R.string.lb_guidedaction_finish_title);
200            } else if (id == ACTION_ID_CONTINUE) {
201                mId = ACTION_ID_CONTINUE;
202                mTitle = mContext.getString(R.string.lb_guidedaction_continue_title);
203            } else if (id == ACTION_ID_YES) {
204                mId = ACTION_ID_YES;
205                mTitle = mContext.getString(android.R.string.yes);
206            } else if (id == ACTION_ID_NO) {
207                mId = ACTION_ID_NO;
208                mTitle = mContext.getString(android.R.string.no);
209            }
210            return this;
211        }
212
213        /**
214         * Sets the ID associated with this action.  The ID can be any value the client wishes;
215         * it is typically used to determine what to do when an action is clicked.
216         * @param id The ID to associate with this action.
217         */
218        public BuilderBase<T> id(long id) {
219            mId = id;
220            return this;
221        }
222
223        /**
224         * Sets the title for this action.  The title is typically a short string indicating the
225         * action to be taken on click, e.g. "Continue" or "Cancel".
226         * @param title The title for this action.
227         */
228        public BuilderBase<T> title(CharSequence title) {
229            mTitle = title;
230            return this;
231        }
232
233        /**
234         * Sets the title for this action.  The title is typically a short string indicating the
235         * action to be taken on click, e.g. "Continue" or "Cancel".
236         * @param titleResourceId The resource id of title for this action.
237         */
238        public BuilderBase<T> title(@StringRes int titleResourceId) {
239            mTitle = getContext().getString(titleResourceId);
240            return this;
241        }
242
243        /**
244         * Sets the optional title text to edit.  When TextView is activated, the edit title
245         * replaces the string of title.
246         * @param editTitle The optional title text to edit when TextView is activated.
247         */
248        public BuilderBase<T> editTitle(CharSequence editTitle) {
249            mEditTitle = editTitle;
250            return this;
251        }
252
253        /**
254         * Sets the optional title text to edit.  When TextView is activated, the edit title
255         * replaces the string of title.
256         * @param editTitleResourceId String resource id of the optional title text to edit when
257         * TextView is activated.
258         */
259        public BuilderBase<T> editTitle(@StringRes int editTitleResourceId) {
260            mEditTitle = getContext().getString(editTitleResourceId);
261            return this;
262        }
263
264        /**
265         * Sets the description for this action.  The description is typically a longer string
266         * providing extra information on what the action will do.
267         * @param description The description for this action.
268         */
269        public BuilderBase<T> description(CharSequence description) {
270            mDescription = description;
271            return this;
272        }
273
274        /**
275         * Sets the description for this action.  The description is typically a longer string
276         * providing extra information on what the action will do.
277         * @param descriptionResourceId String resource id of the description for this action.
278         */
279        public BuilderBase<T> description(@StringRes int descriptionResourceId) {
280            mDescription = getContext().getString(descriptionResourceId);
281            return this;
282        }
283
284        /**
285         * Sets the optional description text to edit.  When TextView is activated, the edit
286         * description replaces the string of description.
287         * @param description The description to edit for this action.
288         */
289        public BuilderBase<T> editDescription(CharSequence description) {
290            mEditDescription = description;
291            return this;
292        }
293
294        /**
295         * Sets the optional description text to edit.  When TextView is activated, the edit
296         * description replaces the string of description.
297         * @param descriptionResourceId String resource id of the description to edit for this
298         * action.
299         */
300        public BuilderBase<T> editDescription(@StringRes int descriptionResourceId) {
301            mEditDescription = getContext().getString(descriptionResourceId);
302            return this;
303        }
304
305        /**
306         * Sets the intent associated with this action.  Clients would typically fire this intent
307         * directly when the action is clicked.
308         * @param intent The intent associated with this action.
309         */
310        public BuilderBase<T> intent(Intent intent) {
311            mIntent = intent;
312            return this;
313        }
314
315        /**
316         * Sets the action's icon drawable.
317         * @param icon The drawable for the icon associated with this action.
318         */
319        public BuilderBase<T> icon(Drawable icon) {
320            mIcon = icon;
321            return this;
322        }
323
324        /**
325         * Sets the action's icon drawable by retrieving it by resource ID from the specified
326         * context. This is a convenience function that simply looks up the drawable and calls
327         * {@link #icon(Drawable)}.
328         * @param iconResourceId The resource ID for the icon associated with this action.
329         * @param context The context whose resource ID should be retrieved.
330         * @deprecated Use {@link #icon(int)}.
331         */
332        @Deprecated
333        public BuilderBase<T> iconResourceId(@DrawableRes int iconResourceId, Context context) {
334            return icon(ContextCompat.getDrawable(context, iconResourceId));
335        }
336
337        /**
338         * Sets the action's icon drawable by retrieving it by resource ID from Builder's
339         * context. This is a convenience function that simply looks up the drawable and calls
340         * {@link #icon(Drawable)}.
341         * @param iconResourceId The resource ID for the icon associated with this action.
342         */
343        public BuilderBase<T> icon(@DrawableRes int iconResourceId) {
344            return icon(ContextCompat.getDrawable(getContext(), iconResourceId));
345        }
346
347        /**
348         * Indicates whether this action title is editable. Note: Editable actions cannot also be
349         * checked, or belong to a check set.
350         * @param editable Whether this action is editable.
351         */
352        public BuilderBase<T> editable(boolean editable) {
353            mEditable = editable;
354            if (mChecked || mCheckSetId != NO_CHECK_SET) {
355                throw new IllegalArgumentException("Editable actions cannot also be checked");
356            }
357            return this;
358        }
359
360        /**
361         * Indicates whether this action's description is editable
362         * @param editable Whether this action description is editable.
363         */
364        public BuilderBase<T> descriptionEditable(boolean editable) {
365            mDescriptionEditable = editable;
366            if (mChecked || mCheckSetId != NO_CHECK_SET) {
367                throw new IllegalArgumentException("Editable actions cannot also be checked");
368            }
369            return this;
370        }
371
372        /**
373         * Sets {@link InputType} of this action title not in editing.
374         *
375         * @param inputType InputType for the action title not in editing.
376         */
377        public BuilderBase<T> inputType(int inputType) {
378            mInputType = inputType;
379            return this;
380        }
381
382        /**
383         * Sets {@link InputType} of this action description not in editing.
384         *
385         * @param inputType InputType for the action description not in editing.
386         */
387        public BuilderBase<T> descriptionInputType(int inputType) {
388            mDescriptionInputType = inputType;
389            return this;
390        }
391
392
393        /**
394         * Sets {@link InputType} of this action title in editing.
395         *
396         * @param inputType InputType for the action title in editing.
397         */
398        public BuilderBase<T> editInputType(int inputType) {
399            mEditInputType = inputType;
400            return this;
401        }
402
403        /**
404         * Sets {@link InputType} of this action description in editing.
405         *
406         * @param inputType InputType for the action description in editing.
407         */
408        public BuilderBase<T> descriptionEditInputType(int inputType) {
409            mDescriptionEditInputType = inputType;
410            return this;
411        }
412
413
414        /**
415         * Indicates whether this action is initially checked.
416         * @param checked Whether this action is checked.
417         */
418        public BuilderBase<T> checked(boolean checked) {
419            mChecked = checked;
420            if (mEditable || mDescriptionEditable) {
421                throw new IllegalArgumentException("Editable actions cannot also be checked");
422            }
423            return this;
424        }
425
426        /**
427         * Indicates whether this action is part of a single-select group similar to radio buttons
428         * or this action is a checkbox. When one item in a check set is checked, all others with
429         * the same check set ID will be checked automatically.
430         * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
431         * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
432         */
433        public BuilderBase<T> checkSetId(int checkSetId) {
434            mCheckSetId = checkSetId;
435            if (mEditable || mDescriptionEditable) {
436                throw new IllegalArgumentException("Editable actions cannot also be in check sets");
437            }
438            return this;
439        }
440
441        /**
442         * Indicates whether the title and description are long, and should be displayed
443         * appropriately.
444         * @param multilineDescription Whether this action has a multiline description.
445         */
446        public BuilderBase<T> multilineDescription(boolean multilineDescription) {
447            mMultilineDescription = multilineDescription;
448            return this;
449        }
450
451        /**
452         * Indicates whether this action has a next state and should display a chevron.
453         * @param hasNext Whether this action has a next state.
454         */
455        public BuilderBase<T> hasNext(boolean hasNext) {
456            mHasNext = hasNext;
457            return this;
458        }
459
460        /**
461         * Indicates whether this action is for information purposes only and cannot be clicked.
462         * @param infoOnly Whether this action has a next state.
463         */
464        public BuilderBase<T> infoOnly(boolean infoOnly) {
465            mInfoOnly = infoOnly;
466            return this;
467        }
468
469        /**
470         * Indicates whether this action is enabled.  If not enabled, an action cannot be clicked.
471         * @param enabled Whether the action is enabled.
472         */
473        public BuilderBase<T> enabled(boolean enabled) {
474            mEnabled = enabled;
475            return this;
476        }
477
478        /**
479         * Indicates whether this action can take focus.
480         * @param focusable
481         * @return The same BuilderBase object.
482         */
483        public BuilderBase<T> focusable(boolean focusable) {
484            mFocusable = focusable;
485            return this;
486        }
487
488        /**
489         * Sets sub actions list.
490         * @param subActions
491         * @return The same BuilderBase object.
492         */
493        public BuilderBase<T> subActions(List<GuidedAction> subActions) {
494            mSubActions = subActions;
495            return this;
496        }
497    }
498
499    /**
500     * Builds a {@link GuidedAction} object.
501     */
502    public static class Builder extends BuilderBase<GuidedAction> {
503
504        /**
505         * @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
506         */
507        @Deprecated
508        public Builder() {
509            super(null);
510        }
511
512        /**
513         * Creates a Builder for GuidedAction.
514         * @param context Context to build GuidedAction.
515         */
516        public Builder(Context context) {
517            super(context);
518        }
519
520        @Override
521        public GuidedAction build() {
522            GuidedAction action = new GuidedAction();
523            applyValues(action);
524            return action;
525        }
526
527    }
528
529    private CharSequence mEditTitle;
530    private CharSequence mEditDescription;
531    private boolean mEditable;
532    private boolean mDescriptionEditable;
533    private int mInputType;
534    private int mDescriptionInputType;
535    private int mEditInputType;
536    private int mDescriptionEditInputType;
537    private boolean mMultilineDescription;
538    private boolean mHasNext;
539    private boolean mChecked;
540    private boolean mInfoOnly;
541    private int mCheckSetId;
542    private boolean mEnabled;
543    private boolean mFocusable;
544    private List<GuidedAction> mSubActions;
545
546    private Intent mIntent;
547
548    protected GuidedAction() {
549        super(0);
550    }
551
552    /**
553     * Returns the title of this action.
554     * @return The title set when this action was built.
555     */
556    public CharSequence getTitle() {
557        return getLabel1();
558    }
559
560    /**
561     * Sets the title of this action.
562     * @param title The title set when this action was built.
563     */
564    public void setTitle(CharSequence title) {
565        setLabel1(title);
566    }
567
568    /**
569     * Returns the optional title text to edit.  When not null, it is being edited instead of
570     * {@link #getTitle()}.
571     * @return Optional title text to edit instead of {@link #getTitle()}.
572     */
573    public CharSequence getEditTitle() {
574        return mEditTitle;
575    }
576
577    /**
578     * Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
579     * @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
580     */
581    public void setEditTitle(CharSequence editTitle) {
582        mEditTitle = editTitle;
583    }
584
585    /**
586     * Returns the optional description text to edit.  When not null, it is being edited instead of
587     * {@link #getDescription()}.
588     * @return Optional description text to edit instead of {@link #getDescription()}.
589     */
590    public CharSequence getEditDescription() {
591        return mEditDescription;
592    }
593
594    /**
595     * Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
596     * @param editDescription Optional description text to edit instead of
597     * {@link #setDescription(CharSequence)}.
598     */
599    public void setEditDescription(CharSequence editDescription) {
600        mEditDescription = editDescription;
601    }
602
603    /**
604     * Returns true if {@link #getEditTitle()} is not null.  When true, the {@link #getEditTitle()}
605     * is being edited instead of {@link #getTitle()}.
606     * @return true if {@link #getEditTitle()} is not null.
607     */
608    public boolean isEditTitleUsed() {
609        return mEditTitle != null;
610    }
611
612    /**
613     * Returns the description of this action.
614     * @return The description of this action.
615     */
616    public CharSequence getDescription() {
617        return getLabel2();
618    }
619
620    /**
621     * Sets the description of this action.
622     * @param description The description of the action.
623     */
624    public void setDescription(CharSequence description) {
625        setLabel2(description);
626    }
627
628    /**
629     * Returns the intent associated with this action.
630     * @return The intent set when this action was built.
631     */
632    public Intent getIntent() {
633        return mIntent;
634    }
635
636    /**
637     * Sets the intent of this action.
638     * @param intent New intent to set on this action.
639     */
640    public void setIntent(Intent intent) {
641        mIntent = intent;
642    }
643
644    /**
645     * Returns whether this action title is editable.
646     * @return true if the action title is editable, false otherwise.
647     */
648    public boolean isEditable() {
649        return mEditable;
650    }
651
652    /**
653     * Returns whether this action description is editable.
654     * @return true if the action description is editable, false otherwise.
655     */
656    public boolean isDescriptionEditable() {
657        return mDescriptionEditable;
658    }
659
660    /**
661     * Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
662     * @return InputType of action title in editing.
663     */
664    public int getEditInputType() {
665        return mEditInputType;
666    }
667
668    /**
669     * Returns InputType of action description in editing; only valid when
670     * {@link #isDescriptionEditable()} is true.
671     * @return InputType of action description in editing.
672     */
673    public int getDescriptionEditInputType() {
674        return mDescriptionEditInputType;
675    }
676
677    /**
678     * Returns InputType of action title not in editing.
679     * @return InputType of action title not in editing.
680     */
681    public int getInputType() {
682        return mInputType;
683    }
684
685    /**
686     * Returns InputType of action description not in editing.
687     * @return InputType of action description not in editing.
688     */
689    public int getDescriptionInputType() {
690        return mDescriptionInputType;
691    }
692
693    /**
694     * Returns whether this action is checked.
695     * @return true if the action is currently checked, false otherwise.
696     */
697    public boolean isChecked() {
698        return mChecked;
699    }
700
701    /**
702     * Sets whether this action is checked.
703     * @param checked Whether this action should be checked.
704     */
705    public void setChecked(boolean checked) {
706        mChecked = checked;
707    }
708
709    /**
710     * Returns the check set id this action is a part of. All actions in the same list with the same
711     * check set id are considered linked. When one of the actions within that set is selected, that
712     * action becomes checked, while all the other actions become unchecked.
713     *
714     * @return an integer representing the check set this action is a part of, or
715     *         {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
716     *         this action is not a checkbox or radiobutton.
717     */
718    public int getCheckSetId() {
719        return mCheckSetId;
720    }
721
722    /**
723     * Returns whether this action is has a multiline description.
724     * @return true if the action was constructed as having a multiline description, false
725     * otherwise.
726     */
727    public boolean hasMultilineDescription() {
728        return mMultilineDescription;
729    }
730
731    /**
732     * Returns whether this action is enabled.
733     * @return true if the action is currently enabled, false otherwise.
734     */
735    public boolean isEnabled() {
736        return mEnabled;
737    }
738
739    /**
740     * Sets whether this action is enabled.
741     * @param enabled Whether this action should be enabled.
742     */
743    public void setEnabled(boolean enabled) {
744        mEnabled = enabled;
745    }
746
747    /**
748     * Returns whether this action is focusable.
749     * @return true if the action is currently focusable, false otherwise.
750     */
751    public boolean isFocusable() {
752        return mFocusable;
753    }
754
755    /**
756     * Sets whether this action is focusable.
757     * @param focusable Whether this action should be focusable.
758     */
759    public void setFocusable(boolean focusable) {
760        mFocusable = focusable;
761    }
762
763    /**
764     * Returns whether this action will request further user input when selected, such as showing
765     * another GuidedStepFragment or launching a new activity. Configured during construction.
766     * @return true if the action will request further user input when selected, false otherwise.
767     */
768    public boolean hasNext() {
769        return mHasNext;
770    }
771
772    /**
773     * Returns whether the action will only display information and is thus not clickable. If both
774     * this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For
775     * example, this might represent e.g. the amount of storage a document uses, or the cost of an
776     * app.
777     * @return true if will only display information, false otherwise.
778     */
779    public boolean infoOnly() {
780        return mInfoOnly;
781    }
782
783    /**
784     * Change sub actions list.
785     * @param actions Sub actions list to set on this action.  Sets null to disable sub actions.
786     */
787    public void setSubActions(List<GuidedAction> actions) {
788        mSubActions = actions;
789    }
790
791    /**
792     * @return List of sub actions or null if sub actions list is not enabled.
793     */
794    public List<GuidedAction> getSubActions() {
795        return mSubActions;
796    }
797
798    /**
799     * @return True if has sub actions list, even it's currently empty.
800     */
801    public boolean hasSubActions() {
802        return mSubActions != null;
803    }
804
805}
806