GuidedAction.java revision b88b36aa081a500eb0e9d4be0bac85b33cd57dde
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 its own builder() method 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    static final int EDITING_NONE = 0;
101    static final int EDITING_TITLE = 1;
102    static final int EDITING_DESCRIPTION = 2;
103    static final int EDITING_ACTIVATOR_VIEW = 3;
104
105    /**
106     * Base builder class to build a {@link GuidedAction} object.  When subclass GuidedAction, you
107     * can override this BuilderBase class, implements your build() method which should call
108     * {@link #applyValues(GuidedAction)}.  When using GuidedAction directly, use {@link Builder}.
109     */
110    public abstract static class BuilderBase<B extends BuilderBase> {
111        private Context mContext;
112        private long mId;
113        private CharSequence mTitle;
114        private CharSequence mEditTitle;
115        private CharSequence mDescription;
116        private CharSequence mEditDescription;
117        private Drawable mIcon;
118        private boolean mChecked;
119        private boolean mMultilineDescription;
120        private boolean mHasNext;
121        private boolean mInfoOnly;
122        private int mEditable = EDITING_NONE;
123        private int mInputType = InputType.TYPE_CLASS_TEXT;
124        private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
125        private int mEditInputType = InputType.TYPE_CLASS_TEXT;
126        private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT;
127        private int mCheckSetId = NO_CHECK_SET;
128        private boolean mEnabled = true;
129        private boolean mFocusable = true;
130        private List<GuidedAction> mSubActions;
131        private Intent mIntent;
132
133        /**
134         * Creates a BuilderBase for GuidedAction or its subclass.
135         * @param context Context object used to build the GuidedAction.
136         */
137        public BuilderBase(Context context) {
138            mContext = context;
139        }
140
141        /**
142         * Returns Context of this Builder.
143         * @return Context of this Builder.
144         */
145        public Context getContext() {
146            return mContext;
147        }
148
149        /**
150         * Subclass of BuilderBase should call this function to apply values.
151         * @param action GuidedAction to apply BuilderBase values.
152         */
153        protected final void applyValues(GuidedAction action) {
154            // Base Action values
155            action.setId(mId);
156            action.setLabel1(mTitle);
157            action.setEditTitle(mEditTitle);
158            action.setLabel2(mDescription);
159            action.setEditDescription(mEditDescription);
160            action.setIcon(mIcon);
161
162            // Subclass values
163            action.mIntent = mIntent;
164            action.mEditable = mEditable;
165            action.mInputType = mInputType;
166            action.mDescriptionInputType = mDescriptionInputType;
167            action.mEditInputType = mEditInputType;
168            action.mDescriptionEditInputType = mDescriptionEditInputType;
169            action.mChecked = mChecked;
170            action.mCheckSetId = mCheckSetId;
171            action.mMultilineDescription = mMultilineDescription;
172            action.mHasNext = mHasNext;
173            action.mInfoOnly = mInfoOnly;
174            action.mEnabled = mEnabled;
175            action.mFocusable = mFocusable;
176            action.mSubActions = mSubActions;
177        }
178
179        /**
180         * Construct a clickable action with associated id and auto assign pre-defined title for the
181         * action. If the id is not supported, the method simply does nothing.
182         * @param id One of {@link GuidedAction#ACTION_ID_OK} {@link GuidedAction#ACTION_ID_CANCEL}
183         * {@link GuidedAction#ACTION_ID_FINISH} {@link GuidedAction#ACTION_ID_CONTINUE}
184         * {@link GuidedAction#ACTION_ID_YES} {@link GuidedAction#ACTION_ID_NO}.
185         * @return The same BuilderBase object.
186         */
187        public B clickAction(long id) {
188            if (id == ACTION_ID_OK) {
189                mId = ACTION_ID_OK;
190                mTitle = mContext.getString(android.R.string.ok);
191            } else if (id == ACTION_ID_CANCEL) {
192                mId = ACTION_ID_CANCEL;
193                mTitle = mContext.getString(android.R.string.cancel);
194            } else if (id == ACTION_ID_FINISH) {
195                mId = ACTION_ID_FINISH;
196                mTitle = mContext.getString(R.string.lb_guidedaction_finish_title);
197            } else if (id == ACTION_ID_CONTINUE) {
198                mId = ACTION_ID_CONTINUE;
199                mTitle = mContext.getString(R.string.lb_guidedaction_continue_title);
200            } else if (id == ACTION_ID_YES) {
201                mId = ACTION_ID_YES;
202                mTitle = mContext.getString(android.R.string.yes);
203            } else if (id == ACTION_ID_NO) {
204                mId = ACTION_ID_NO;
205                mTitle = mContext.getString(android.R.string.no);
206            }
207            return (B) this;
208        }
209
210        /**
211         * Sets the ID associated with this action.  The ID can be any value the client wishes;
212         * it is typically used to determine what to do when an action is clicked.
213         * @param id The ID to associate with this action.
214         */
215        public B id(long id) {
216            mId = id;
217            return (B) this;
218        }
219
220        /**
221         * Sets the title for this action.  The title is typically a short string indicating the
222         * action to be taken on click, e.g. "Continue" or "Cancel".
223         * @param title The title for this action.
224         */
225        public B title(CharSequence title) {
226            mTitle = title;
227            return (B) this;
228        }
229
230        /**
231         * Sets the title for this action.  The title is typically a short string indicating the
232         * action to be taken on click, e.g. "Continue" or "Cancel".
233         * @param titleResourceId The resource id of title for this action.
234         */
235        public B title(@StringRes int titleResourceId) {
236            mTitle = getContext().getString(titleResourceId);
237            return (B) this;
238        }
239
240        /**
241         * Sets the optional title text to edit.  When TextView is activated, the edit title
242         * replaces the string of title.
243         * @param editTitle The optional title text to edit when TextView is activated.
244         */
245        public B editTitle(CharSequence editTitle) {
246            mEditTitle = editTitle;
247            return (B) this;
248        }
249
250        /**
251         * Sets the optional title text to edit.  When TextView is activated, the edit title
252         * replaces the string of title.
253         * @param editTitleResourceId String resource id of the optional title text to edit when
254         * TextView is activated.
255         */
256        public B editTitle(@StringRes int editTitleResourceId) {
257            mEditTitle = getContext().getString(editTitleResourceId);
258            return (B) this;
259        }
260
261        /**
262         * Sets the description for this action.  The description is typically a longer string
263         * providing extra information on what the action will do.
264         * @param description The description for this action.
265         */
266        public B description(CharSequence description) {
267            mDescription = description;
268            return (B) this;
269        }
270
271        /**
272         * Sets the description for this action.  The description is typically a longer string
273         * providing extra information on what the action will do.
274         * @param descriptionResourceId String resource id of the description for this action.
275         */
276        public B description(@StringRes int descriptionResourceId) {
277            mDescription = getContext().getString(descriptionResourceId);
278            return (B) this;
279        }
280
281        /**
282         * Sets the optional description text to edit.  When TextView is activated, the edit
283         * description replaces the string of description.
284         * @param description The description to edit for this action.
285         */
286        public B editDescription(CharSequence description) {
287            mEditDescription = description;
288            return (B) this;
289        }
290
291        /**
292         * Sets the optional description text to edit.  When TextView is activated, the edit
293         * description replaces the string of description.
294         * @param descriptionResourceId String resource id of the description to edit for this
295         * action.
296         */
297        public B editDescription(@StringRes int descriptionResourceId) {
298            mEditDescription = getContext().getString(descriptionResourceId);
299            return (B) this;
300        }
301
302        /**
303         * Sets the intent associated with this action.  Clients would typically fire this intent
304         * directly when the action is clicked.
305         * @param intent The intent associated with this action.
306         */
307        public B intent(Intent intent) {
308            mIntent = intent;
309            return (B) this;
310        }
311
312        /**
313         * Sets the action's icon drawable.
314         * @param icon The drawable for the icon associated with this action.
315         */
316        public B icon(Drawable icon) {
317            mIcon = icon;
318            return (B) this;
319        }
320
321        /**
322         * Sets the action's icon drawable by retrieving it by resource ID from the specified
323         * context. This is a convenience function that simply looks up the drawable and calls
324         * {@link #icon(Drawable)}.
325         * @param iconResourceId The resource ID for the icon associated with this action.
326         * @param context The context whose resource ID should be retrieved.
327         * @deprecated Use {@link #icon(int)}.
328         */
329        @Deprecated
330        public B iconResourceId(@DrawableRes int iconResourceId, Context context) {
331            return icon(ContextCompat.getDrawable(context, iconResourceId));
332        }
333
334        /**
335         * Sets the action's icon drawable by retrieving it by resource ID from Builder's
336         * context. This is a convenience function that simply looks up the drawable and calls
337         * {@link #icon(Drawable)}.
338         * @param iconResourceId The resource ID for the icon associated with this action.
339         */
340        public B icon(@DrawableRes int iconResourceId) {
341            return icon(ContextCompat.getDrawable(getContext(), iconResourceId));
342        }
343
344        /**
345         * Indicates whether this action title is editable. Note: Editable actions cannot also be
346         * checked, or belong to a check set.
347         * @param editable Whether this action is editable.
348         */
349        public B editable(boolean editable) {
350            if (!editable && mEditable == EDITING_TITLE) {
351                mEditable = EDITING_NONE;
352                return (B) this;
353            }
354            mEditable = EDITING_TITLE;
355            if (mChecked || mCheckSetId != NO_CHECK_SET) {
356                throw new IllegalArgumentException("Editable actions cannot also be checked");
357            }
358            return (B) this;
359        }
360
361        /**
362         * Indicates whether this action's description is editable
363         * @param editable Whether this action description is editable.
364         */
365        public B descriptionEditable(boolean editable) {
366            if (!editable && mEditable == EDITING_DESCRIPTION) {
367                mEditable = EDITING_NONE;
368                return (B) this;
369            }
370            mEditable = EDITING_DESCRIPTION;
371            if (mChecked || mCheckSetId != NO_CHECK_SET) {
372                throw new IllegalArgumentException("Editable actions cannot also be checked");
373            }
374            return (B) this;
375        }
376
377        /**
378         * Indicates whether this action has a view can be activated to edit, e.g. a DatePicker.
379         * @param editable Whether this action has view can be activated to edit.
380         */
381        public B hasEditableActivatorView(boolean editable) {
382            if (!editable && mEditable == EDITING_ACTIVATOR_VIEW) {
383                mEditable = EDITING_NONE;
384                return (B) this;
385            }
386            mEditable = EDITING_ACTIVATOR_VIEW;
387            if (mChecked || mCheckSetId != NO_CHECK_SET) {
388                throw new IllegalArgumentException("Editable actions cannot also be checked");
389            }
390            return (B) this;
391        }
392
393        /**
394         * Sets {@link InputType} of this action title not in editing.
395         *
396         * @param inputType InputType for the action title not in editing.
397         */
398        public B inputType(int inputType) {
399            mInputType = inputType;
400            return (B) this;
401        }
402
403        /**
404         * Sets {@link InputType} of this action description not in editing.
405         *
406         * @param inputType InputType for the action description not in editing.
407         */
408        public B descriptionInputType(int inputType) {
409            mDescriptionInputType = inputType;
410            return (B) this;
411        }
412
413
414        /**
415         * Sets {@link InputType} of this action title in editing.
416         *
417         * @param inputType InputType for the action title in editing.
418         */
419        public B editInputType(int inputType) {
420            mEditInputType = inputType;
421            return (B) this;
422        }
423
424        /**
425         * Sets {@link InputType} of this action description in editing.
426         *
427         * @param inputType InputType for the action description in editing.
428         */
429        public B descriptionEditInputType(int inputType) {
430            mDescriptionEditInputType = inputType;
431            return (B) this;
432        }
433
434
435        /**
436         * Indicates whether this action is initially checked.
437         * @param checked Whether this action is checked.
438         */
439        public B checked(boolean checked) {
440            mChecked = checked;
441            if (mEditable != EDITING_NONE) {
442                throw new IllegalArgumentException("Editable actions cannot also be checked");
443            }
444            return (B) this;
445        }
446
447        /**
448         * Indicates whether this action is part of a single-select group similar to radio buttons
449         * or this action is a checkbox. When one item in a check set is checked, all others with
450         * the same check set ID will be checked automatically.
451         * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
452         * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
453         */
454        public B checkSetId(int checkSetId) {
455            mCheckSetId = checkSetId;
456            if (mEditable != EDITING_NONE) {
457                throw new IllegalArgumentException("Editable actions cannot also be in check sets");
458            }
459            return (B) this;
460        }
461
462        /**
463         * Indicates whether the title and description are long, and should be displayed
464         * appropriately.
465         * @param multilineDescription Whether this action has a multiline description.
466         */
467        public B multilineDescription(boolean multilineDescription) {
468            mMultilineDescription = multilineDescription;
469            return (B) this;
470        }
471
472        /**
473         * Indicates whether this action has a next state and should display a chevron.
474         * @param hasNext Whether this action has a next state.
475         */
476        public B hasNext(boolean hasNext) {
477            mHasNext = hasNext;
478            return (B) this;
479        }
480
481        /**
482         * Indicates whether this action is for information purposes only and cannot be clicked.
483         * @param infoOnly Whether this action has a next state.
484         */
485        public B infoOnly(boolean infoOnly) {
486            mInfoOnly = infoOnly;
487            return (B) this;
488        }
489
490        /**
491         * Indicates whether this action is enabled.  If not enabled, an action cannot be clicked.
492         * @param enabled Whether the action is enabled.
493         */
494        public B enabled(boolean enabled) {
495            mEnabled = enabled;
496            return (B) this;
497        }
498
499        /**
500         * Indicates whether this action can take focus.
501         * @param focusable
502         * @return The same BuilderBase object.
503         */
504        public B focusable(boolean focusable) {
505            mFocusable = focusable;
506            return (B) this;
507        }
508
509        /**
510         * Sets sub actions list.
511         * @param subActions
512         * @return The same BuilderBase object.
513         */
514        public B subActions(List<GuidedAction> subActions) {
515            mSubActions = subActions;
516            return (B) this;
517        }
518    }
519
520    /**
521     * Builds a {@link GuidedAction} object.
522     */
523    public static class Builder extends BuilderBase<Builder> {
524
525        /**
526         * @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
527         */
528        @Deprecated
529        public Builder() {
530            super(null);
531        }
532
533        /**
534         * Creates a Builder for GuidedAction.
535         * @param context Context to build GuidedAction.
536         */
537        public Builder(Context context) {
538            super(context);
539        }
540
541        /**
542         * Builds the GuidedAction corresponding to this Builder.
543         * @return The GuidedAction as configured through this Builder.
544         */
545        public GuidedAction build() {
546            GuidedAction action = new GuidedAction();
547            applyValues(action);
548            return action;
549        }
550
551    }
552
553    private CharSequence mEditTitle;
554    private CharSequence mEditDescription;
555    private int mEditable;
556    private int mInputType;
557    private int mDescriptionInputType;
558    private int mEditInputType;
559    private int mDescriptionEditInputType;
560    private boolean mMultilineDescription;
561    private boolean mHasNext;
562    private boolean mChecked;
563    private boolean mInfoOnly;
564    private int mCheckSetId;
565    private boolean mEnabled;
566    private boolean mFocusable;
567    private List<GuidedAction> mSubActions;
568
569    private Intent mIntent;
570
571    protected GuidedAction() {
572        super(0);
573    }
574
575    /**
576     * Returns the title of this action.
577     * @return The title set when this action was built.
578     */
579    public CharSequence getTitle() {
580        return getLabel1();
581    }
582
583    /**
584     * Sets the title of this action.
585     * @param title The title set when this action was built.
586     */
587    public void setTitle(CharSequence title) {
588        setLabel1(title);
589    }
590
591    /**
592     * Returns the optional title text to edit.  When not null, it is being edited instead of
593     * {@link #getTitle()}.
594     * @return Optional title text to edit instead of {@link #getTitle()}.
595     */
596    public CharSequence getEditTitle() {
597        return mEditTitle;
598    }
599
600    /**
601     * Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
602     * @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
603     */
604    public void setEditTitle(CharSequence editTitle) {
605        mEditTitle = editTitle;
606    }
607
608    /**
609     * Returns the optional description text to edit.  When not null, it is being edited instead of
610     * {@link #getDescription()}.
611     * @return Optional description text to edit instead of {@link #getDescription()}.
612     */
613    public CharSequence getEditDescription() {
614        return mEditDescription;
615    }
616
617    /**
618     * Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
619     * @param editDescription Optional description text to edit instead of
620     * {@link #setDescription(CharSequence)}.
621     */
622    public void setEditDescription(CharSequence editDescription) {
623        mEditDescription = editDescription;
624    }
625
626    /**
627     * Returns true if {@link #getEditTitle()} is not null.  When true, the {@link #getEditTitle()}
628     * is being edited instead of {@link #getTitle()}.
629     * @return true if {@link #getEditTitle()} is not null.
630     */
631    public boolean isEditTitleUsed() {
632        return mEditTitle != null;
633    }
634
635    /**
636     * Returns the description of this action.
637     * @return The description of this action.
638     */
639    public CharSequence getDescription() {
640        return getLabel2();
641    }
642
643    /**
644     * Sets the description of this action.
645     * @param description The description of the action.
646     */
647    public void setDescription(CharSequence description) {
648        setLabel2(description);
649    }
650
651    /**
652     * Returns the intent associated with this action.
653     * @return The intent set when this action was built.
654     */
655    public Intent getIntent() {
656        return mIntent;
657    }
658
659    /**
660     * Sets the intent of this action.
661     * @param intent New intent to set on this action.
662     */
663    public void setIntent(Intent intent) {
664        mIntent = intent;
665    }
666
667    /**
668     * Returns whether this action has any editable part, e.g. editable title, editable description
669     * or editable activate view.
670     * @return true if this action has any editable part, false otherwise.
671     */
672    public boolean hasAnyEditable() {
673        return mEditable != EDITING_NONE;
674    }
675
676    /**
677     * Returns whether this action title is editable.
678     * @return true if the action title is editable, false otherwise.
679     */
680    public boolean isEditable() {
681        return mEditable == EDITING_TITLE;
682    }
683
684    /**
685     * Returns whether this action description is editable.
686     * @return true if the action description is editable, false otherwise.
687     */
688    public boolean isDescriptionEditable() {
689        return mEditable == EDITING_DESCRIPTION;
690    }
691
692    /**
693     * Returns if this action has editable title or editable description.
694     * @return True if this action has editable title or editable description, false otherwise.
695     */
696    public boolean hasTextEditable() {
697        return mEditable == EDITING_TITLE || mEditable == EDITING_DESCRIPTION;
698    }
699
700    /**
701     * Returns whether this action can be activated to edit, e.g. a DatePicker.
702     * @return true if the action can be activated to edit.
703     */
704    public boolean hasEditableActivatorView() {
705        return mEditable == EDITING_ACTIVATOR_VIEW;
706    }
707
708    /**
709     * Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
710     * @return InputType of action title in editing.
711     */
712    public int getEditInputType() {
713        return mEditInputType;
714    }
715
716    /**
717     * Returns InputType of action description in editing; only valid when
718     * {@link #isDescriptionEditable()} is true.
719     * @return InputType of action description in editing.
720     */
721    public int getDescriptionEditInputType() {
722        return mDescriptionEditInputType;
723    }
724
725    /**
726     * Returns InputType of action title not in editing.
727     * @return InputType of action title not in editing.
728     */
729    public int getInputType() {
730        return mInputType;
731    }
732
733    /**
734     * Returns InputType of action description not in editing.
735     * @return InputType of action description not in editing.
736     */
737    public int getDescriptionInputType() {
738        return mDescriptionInputType;
739    }
740
741    /**
742     * Returns whether this action is checked.
743     * @return true if the action is currently checked, false otherwise.
744     */
745    public boolean isChecked() {
746        return mChecked;
747    }
748
749    /**
750     * Sets whether this action is checked.
751     * @param checked Whether this action should be checked.
752     */
753    public void setChecked(boolean checked) {
754        mChecked = checked;
755    }
756
757    /**
758     * Returns the check set id this action is a part of. All actions in the same list with the same
759     * check set id are considered linked. When one of the actions within that set is selected, that
760     * action becomes checked, while all the other actions become unchecked.
761     *
762     * @return an integer representing the check set this action is a part of, or
763     *         {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
764     *         this action is not a checkbox or radiobutton.
765     */
766    public int getCheckSetId() {
767        return mCheckSetId;
768    }
769
770    /**
771     * Returns whether this action is has a multiline description.
772     * @return true if the action was constructed as having a multiline description, false
773     * otherwise.
774     */
775    public boolean hasMultilineDescription() {
776        return mMultilineDescription;
777    }
778
779    /**
780     * Returns whether this action is enabled.
781     * @return true if the action is currently enabled, false otherwise.
782     */
783    public boolean isEnabled() {
784        return mEnabled;
785    }
786
787    /**
788     * Sets whether this action is enabled.
789     * @param enabled Whether this action should be enabled.
790     */
791    public void setEnabled(boolean enabled) {
792        mEnabled = enabled;
793    }
794
795    /**
796     * Returns whether this action is focusable.
797     * @return true if the action is currently focusable, false otherwise.
798     */
799    public boolean isFocusable() {
800        return mFocusable;
801    }
802
803    /**
804     * Sets whether this action is focusable.
805     * @param focusable Whether this action should be focusable.
806     */
807    public void setFocusable(boolean focusable) {
808        mFocusable = focusable;
809    }
810
811    /**
812     * Returns whether this action will request further user input when selected, such as showing
813     * another GuidedStepFragment or launching a new activity. Configured during construction.
814     * @return true if the action will request further user input when selected, false otherwise.
815     */
816    public boolean hasNext() {
817        return mHasNext;
818    }
819
820    /**
821     * Returns whether the action will only display information and is thus not clickable. If both
822     * this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For
823     * example, this might represent e.g. the amount of storage a document uses, or the cost of an
824     * app.
825     * @return true if will only display information, false otherwise.
826     */
827    public boolean infoOnly() {
828        return mInfoOnly;
829    }
830
831    /**
832     * Change sub actions list.
833     * @param actions Sub actions list to set on this action.  Sets null to disable sub actions.
834     */
835    public void setSubActions(List<GuidedAction> actions) {
836        mSubActions = actions;
837    }
838
839    /**
840     * @return List of sub actions or null if sub actions list is not enabled.
841     */
842    public List<GuidedAction> getSubActions() {
843        return mSubActions;
844    }
845
846    /**
847     * @return True if has sub actions list, even it's currently empty.
848     */
849    public boolean hasSubActions() {
850        return mSubActions != null;
851    }
852
853}
854