1 /*
2  * Copyright (C) 2018 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 package com.android.internal.globalactions;
17 
18 import android.content.Context;
19 import android.util.Log;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.ImageView;
24 import android.widget.TextView;
25 import com.android.internal.R;
26 
27 /**
28  * A toggle action knows whether it is on or off, and displays an icon and status message
29  * accordingly.
30  */
31 public abstract class ToggleAction implements Action {
32     private static final String TAG = "ToggleAction";
33 
34     public enum State {
35         Off(false),
36         TurningOn(true),
37         TurningOff(true),
38         On(false);
39 
40         private final boolean inTransition;
41 
State(boolean intermediate)42         State(boolean intermediate) {
43             inTransition = intermediate;
44         }
45 
inTransition()46         public boolean inTransition() {
47             return inTransition;
48         }
49     }
50 
51     protected State mState = State.Off;
52 
53     // prefs
54     protected int mEnabledIconResId;
55     protected int mDisabledIconResid;
56     protected int mMessageResId;
57     protected int mEnabledStatusMessageResId;
58     protected int mDisabledStatusMessageResId;
59 
60     /**
61      * @param enabledIconResId The icon for when this action is on.
62      * @param disabledIconResid The icon for when this action is off.
63      * @param message The general information message, e.g 'Silent Mode'
64      * @param enabledStatusMessageResId The on status message, e.g 'sound disabled'
65      * @param disabledStatusMessageResId The off status message, e.g. 'sound enabled'
66      */
ToggleAction(int enabledIconResId, int disabledIconResid, int message, int enabledStatusMessageResId, int disabledStatusMessageResId)67     public ToggleAction(int enabledIconResId,
68             int disabledIconResid,
69             int message,
70             int enabledStatusMessageResId,
71             int disabledStatusMessageResId) {
72         mEnabledIconResId = enabledIconResId;
73         mDisabledIconResid = disabledIconResid;
74         mMessageResId = message;
75         mEnabledStatusMessageResId = enabledStatusMessageResId;
76         mDisabledStatusMessageResId = disabledStatusMessageResId;
77     }
78 
79     /** Override to make changes to resource IDs just before creating the View. */
willCreate()80     void willCreate() {
81 
82     }
83 
84     @Override
getLabelForAccessibility(Context context)85     public CharSequence getLabelForAccessibility(Context context) {
86         return context.getString(mMessageResId);
87     }
88 
89     @Override
create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater)90     public View create(Context context, View convertView, ViewGroup parent,
91             LayoutInflater inflater) {
92         willCreate();
93 
94         View v = inflater.inflate(R.layout.global_actions_item, parent, false);
95 
96         ImageView icon = v.findViewById(R.id.icon);
97         TextView messageView = v.findViewById(R.id.message);
98         TextView statusView = v.findViewById(R.id.status);
99         final boolean enabled = isEnabled();
100 
101         if (messageView != null) {
102             messageView.setText(mMessageResId);
103             messageView.setEnabled(enabled);
104         }
105 
106         boolean on = ((mState == State.On) || (mState == State.TurningOn));
107         if (icon != null) {
108             icon.setImageDrawable(context.getDrawable(
109                     (on ? mEnabledIconResId : mDisabledIconResid)));
110             icon.setEnabled(enabled);
111         }
112 
113         if (statusView != null) {
114             statusView.setText(on ? mEnabledStatusMessageResId : mDisabledStatusMessageResId);
115             statusView.setVisibility(View.VISIBLE);
116             statusView.setEnabled(enabled);
117         }
118         v.setEnabled(enabled);
119 
120         return v;
121     }
122 
123     @Override
onPress()124     public final void onPress() {
125         if (mState.inTransition()) {
126             Log.w(TAG, "shouldn't be able to toggle when in transition");
127             return;
128         }
129 
130         final boolean nowOn = !(mState == State.On);
131         onToggle(nowOn);
132         changeStateFromPress(nowOn);
133     }
134 
135     @Override
isEnabled()136     public boolean isEnabled() {
137         return !mState.inTransition();
138     }
139 
140     /**
141      * Implementations may override this if their state can be in on of the intermediate
142      * states until some notification is received (e.g airplane mode is 'turning off' until
143      * we know the wireless connections are back online
144      * @param buttonOn Whether the button was turned on or off
145      */
changeStateFromPress(boolean buttonOn)146     protected void changeStateFromPress(boolean buttonOn) {
147         mState = buttonOn ? State.On : State.Off;
148     }
149 
onToggle(boolean on)150     public abstract void onToggle(boolean on);
151 
updateState(State state)152     public void updateState(State state) {
153         mState = state;
154     }
155 }
156