GuidedAction.java revision 7b93b3baf1195fbd286517556b981e25cb542a40
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) {
351                if (mEditable == EDITING_TITLE) {
352                    mEditable = EDITING_NONE;
353                }
354                return (B) this;
355            }
356            mEditable = EDITING_TITLE;
357            if (mChecked || mCheckSetId != NO_CHECK_SET) {
358                throw new IllegalArgumentException("Editable actions cannot also be checked");
359            }
360            return (B) this;
361        }
362
363        /**
364         * Indicates whether this action's description is editable
365         * @param editable Whether this action description is editable.
366         */
367        public B descriptionEditable(boolean editable) {
368            if (!editable) {
369                if (mEditable == EDITING_DESCRIPTION) {
370                    mEditable = EDITING_NONE;
371                }
372                return (B) this;
373            }
374            mEditable = EDITING_DESCRIPTION;
375            if (mChecked || mCheckSetId != NO_CHECK_SET) {
376                throw new IllegalArgumentException("Editable actions cannot also be checked");
377            }
378            return (B) this;
379        }
380
381        /**
382         * Indicates whether this action has a view can be activated to edit, e.g. a DatePicker.
383         * @param editable Whether this action has view can be activated to edit.
384         */
385        public B hasEditableActivatorView(boolean editable) {
386            if (!editable) {
387                if (mEditable == EDITING_ACTIVATOR_VIEW) {
388                    mEditable = EDITING_NONE;
389                }
390                return (B) this;
391            }
392            mEditable = EDITING_ACTIVATOR_VIEW;
393            if (mChecked || mCheckSetId != NO_CHECK_SET) {
394                throw new IllegalArgumentException("Editable actions cannot also be checked");
395            }
396            return (B) this;
397        }
398
399        /**
400         * Sets {@link InputType} of this action title not in editing.
401         *
402         * @param inputType InputType for the action title not in editing.
403         */
404        public B inputType(int inputType) {
405            mInputType = inputType;
406            return (B) this;
407        }
408
409        /**
410         * Sets {@link InputType} of this action description not in editing.
411         *
412         * @param inputType InputType for the action description not in editing.
413         */
414        public B descriptionInputType(int inputType) {
415            mDescriptionInputType = inputType;
416            return (B) this;
417        }
418
419
420        /**
421         * Sets {@link InputType} of this action title in editing.
422         *
423         * @param inputType InputType for the action title in editing.
424         */
425        public B editInputType(int inputType) {
426            mEditInputType = inputType;
427            return (B) this;
428        }
429
430        /**
431         * Sets {@link InputType} of this action description in editing.
432         *
433         * @param inputType InputType for the action description in editing.
434         */
435        public B descriptionEditInputType(int inputType) {
436            mDescriptionEditInputType = inputType;
437            return (B) this;
438        }
439
440
441        /**
442         * Indicates whether this action is initially checked.
443         * @param checked Whether this action is checked.
444         */
445        public B checked(boolean checked) {
446            mChecked = checked;
447            if (mEditable != EDITING_NONE) {
448                throw new IllegalArgumentException("Editable actions cannot also be checked");
449            }
450            return (B) this;
451        }
452
453        /**
454         * Indicates whether this action is part of a single-select group similar to radio buttons
455         * or this action is a checkbox. When one item in a check set is checked, all others with
456         * the same check set ID will be checked automatically.
457         * @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
458         * radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
459         */
460        public B checkSetId(int checkSetId) {
461            mCheckSetId = checkSetId;
462            if (mEditable != EDITING_NONE) {
463                throw new IllegalArgumentException("Editable actions cannot also be in check sets");
464            }
465            return (B) this;
466        }
467
468        /**
469         * Indicates whether the title and description are long, and should be displayed
470         * appropriately.
471         * @param multilineDescription Whether this action has a multiline description.
472         */
473        public B multilineDescription(boolean multilineDescription) {
474            mMultilineDescription = multilineDescription;
475            return (B) this;
476        }
477
478        /**
479         * Indicates whether this action has a next state and should display a chevron.
480         * @param hasNext Whether this action has a next state.
481         */
482        public B hasNext(boolean hasNext) {
483            mHasNext = hasNext;
484            return (B) this;
485        }
486
487        /**
488         * Indicates whether this action is for information purposes only and cannot be clicked.
489         * @param infoOnly Whether this action has a next state.
490         */
491        public B infoOnly(boolean infoOnly) {
492            mInfoOnly = infoOnly;
493            return (B) this;
494        }
495
496        /**
497         * Indicates whether this action is enabled.  If not enabled, an action cannot be clicked.
498         * @param enabled Whether the action is enabled.
499         */
500        public B enabled(boolean enabled) {
501            mEnabled = enabled;
502            return (B) this;
503        }
504
505        /**
506         * Indicates whether this action can take focus.
507         * @param focusable
508         * @return The same BuilderBase object.
509         */
510        public B focusable(boolean focusable) {
511            mFocusable = focusable;
512            return (B) this;
513        }
514
515        /**
516         * Sets sub actions list.
517         * @param subActions
518         * @return The same BuilderBase object.
519         */
520        public B subActions(List<GuidedAction> subActions) {
521            mSubActions = subActions;
522            return (B) this;
523        }
524    }
525
526    /**
527     * Builds a {@link GuidedAction} object.
528     */
529    public static class Builder extends BuilderBase<Builder> {
530
531        /**
532         * @deprecated Use {@link GuidedAction.Builder#GuidedAction.Builder(Context)}.
533         */
534        @Deprecated
535        public Builder() {
536            super(null);
537        }
538
539        /**
540         * Creates a Builder for GuidedAction.
541         * @param context Context to build GuidedAction.
542         */
543        public Builder(Context context) {
544            super(context);
545        }
546
547        /**
548         * Builds the GuidedAction corresponding to this Builder.
549         * @return The GuidedAction as configured through this Builder.
550         */
551        public GuidedAction build() {
552            GuidedAction action = new GuidedAction();
553            applyValues(action);
554            return action;
555        }
556
557    }
558
559    private CharSequence mEditTitle;
560    private CharSequence mEditDescription;
561    private int mEditable;
562    private int mInputType;
563    private int mDescriptionInputType;
564    private int mEditInputType;
565    private int mDescriptionEditInputType;
566    private boolean mMultilineDescription;
567    private boolean mHasNext;
568    private boolean mChecked;
569    private boolean mInfoOnly;
570    private int mCheckSetId;
571    private boolean mEnabled;
572    private boolean mFocusable;
573    private List<GuidedAction> mSubActions;
574
575    private Intent mIntent;
576
577    protected GuidedAction() {
578        super(0);
579    }
580
581    /**
582     * Returns the title of this action.
583     * @return The title set when this action was built.
584     */
585    public CharSequence getTitle() {
586        return getLabel1();
587    }
588
589    /**
590     * Sets the title of this action.
591     * @param title The title set when this action was built.
592     */
593    public void setTitle(CharSequence title) {
594        setLabel1(title);
595    }
596
597    /**
598     * Returns the optional title text to edit.  When not null, it is being edited instead of
599     * {@link #getTitle()}.
600     * @return Optional title text to edit instead of {@link #getTitle()}.
601     */
602    public CharSequence getEditTitle() {
603        return mEditTitle;
604    }
605
606    /**
607     * Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
608     * @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
609     */
610    public void setEditTitle(CharSequence editTitle) {
611        mEditTitle = editTitle;
612    }
613
614    /**
615     * Returns the optional description text to edit.  When not null, it is being edited instead of
616     * {@link #getDescription()}.
617     * @return Optional description text to edit instead of {@link #getDescription()}.
618     */
619    public CharSequence getEditDescription() {
620        return mEditDescription;
621    }
622
623    /**
624     * Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
625     * @param editDescription Optional description text to edit instead of
626     * {@link #setDescription(CharSequence)}.
627     */
628    public void setEditDescription(CharSequence editDescription) {
629        mEditDescription = editDescription;
630    }
631
632    /**
633     * Returns true if {@link #getEditTitle()} is not null.  When true, the {@link #getEditTitle()}
634     * is being edited instead of {@link #getTitle()}.
635     * @return true if {@link #getEditTitle()} is not null.
636     */
637    public boolean isEditTitleUsed() {
638        return mEditTitle != null;
639    }
640
641    /**
642     * Returns the description of this action.
643     * @return The description of this action.
644     */
645    public CharSequence getDescription() {
646        return getLabel2();
647    }
648
649    /**
650     * Sets the description of this action.
651     * @param description The description of the action.
652     */
653    public void setDescription(CharSequence description) {
654        setLabel2(description);
655    }
656
657    /**
658     * Returns the intent associated with this action.
659     * @return The intent set when this action was built.
660     */
661    public Intent getIntent() {
662        return mIntent;
663    }
664
665    /**
666     * Sets the intent of this action.
667     * @param intent New intent to set on this action.
668     */
669    public void setIntent(Intent intent) {
670        mIntent = intent;
671    }
672
673    /**
674     * Returns whether this action has any editable part, e.g. editable title, editable description
675     * or editable activate view.
676     * @return true if this action has any editable part, false otherwise.
677     */
678    public boolean hasAnyEditable() {
679        return mEditable != EDITING_NONE;
680    }
681
682    /**
683     * Returns whether this action title is editable.
684     * @return true if the action title is editable, false otherwise.
685     */
686    public boolean isEditable() {
687        return mEditable == EDITING_TITLE;
688    }
689
690    /**
691     * Returns whether this action description is editable.
692     * @return true if the action description is editable, false otherwise.
693     */
694    public boolean isDescriptionEditable() {
695        return mEditable == EDITING_DESCRIPTION;
696    }
697
698    /**
699     * Returns if this action has editable title or editable description.
700     * @return True if this action has editable title or editable description, false otherwise.
701     */
702    public boolean hasTextEditable() {
703        return mEditable == EDITING_TITLE || mEditable == EDITING_DESCRIPTION;
704    }
705
706    /**
707     * Returns whether this action can be activated to edit, e.g. a DatePicker.
708     * @return true if the action can be activated to edit.
709     */
710    public boolean hasEditableActivatorView() {
711        return mEditable == EDITING_ACTIVATOR_VIEW;
712    }
713
714    /**
715     * Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
716     * @return InputType of action title in editing.
717     */
718    public int getEditInputType() {
719        return mEditInputType;
720    }
721
722    /**
723     * Returns InputType of action description in editing; only valid when
724     * {@link #isDescriptionEditable()} is true.
725     * @return InputType of action description in editing.
726     */
727    public int getDescriptionEditInputType() {
728        return mDescriptionEditInputType;
729    }
730
731    /**
732     * Returns InputType of action title not in editing.
733     * @return InputType of action title not in editing.
734     */
735    public int getInputType() {
736        return mInputType;
737    }
738
739    /**
740     * Returns InputType of action description not in editing.
741     * @return InputType of action description not in editing.
742     */
743    public int getDescriptionInputType() {
744        return mDescriptionInputType;
745    }
746
747    /**
748     * Returns whether this action is checked.
749     * @return true if the action is currently checked, false otherwise.
750     */
751    public boolean isChecked() {
752        return mChecked;
753    }
754
755    /**
756     * Sets whether this action is checked.
757     * @param checked Whether this action should be checked.
758     */
759    public void setChecked(boolean checked) {
760        mChecked = checked;
761    }
762
763    /**
764     * Returns the check set id this action is a part of. All actions in the same list with the same
765     * check set id are considered linked. When one of the actions within that set is selected, that
766     * action becomes checked, while all the other actions become unchecked.
767     *
768     * @return an integer representing the check set this action is a part of, or
769     *         {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
770     *         this action is not a checkbox or radiobutton.
771     */
772    public int getCheckSetId() {
773        return mCheckSetId;
774    }
775
776    /**
777     * Returns whether this action is has a multiline description.
778     * @return true if the action was constructed as having a multiline description, false
779     * otherwise.
780     */
781    public boolean hasMultilineDescription() {
782        return mMultilineDescription;
783    }
784
785    /**
786     * Returns whether this action is enabled.
787     * @return true if the action is currently enabled, false otherwise.
788     */
789    public boolean isEnabled() {
790        return mEnabled;
791    }
792
793    /**
794     * Sets whether this action is enabled.
795     * @param enabled Whether this action should be enabled.
796     */
797    public void setEnabled(boolean enabled) {
798        mEnabled = enabled;
799    }
800
801    /**
802     * Returns whether this action is focusable.
803     * @return true if the action is currently focusable, false otherwise.
804     */
805    public boolean isFocusable() {
806        return mFocusable;
807    }
808
809    /**
810     * Sets whether this action is focusable.
811     * @param focusable Whether this action should be focusable.
812     */
813    public void setFocusable(boolean focusable) {
814        mFocusable = focusable;
815    }
816
817    /**
818     * Returns whether this action will request further user input when selected, such as showing
819     * another GuidedStepFragment or launching a new activity. Configured during construction.
820     * @return true if the action will request further user input when selected, false otherwise.
821     */
822    public boolean hasNext() {
823        return mHasNext;
824    }
825
826    /**
827     * Returns whether the action will only display information and is thus not clickable. If both
828     * this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For
829     * example, this might represent e.g. the amount of storage a document uses, or the cost of an
830     * app.
831     * @return true if will only display information, false otherwise.
832     */
833    public boolean infoOnly() {
834        return mInfoOnly;
835    }
836
837    /**
838     * Change sub actions list.
839     * @param actions Sub actions list to set on this action.  Sets null to disable sub actions.
840     */
841    public void setSubActions(List<GuidedAction> actions) {
842        mSubActions = actions;
843    }
844
845    /**
846     * @return List of sub actions or null if sub actions list is not enabled.
847     */
848    public List<GuidedAction> getSubActions() {
849        return mSubActions;
850    }
851
852    /**
853     * @return True if has sub actions list, even it's currently empty.
854     */
855    public boolean hasSubActions() {
856        return mSubActions != null;
857    }
858
859}
860