blob: 21986d51e02eb28ee3b83fffc47c56672aff2cb6 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package android.support.v17.leanback.widget;
import android.support.v17.leanback.R;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.text.InputType;
import android.util.Log;
/**
* A data class which represents an action within a {@link
* android.support.v17.leanback.app.GuidedStepFragment}. GuidedActions contain at minimum a title
* and a description, and typically also an icon.
* <p>
* A GuidedAction typically represents a single action a user may take, but may also represent a
* possible choice out of a group of mutually exclusive choices (similar to radio buttons), or an
* information-only label (in which case the item cannot be clicked).
* <p>
* GuidedActions may optionally be checked. They may also indicate that they will request further
* user input on selection, in which case they will be displayed with a chevron indicator.
*/
public class GuidedAction extends Action {
private static final String TAG = "GuidedAction";
/**
* Special check set Id that is neither checkbox nor radio.
*/
public static final int NO_CHECK_SET = 0;
/**
* Default checkset Id for radio.
*/
public static final int DEFAULT_CHECK_SET_ID = 1;
/**
* Checkset Id for checkbox.
*/
public static final int CHECKBOX_CHECK_SET_ID = -1;
/**
* When finishing editing, goes to next action.
*/
public static final long ACTION_ID_NEXT = -2;
/**
* When finishing editing, stay on current action.
*/
public static final long ACTION_ID_CURRENT = -3;
/**
* Id of standard OK action.
*/
public static final long ACTION_ID_OK = -4;
/**
* Id of standard Cancel action.
*/
public static final long ACTION_ID_CANCEL = -5;
/**
* Id of standard Finish action.
*/
public static final long ACTION_ID_FINISH = -6;
/**
* Id of standard Finish action.
*/
public static final long ACTION_ID_CONTINUE = -7;
/**
* Id of standard Yes action.
*/
public static final long ACTION_ID_YES = -8;
/**
* Id of standard No action.
*/
public static final long ACTION_ID_NO = -9;
/**
* Builds a {@link GuidedAction} object. When subclass GuidedAction, you may override this
* Builder class and call {@link #applyValues(GuidedAction)}.
*/
public static class Builder {
private long mId;
private CharSequence mTitle;
private CharSequence mEditTitle;
private CharSequence mDescription;
private CharSequence mEditDescription;
private Drawable mIcon;
private boolean mChecked;
private boolean mMultilineDescription;
private boolean mHasNext;
private boolean mInfoOnly;
private boolean mEditable = false;
private boolean mDescriptionEditable = false;
private int mInputType = InputType.TYPE_CLASS_TEXT;
private int mDescriptionInputType = InputType.TYPE_CLASS_TEXT;
private int mEditInputType = InputType.TYPE_CLASS_TEXT;
private int mDescriptionEditInputType = InputType.TYPE_CLASS_TEXT;
private int mCheckSetId = NO_CHECK_SET;
private boolean mEnabled = true;
private boolean mFocusable = true;
private Intent mIntent;
/**
* Builds the GuidedAction corresponding to this Builder.
* @return the GuidedAction as configured through this Builder.
*/
public final GuidedAction build() {
GuidedAction action = new GuidedAction();
applyValues(action);
return action;
}
/**
* Subclass Builder may call this function to apply values.
* @param action GuidedAction to apply Builder values.
*/
protected final void applyValues(GuidedAction action) {
// Base Action values
action.setId(mId);
action.setLabel1(mTitle);
action.setEditTitle(mEditTitle);
action.setLabel2(mDescription);
action.setEditDescription(mEditDescription);
action.setIcon(mIcon);
// Subclass values
action.mIntent = mIntent;
action.mEditable = mEditable;
action.mDescriptionEditable = mDescriptionEditable;
action.mInputType = mInputType;
action.mDescriptionInputType = mDescriptionInputType;
action.mEditInputType = mEditInputType;
action.mDescriptionEditInputType = mDescriptionEditInputType;
action.mChecked = mChecked;
action.mCheckSetId = mCheckSetId;
action.mMultilineDescription = mMultilineDescription;
action.mHasNext = mHasNext;
action.mInfoOnly = mInfoOnly;
action.mEnabled = mEnabled;
action.mFocusable = mFocusable;
}
/**
* Construct a standard "OK" action with {@link GuidedAction#ACTION_ID_OK}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructOK(Context context) {
mId = ACTION_ID_OK;
mTitle = context.getString(android.R.string.ok);
return this;
}
/**
* Construct a standard "Cancel" action with {@link GuidedAction#ACTION_ID_CANCEL}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructCancel(Context context) {
mId = ACTION_ID_CANCEL;
mTitle = context.getString(android.R.string.cancel);
return this;
}
/**
* Construct a standard "Finish" action with {@link GuidedAction#ACTION_ID_FINISH}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructFinish(Context context) {
mId = ACTION_ID_FINISH;
mTitle = context.getString(R.string.lb_guidedaction_finish_title);
return this;
}
/**
* Construct a standard "Continue" action with {@link GuidedAction#ACTION_ID_CONTINUE}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructContinue(Context context) {
mId = ACTION_ID_CONTINUE;
mHasNext = true;
mTitle = context.getString(R.string.lb_guidedaction_continue_title);
return this;
}
/**
* Construct a standard "Yes" action with {@link GuidedAction#ACTION_ID_YES}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructYes(Context context) {
mId = ACTION_ID_YES;
mTitle = context.getString(android.R.string.yes);
return this;
}
/**
* Construct a standard "No" action with {@link GuidedAction#ACTION_ID_NO}.
* @param context Context for loading action title.
* @return The same Builder object.
*/
public Builder constructNo(Context context) {
mId = ACTION_ID_NO;
mTitle = context.getString(android.R.string.no);
return this;
}
/**
* Sets the ID associated with this action. The ID can be any value the client wishes;
* it is typically used to determine what to do when an action is clicked.
* @param id The ID to associate with this action.
*/
public Builder id(long id) {
mId = id;
return this;
}
/**
* Sets the title for this action. The title is typically a short string indicating the
* action to be taken on click, e.g. "Continue" or "Cancel".
* @param title The title for this action.
*/
public Builder title(CharSequence title) {
mTitle = title;
return this;
}
/**
* Sets the optional title text to edit. When TextView is activated, the edit title
* replaces the string of title.
*/
public Builder editTitle(CharSequence editTitle) {
mEditTitle = editTitle;
return this;
}
/**
* Sets the description for this action. The description is typically a longer string
* providing extra information on what the action will do.
* @param description The description for this action.
*/
public Builder description(CharSequence description) {
mDescription = description;
return this;
}
/**
* Sets the optional description text to edit. When TextView is activated, the edit
* description replaces the string of description.
* @param description The description to edit for this action.
*/
public Builder editDescription(CharSequence description) {
mEditDescription = description;
return this;
}
/**
* Sets the intent associated with this action. Clients would typically fire this intent
* directly when the action is clicked.
* @param intent The intent associated with this action.
*/
public Builder intent(Intent intent) {
mIntent = intent;
return this;
}
/**
* Sets the action's icon drawable.
* @param icon The drawable for the icon associated with this action.
*/
public Builder icon(Drawable icon) {
mIcon = icon;
return this;
}
/**
* Sets the action's icon drawable by retrieving it by resource ID from the specified
* context. This is a convenience function that simply looks up the drawable and calls
* {@link #icon}.
* @param iconResourceId The resource ID for the icon associated with this action.
* @param context The context whose resource ID should be retrieved.
*/
public Builder iconResourceId(int iconResourceId, Context context) {
return icon(context.getResources().getDrawable(iconResourceId));
}
/**
* Indicates whether this action title is editable. Note: Editable actions cannot also be
* checked, or belong to a check set.
* @param editable Whether this action is editable.
*/
public Builder editable(boolean editable) {
mEditable = editable;
if (mChecked || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return this;
}
/**
* Indicates whether this action's description is editable
* @param editable Whether this action description is editable.
*/
public Builder descriptionEditable(boolean editable) {
mDescriptionEditable = editable;
if (mChecked || mCheckSetId != NO_CHECK_SET) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return this;
}
/**
* Sets {@link InputType} of this action title not in editing.
*
* @param inputType InputType for the action title not in editing.
*/
public Builder inputType(int inputType) {
mInputType = inputType;
return this;
}
/**
* Sets {@link InputType} of this action description not in editing.
*
* @param inputType InputType for the action description not in editing.
*/
public Builder descriptionInputType(int inputType) {
mDescriptionInputType = inputType;
return this;
}
/**
* Sets {@link InputType} of this action title in editing.
*
* @param inputType InputType for the action title in editing.
*/
public Builder editInputType(int inputType) {
mEditInputType = inputType;
return this;
}
/**
* Sets {@link InputType} of this action description in editing.
*
* @param inputType InputType for the action description in editing.
*/
public Builder descriptionEditInputType(int inputType) {
mDescriptionEditInputType = inputType;
return this;
}
/**
* Indicates whether this action is initially checked.
* @param checked Whether this action is checked.
*/
public Builder checked(boolean checked) {
mChecked = checked;
if (mEditable || mDescriptionEditable) {
throw new IllegalArgumentException("Editable actions cannot also be checked");
}
return this;
}
/**
* Indicates whether this action is part of a single-select group similar to radio buttons
* or this action is a checkbox. When one item in a check set is checked, all others with
* the same check set ID will be nchecked automatically.
* @param checkSetId The check set ID, or {@link GuidedAction#NO_CHECK_SET} to indicate not
* radio or checkbox, or {@link GuidedAction#CHECKBOX_CHECK_SET_ID} to indicate a checkbox.
*/
public Builder checkSetId(int checkSetId) {
mCheckSetId = checkSetId;
if (mEditable || mDescriptionEditable) {
throw new IllegalArgumentException("Editable actions cannot also be in check sets");
}
return this;
}
/**
* Indicates whether the title and description are long, and should be displayed
* appropriately.
* @param multilineDescription Whether this action has a multiline description.
*/
public Builder multilineDescription(boolean multilineDescription) {
mMultilineDescription = multilineDescription;
return this;
}
/**
* Indicates whether this action has a next state and should display a chevron.
* @param hasNext Whether this action has a next state.
*/
public Builder hasNext(boolean hasNext) {
mHasNext = hasNext;
return this;
}
/**
* Indicates whether this action is for information purposes only and cannot be clicked.
* @param infoOnly Whether this action has a next state.
*/
public Builder infoOnly(boolean infoOnly) {
mInfoOnly = infoOnly;
return this;
}
/**
* Indicates whether this action is enabled. If not enabled, an action cannot be clicked.
* @param enabled Whether the action is enabled.
*/
public Builder enabled(boolean enabled) {
mEnabled = enabled;
return this;
}
/**
* Indicates whether this action can take focus.
* @param focusable
* @return The same Builder object.
*/
public Builder focusable(boolean focusable) {
mFocusable = focusable;
return this;
}
}
private CharSequence mEditTitle;
private CharSequence mEditDescription;
private boolean mEditable;
private boolean mDescriptionEditable;
private int mInputType;
private int mDescriptionInputType;
private int mEditInputType;
private int mDescriptionEditInputType;
private boolean mMultilineDescription;
private boolean mHasNext;
private boolean mChecked;
private boolean mInfoOnly;
private int mCheckSetId;
private boolean mEnabled;
private boolean mFocusable;
private Intent mIntent;
protected GuidedAction() {
super(0);
}
/**
* Returns the title of this action.
* @return The title set when this action was built.
*/
public CharSequence getTitle() {
return getLabel1();
}
/**
* Sets the title of this action.
* @param title The title set when this action was built.
*/
public void setTitle(CharSequence title) {
setLabel1(title);
}
/**
* Returns the optional title text to edit. When not null, it is being edited instead of
* {@link #getTitle()}.
* @return Optional title text to edit instead of {@link #getTitle()}.
*/
public CharSequence getEditTitle() {
return mEditTitle;
}
/**
* Sets the optional title text to edit instead of {@link #setTitle(CharSequence)}.
* @param editTitle Optional title text to edit instead of {@link #setTitle(CharSequence)}.
*/
public void setEditTitle(CharSequence editTitle) {
mEditTitle = editTitle;
}
/**
* Returns the optional description text to edit. When not null, it is being edited instead of
* {@link #getDescription()}.
* @return Optional description text to edit instead of {@link #getDescription()}.
*/
public CharSequence getEditDescription() {
return mEditDescription;
}
/**
* Sets the optional description text to edit instead of {@link #setDescription(CharSequence)}.
* @param editDescription Optional description text to edit instead of
* {@link #setDescription(CharSequence)}.
*/
public void setEditDescription(CharSequence editDescription) {
mEditDescription = editDescription;
}
/**
* Returns true if {@link #getEditTitle()} is not null. When true, the {@link #getEditTitle()}
* is being edited instead of {@link #getTitle()}.
* @return true if {@link #getEditTitle()} is not null.
*/
public boolean isEditTitleUsed() {
return mEditTitle != null;
}
/**
* Returns the description of this action.
* @return The description of this action.
*/
public CharSequence getDescription() {
return getLabel2();
}
/**
* Sets the description of this action.
* @param description The description of the action.
*/
public void setDescription(CharSequence description) {
setLabel2(description);
}
/**
* Returns the intent associated with this action.
* @return The intent set when this action was built.
*/
public Intent getIntent() {
return mIntent;
}
/**
* Returns whether this action title is editable.
* @return true if the action title is editable, false otherwise.
*/
public boolean isEditable() {
return mEditable;
}
/**
* Returns whether this action description is editable.
* @return true if the action description is editable, false otherwise.
*/
public boolean isDescriptionEditable() {
return mDescriptionEditable;
}
/**
* Returns InputType of action title in editing; only valid when {@link #isEditable()} is true.
* @return InputType of action title in editing.
*/
public int getEditInputType() {
return mEditInputType;
}
/**
* Returns InputType of action description in editing; only valid when
* {@link #isDescriptionEditable()} is true.
* @return InputType of action description in editing.
*/
public int getDescriptionEditInputType() {
return mDescriptionEditInputType;
}
/**
* Returns InputType of action title not in editing.
* @return InputType of action title not in editing.
*/
public int getInputType() {
return mInputType;
}
/**
* Returns InputType of action description not in editing.
* @return InputType of action description not in editing.
*/
public int getDescriptionInputType() {
return mDescriptionInputType;
}
/**
* Returns whether this action is checked.
* @return true if the action is currently checked, false otherwise.
*/
public boolean isChecked() {
return mChecked;
}
/**
* Sets whether this action is checked.
* @param checked Whether this action should be checked.
*/
public void setChecked(boolean checked) {
mChecked = checked;
}
/**
* Returns the check set id this action is a part of. All actions in the same list with the same
* check set id are considered linked. When one of the actions within that set is selected, that
* action becomes checked, while all the other actions become unchecked.
*
* @return an integer representing the check set this action is a part of, or
* {@link #CHECKBOX_CHECK_SET_ID} if this is a checkbox, or {@link #NO_CHECK_SET} if
* this action is not a checkbox or radiobutton.
*/
public int getCheckSetId() {
return mCheckSetId;
}
/**
* Returns whether this action is has a multiline description.
* @return true if the action was constructed as having a multiline description, false
* otherwise.
*/
public boolean hasMultilineDescription() {
return mMultilineDescription;
}
/**
* Returns whether this action is enabled.
* @return true if the action is currently enabled, false otherwise.
*/
public boolean isEnabled() {
return mEnabled;
}
/**
* Sets whether this action is enabled.
* @param enabled Whether this action should be enabled.
*/
public void setEnabled(boolean enabled) {
mEnabled = enabled;
}
/**
* Returns whether this action is focusable.
* @return true if the action is currently focusable, false otherwise.
*/
public boolean isFocusable() {
return mFocusable;
}
/**
* Sets whether this action is focusable.
* @param focusable Whether this action should be focusable.
*/
public void setFocusable(boolean focusable) {
mFocusable = focusable;
}
/**
* Returns whether this action will request further user input when selected, such as showing
* another GuidedStepFragment or launching a new activity. Configured during construction.
* @return true if the action will request further user input when selected, false otherwise.
*/
public boolean hasNext() {
return mHasNext;
}
/**
* Returns whether the action will only display information and is thus not clickable. If both
* this and {@link #hasNext()} are true, infoOnly takes precedence. The default is false. For
* example, this might represent e.g. the amount of storage a document uses, or the cost of an
* app.
* @return true if will only display information, false otherwise.
*/
public boolean infoOnly() {
return mInfoOnly;
}
}