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 */
16package com.android.internal.globalactions;
17
18import android.content.Context;
19import android.util.Log;
20import android.view.LayoutInflater;
21import android.view.View;
22import android.view.ViewGroup;
23import android.widget.ImageView;
24import android.widget.TextView;
25import 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 */
31public 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
42        State(boolean intermediate) {
43            inTransition = intermediate;
44        }
45
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     */
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. */
80    void willCreate() {
81
82    }
83
84    @Override
85    public CharSequence getLabelForAccessibility(Context context) {
86        return context.getString(mMessageResId);
87    }
88
89    @Override
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
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
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     */
146    protected void changeStateFromPress(boolean buttonOn) {
147        mState = buttonOn ? State.On : State.Off;
148    }
149
150    public abstract void onToggle(boolean on);
151
152    public void updateState(State state) {
153        mState = state;
154    }
155}
156