1 /*
2  * Copyright (C) 2019 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.systemui.volume;
18 
19 import android.content.Context;
20 import android.os.Handler;
21 import android.util.AttributeSet;
22 import android.view.GestureDetector;
23 import android.view.MotionEvent;
24 
25 import androidx.core.view.ViewCompat;
26 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
27 
28 import com.android.keyguard.AlphaOptimizedImageButton;
29 import com.android.systemui.R;
30 
31 /** Toggle button in Volume Dialog that allows extra state for when streams are opted-out */
32 public class CaptionsToggleImageButton extends AlphaOptimizedImageButton {
33 
34     private static final int[] OPTED_OUT_STATE = new int[] { R.attr.optedOut };
35 
36     private ConfirmedTapListener mConfirmedTapListener;
37     private boolean mCaptionsEnabled = false;
38     private boolean mOptedOut = false;
39 
40     private GestureDetector mGestureDetector;
41     private GestureDetector.SimpleOnGestureListener mGestureListener =
42             new GestureDetector.SimpleOnGestureListener() {
43         @Override
44         public boolean onSingleTapConfirmed(MotionEvent e) {
45             return tryToSendTapConfirmedEvent();
46         }
47     };
48 
CaptionsToggleImageButton(Context context, AttributeSet attrs)49     public CaptionsToggleImageButton(Context context, AttributeSet attrs) {
50         super(context, attrs);
51         this.setContentDescription(
52                 getContext().getString(R.string.volume_odi_captions_content_description));
53     }
54 
55     @Override
onTouchEvent(MotionEvent event)56     public boolean onTouchEvent(MotionEvent event) {
57         if (mGestureDetector != null) mGestureDetector.onTouchEvent(event);
58         return super.onTouchEvent(event);
59     }
60 
61     @Override
onCreateDrawableState(int extraSpace)62     public int[] onCreateDrawableState(int extraSpace) {
63         int[] state = super.onCreateDrawableState(extraSpace + 1);
64         if (mOptedOut) {
65             mergeDrawableStates(state, OPTED_OUT_STATE);
66         }
67         return state;
68     }
69 
setCaptionsEnabled(boolean areCaptionsEnabled)70     Runnable setCaptionsEnabled(boolean areCaptionsEnabled) {
71         this.mCaptionsEnabled = areCaptionsEnabled;
72 
73         ViewCompat.replaceAccessibilityAction(
74                 this,
75                 AccessibilityActionCompat.ACTION_CLICK,
76                 mCaptionsEnabled
77                         ? getContext().getString(R.string.volume_odi_captions_hint_disable)
78                         : getContext().getString(R.string.volume_odi_captions_hint_enable),
79                 (view, commandArguments) -> tryToSendTapConfirmedEvent());
80 
81         return this.setImageResourceAsync(mCaptionsEnabled
82                 ? R.drawable.ic_volume_odi_captions
83                 : R.drawable.ic_volume_odi_captions_disabled);
84     }
85 
tryToSendTapConfirmedEvent()86     private boolean tryToSendTapConfirmedEvent() {
87         if (mConfirmedTapListener != null) {
88             mConfirmedTapListener.onConfirmedTap();
89             return true;
90         }
91         return false;
92     }
93 
getCaptionsEnabled()94     boolean getCaptionsEnabled() {
95         return this.mCaptionsEnabled;
96     }
97 
98     /** Sets whether or not the current stream has opted out of captions */
setOptedOut(boolean isOptedOut)99     void setOptedOut(boolean isOptedOut) {
100         this.mOptedOut = isOptedOut;
101         refreshDrawableState();
102     }
103 
getOptedOut()104     boolean getOptedOut() {
105         return this.mOptedOut;
106     }
107 
setOnConfirmedTapListener(ConfirmedTapListener listener, Handler handler)108     void setOnConfirmedTapListener(ConfirmedTapListener listener, Handler handler) {
109         mConfirmedTapListener = listener;
110 
111         if (mGestureDetector == null) {
112             this.mGestureDetector = new GestureDetector(getContext(), mGestureListener, handler);
113         }
114     }
115 
116     /** Listener for confirmed taps rather than normal on click listener. */
117     interface ConfirmedTapListener {
onConfirmedTap()118         void onConfirmedTap();
119     }
120 }
121