1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tv.settings.dialog.old;
18 
19 import android.content.Context;
20 import android.content.Intent;
21 import android.content.pm.PackageManager;
22 import android.content.res.Resources;
23 import android.graphics.drawable.Drawable;
24 import android.net.Uri;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.Log;
28 
29 import java.util.ArrayList;
30 
31 /**
32  * An action within an {@link ActionAdapter}.
33  */
34 public class Action implements Parcelable {
35 
36     private static final String TAG = "Action";
37 
38     public static final int NO_DRAWABLE = 0;
39     public static final int NO_CHECK_SET = 0;
40     public static final int DEFAULT_CHECK_SET_ID = 1;
41 
42     private final String mKey;
43     private final String mTitle;
44     private final String mDescription;
45     private final Intent mIntent;
46 
47     /**
48      * If not {@code null}, the package name to use to retrieve {{@link #mDrawableResource}.
49      */
50     private final String mResourcePackageName;
51 
52     private final int mDrawableResource;
53     private boolean mChecked;
54     private final boolean mMultilineDescription;
55     private final boolean mHasNext;
56     private final boolean mInfoOnly;
57     private final int mCheckSetId;
58     private boolean mEnabled;
59 
60     /**
61      * Builds a Action object.
62      */
63     public static class Builder {
64         private String mKey;
65         private String mTitle;
66         private String mDescription;
67         private Intent mIntent;
68         private String mResourcePackageName;
69         private int mDrawableResource = NO_DRAWABLE;
70         private boolean mChecked;
71         private boolean mMultilineDescription;
72         private boolean mHasNext;
73         private boolean mInfoOnly;
74         private int mCheckSetId = NO_CHECK_SET;
75         private boolean mEnabled = true;
76 
build()77         public Action build() {
78             return new Action(
79                     mKey,
80                     mTitle,
81                     mDescription,
82                     mResourcePackageName,
83                     mDrawableResource,
84                     mChecked,
85                     mMultilineDescription,
86                     mHasNext,
87                     mInfoOnly,
88                     mIntent,
89                     mCheckSetId,
90                     mEnabled);
91         }
92 
key(String key)93         public Builder key(String key) {
94             mKey = key;
95             return this;
96         }
97 
title(String title)98         public Builder title(String title) {
99             mTitle = title;
100             return this;
101         }
102 
description(String description)103         public Builder description(String description) {
104             mDescription = description;
105             return this;
106         }
107 
intent(Intent intent)108         public Builder intent(Intent intent) {
109             mIntent = intent;
110             return this;
111         }
112 
resourcePackageName(String resourcePackageName)113         public Builder resourcePackageName(String resourcePackageName) {
114             mResourcePackageName = resourcePackageName;
115             return this;
116         }
117 
drawableResource(int drawableResource)118         public Builder drawableResource(int drawableResource) {
119             mDrawableResource = drawableResource;
120             return this;
121         }
122 
checked(boolean checked)123         public Builder checked(boolean checked) {
124             mChecked = checked;
125             return this;
126         }
127 
multilineDescription(boolean multilineDescription)128         public Builder multilineDescription(boolean multilineDescription) {
129             mMultilineDescription = multilineDescription;
130             return this;
131         }
132 
hasNext(boolean hasNext)133         public Builder hasNext(boolean hasNext) {
134             mHasNext = hasNext;
135             return this;
136         }
137 
infoOnly(boolean infoOnly)138         public Builder infoOnly(boolean infoOnly) {
139             mInfoOnly = infoOnly;
140             return this;
141         }
142 
checkSetId(int checkSetId)143         public Builder checkSetId(int checkSetId) {
144             mCheckSetId = checkSetId;
145             return this;
146         }
147 
enabled(boolean enabled)148         public Builder enabled(boolean enabled) {
149             mEnabled = enabled;
150             return this;
151         }
152     }
153 
Action(String key, String title, String description, String resourcePackageName, int drawableResource, boolean checked, boolean multilineDescription, boolean hasNext, boolean infoOnly, Intent intent, int checkSetId, boolean enabled)154     protected Action(String key, String title, String description, String resourcePackageName,
155             int drawableResource, boolean checked, boolean multilineDescription,
156             boolean hasNext, boolean infoOnly, Intent intent, int checkSetId, boolean enabled) {
157         mKey = key;
158         mTitle = title;
159         mDescription = description;
160         mResourcePackageName = resourcePackageName;
161         mDrawableResource = drawableResource;
162         mChecked = checked;
163         mMultilineDescription = multilineDescription;
164         mHasNext = hasNext;
165         mInfoOnly = infoOnly;
166         mIntent = intent;
167         mCheckSetId = checkSetId;
168         mEnabled = enabled;
169     }
170 
171     /**
172      * Returns a list of {@link Action} with the specified keys and titles
173      * matched up.
174      * <p>
175      * The key and title arrays must be of equal length.
176      */
createActionsFromArrays(String[] keys, String[] titles)177     public static ArrayList<Action> createActionsFromArrays(String[] keys, String[] titles) {
178         return createActionsFromArrays(keys, titles, NO_CHECK_SET, null);
179     }
180 
181     /**
182      * Returns a list of {@link Action} with the specified keys and titles
183      * matched up and a given check set ID so that they are related.
184      * <p>
185      * The key and title arrays must be of equal length.
186      */
createActionsFromArrays(String[] keys, String[] titles, int checkSetId, String checkedItemKey)187     public static ArrayList<Action> createActionsFromArrays(String[] keys, String[] titles,
188             int checkSetId, String checkedItemKey) {
189         int keysLength = keys.length;
190         int titlesLength = titles.length;
191 
192         if (keysLength != titlesLength) {
193             throw new IllegalArgumentException("Keys and titles dimensions must match");
194         }
195 
196         ArrayList<Action> actions = new ArrayList<Action>();
197         for (int i = 0; i < keysLength; i++) {
198             Action.Builder builder = new Action.Builder();
199             builder.key(keys[i]).title(titles[i]).checkSetId(checkSetId);
200             if (checkedItemKey != null) {
201                 if (checkedItemKey.equals(keys[i])) {
202                     builder.checked(true);
203                 } else {
204                     builder.checked(false);
205                 }
206             }
207             Action action = builder.build();
208             actions.add(action);
209         }
210         return actions;
211     }
212 
getKey()213     public String getKey() {
214         return mKey;
215     }
216 
getTitle()217     public String getTitle() {
218         return mTitle;
219     }
220 
getDescription()221     public String getDescription() {
222         return mDescription;
223     }
224 
getIntent()225     public Intent getIntent() {
226         return mIntent;
227     }
228 
isChecked()229     public boolean isChecked() {
230         return mChecked;
231     }
232 
getIconUri()233     public Uri getIconUri() {
234         return null;
235     }
236 
237     /**
238      * Returns the check set id this action is a part of.  All actions in the same list with the
239      * same check set id are considered linked.  When one of the actions within that set is selected
240      * that action becomes checked while all the other actions become unchecked.
241      * @return an integer representing the check set this action is a part of or {@NO_CHECK_SET} if
242      * this action isn't a part of a check set.
243      */
getCheckSetId()244     public int getCheckSetId() {
245         return mCheckSetId;
246     }
247 
hasMultilineDescription()248     public boolean hasMultilineDescription() {
249         return mMultilineDescription;
250     }
251 
isEnabled()252     public boolean isEnabled() {
253         return mEnabled;
254     }
255 
setChecked(boolean checked)256     public void setChecked(boolean checked) {
257         mChecked = checked;
258     }
259 
setEnabled(boolean enabled)260     public void setEnabled(boolean enabled) {
261         mEnabled = enabled;
262     }
263 
264     /**
265      * @return true if the action will request further user input when selected
266      *         (such as showing another dialog or launching a new activity).
267      *         False, otherwise.
268      */
hasNext()269     public boolean hasNext() {
270         return mHasNext;
271     }
272 
273     /**
274      * @return true if the action will only display information and is thus unactionable.
275      * If both this and {@link #hasNext()} are true, infoOnly takes precedence. (default is false)
276      * e.g. Play balance, or cost of an app.
277      */
infoOnly()278     public boolean infoOnly() {
279         return mInfoOnly;
280     }
281 
282     /**
283      * Returns an indicator to be drawn. If null is returned, no space for the
284      * indicator will be made.
285      *
286      * @param context the context of the Activity this Action belongs to
287      * @return an indicator to draw or null if no indicator space should exist.
288      */
getIndicator(Context context)289     public Drawable getIndicator(Context context) {
290         if (mDrawableResource == NO_DRAWABLE) {
291             return null;
292         }
293         if (mResourcePackageName == null) {
294             return context.getDrawable(mDrawableResource);
295         }
296         // If we get to here, need to load the resources.
297         Drawable icon = null;
298         try {
299             Context packageContext = context.createPackageContext(mResourcePackageName, 0);
300             icon = packageContext.getDrawable(mDrawableResource);
301         } catch (PackageManager.NameNotFoundException e) {
302             if (Log.isLoggable(TAG, Log.WARN)) {
303                 Log.w(TAG, "No icon for this action.");
304             }
305         } catch (Resources.NotFoundException e) {
306             if (Log.isLoggable(TAG, Log.WARN)) {
307                 Log.w(TAG, "No icon for this action.");
308             }
309         }
310         return icon;
311     }
312 
313     public static Parcelable.Creator<Action> CREATOR = new Parcelable.Creator<Action>() {
314 
315         @Override
316         public Action createFromParcel(Parcel source) {
317 
318             return new Action.Builder()
319                     .key(source.readString())
320                     .title(source.readString())
321                     .description(source.readString())
322                     .intent((Intent) source.readParcelable(Intent.class.getClassLoader()))
323                     .resourcePackageName(source.readString())
324                     .drawableResource(source.readInt())
325                     .checked(source.readInt() != 0)
326                     .multilineDescription(source.readInt() != 0)
327                     .checkSetId(source.readInt())
328                     .build();
329         }
330 
331         @Override
332         public Action[] newArray(int size) {
333             return new Action[size];
334         }
335     };
336 
337     @Override
describeContents()338     public int describeContents() {
339         return 0;
340     }
341 
342     @Override
writeToParcel(Parcel dest, int flags)343     public void writeToParcel(Parcel dest, int flags) {
344         dest.writeString(mKey);
345         dest.writeString(mTitle);
346         dest.writeString(mDescription);
347         dest.writeParcelable(mIntent, flags);
348         dest.writeString(mResourcePackageName);
349         dest.writeInt(mDrawableResource);
350         dest.writeInt(mChecked ? 1 : 0);
351         dest.writeInt(mMultilineDescription ? 1 : 0);
352         dest.writeInt(mCheckSetId);
353     }
354 }
355