1 /*
2  * Copyright (C) 2022 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.wallpaper.widget;
17 
18 import android.content.Context;
19 import android.content.res.TypedArray;
20 import android.util.AttributeSet;
21 import android.view.LayoutInflater;
22 import android.widget.CompoundButton;
23 import android.widget.FrameLayout;
24 import android.widget.LinearLayout;
25 import android.widget.ToggleButton;
26 
27 import androidx.annotation.IntDef;
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 import androidx.appcompat.content.res.AppCompatResources;
31 
32 import com.android.wallpaper.R;
33 
34 /**
35  * Custom layout for a group of wallpaper control buttons.
36  */
37 public final class WallpaperControlButtonGroup extends FrameLayout {
38 
39     public static final int DELETE = 0;
40     public static final int EDIT = 1;
41     public static final int CUSTOMIZE = 2;
42     public static final int EFFECTS = 3;
43     public static final int INFORMATION = 4;
44     public static final int SHARE = 5;
45     final int[] mFloatingSheetControlButtonTypes = {CUSTOMIZE, EFFECTS, SHARE, INFORMATION};
46     ToggleButton mDeleteButton;
47     ToggleButton mEditButton;
48     ToggleButton mCustomizeButton;
49     ToggleButton mEffectsButton;
50     ToggleButton mShareButton;
51     ToggleButton mInformationButton;
52 
53     /**
54      * The default orientation is vertical
55      */
56     private int mOrientation = LinearLayout.VERTICAL;
57 
58     /**
59      * Constructor
60      */
WallpaperControlButtonGroup(@onNull Context context, @Nullable AttributeSet attrs)61     public WallpaperControlButtonGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
62         super(context, attrs);
63         initAttributes(attrs);
64         LayoutInflater.from(context).inflate(R.layout.wallpaper_control_button_group, this,
65                 true);
66         LinearLayout buttonGroupContainer = findViewById(R.id.wallpaper_control_container);
67         if (mOrientation == LinearLayout.HORIZONTAL) {
68             buttonGroupContainer.setOrientation(LinearLayout.HORIZONTAL);
69             buttonGroupContainer.setDividerDrawable(context.getDrawable(
70                     R.drawable.wallpaper_control_button_group_divider_horizontal));
71         } else {
72             buttonGroupContainer.setOrientation(LinearLayout.VERTICAL);
73             buttonGroupContainer.setDividerDrawable(
74                     context.getDrawable(
75                             R.drawable.wallpaper_control_button_group_divider_vertical));
76         }
77 
78         mDeleteButton = findViewById(R.id.delete_button);
79         mEditButton = findViewById(R.id.edit_button);
80         mCustomizeButton = findViewById(R.id.customize_button);
81         mEffectsButton = findViewById(R.id.effects_button);
82         mShareButton = findViewById(R.id.share_button);
83         mInformationButton = findViewById(R.id.information_button);
84     }
85 
86     /**
87      * @param attrs sets the local attribute properties for [WallpaperControlButtonGroup]
88      */
initAttributes(AttributeSet attrs)89     private void initAttributes(AttributeSet attrs) {
90         if (attrs != null) {
91             TypedArray typeArray = getContext().obtainStyledAttributes(attrs,
92                     R.styleable.WallpaperControlButtonGroup);
93 
94             // default to vertical
95             mOrientation = typeArray.getInt(R.styleable.WallpaperControlButtonGroup_orientation,
96                     LinearLayout.VERTICAL);
97 
98             typeArray.recycle();
99         }
100     }
101 
102     /**
103      * Show a button by giving a correspondent listener
104      */
showButton(@allpaperControlType int type, CompoundButton.OnCheckedChangeListener listener)105     public void showButton(@WallpaperControlType int type,
106             CompoundButton.OnCheckedChangeListener listener) {
107         ToggleButton button = getActionButton(type);
108         if (button != null) {
109             button.setVisibility(VISIBLE);
110             button.setOnCheckedChangeListener(listener);
111         }
112     }
113 
getActionButton(@allpaperControlType int type)114     private ToggleButton getActionButton(@WallpaperControlType int type) {
115         switch (type) {
116             case DELETE:
117                 return mDeleteButton;
118             case EDIT:
119                 return mEditButton;
120             case CUSTOMIZE:
121                 return mCustomizeButton;
122             case EFFECTS:
123                 return mEffectsButton;
124             case SHARE:
125                 return mShareButton;
126             case INFORMATION:
127                 return mInformationButton;
128             default:
129                 return null;
130         }
131     }
132 
133     /**
134      * Hide a button
135      */
hideButton(@allpaperControlType int type)136     public void hideButton(@WallpaperControlType int type) {
137         getActionButton(type).setVisibility(GONE);
138     }
139 
140     /**
141      * Set checked for a button
142      */
setChecked(@allpaperControlType int type, boolean checked)143     public void setChecked(@WallpaperControlType int type, boolean checked) {
144         getActionButton(type).setChecked(checked);
145     }
146 
147     /**
148      * Update the background color in case the context theme has changed.
149      */
updateBackgroundColor()150     public void updateBackgroundColor() {
151         Context context = getContext();
152         if (context == null) {
153             return;
154         }
155         mDeleteButton.setForeground(null);
156         mEditButton.setForeground(null);
157         mCustomizeButton.setForeground(null);
158         mEffectsButton.setForeground(null);
159         mShareButton.setForeground(null);
160         mInformationButton.setForeground(null);
161         mDeleteButton.setForeground(AppCompatResources.getDrawable(context,
162                 R.drawable.wallpaper_control_button_delete));
163         mEditButton.setForeground(
164                 AppCompatResources.getDrawable(context, R.drawable.wallpaper_control_button_edit));
165         mCustomizeButton.setForeground(AppCompatResources.getDrawable(context,
166                 R.drawable.wallpaper_control_button_customize));
167         mEffectsButton.setForeground(AppCompatResources.getDrawable(context,
168                 R.drawable.wallpaper_control_button_effect));
169         mShareButton.setForeground(AppCompatResources.getDrawable(context,
170                 R.drawable.wallpaper_control_button_share));
171         mInformationButton.setForeground(
172                 AppCompatResources.getDrawable(context, R.drawable.wallpaper_control_button_info));
173     }
174 
175     /**
176      * Ensures only one toggle button with a floating sheet is selected at a time
177      */
deselectOtherFloatingSheetControlButtons(@allpaperControlType int selectedType)178     public void deselectOtherFloatingSheetControlButtons(@WallpaperControlType int selectedType) {
179         for (int type : mFloatingSheetControlButtonTypes) {
180             if (type != selectedType) {
181                 getActionButton(type).setChecked(false);
182             }
183         }
184     }
185 
186     /**
187      * Returns true if there is a floating sheet button selected, and false if not
188      */
isFloatingSheetControlButtonSelected()189     public boolean isFloatingSheetControlButtonSelected() {
190         for (int type : mFloatingSheetControlButtonTypes) {
191             if (getActionButton(type).isChecked()) {
192                 return true;
193             }
194         }
195         return false;
196     }
197 
198     /**
199      * Deselects all floating sheet toggle buttons in the Wallpaper Control Button Group
200      */
deselectAllFloatingSheetControlButtons()201     public void deselectAllFloatingSheetControlButtons() {
202         for (int type : mFloatingSheetControlButtonTypes) {
203             getActionButton(type).setChecked(false);
204         }
205     }
206 
207     /**
208      * Overlay tab
209      */
210     @IntDef({DELETE, EDIT, CUSTOMIZE, EFFECTS, SHARE, INFORMATION})
211     public @interface WallpaperControlType {
212     }
213 }
214