• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.navigationbar.buttons;
18 
19 import android.annotation.IdRes;
20 import android.annotation.NonNull;
21 import android.view.View;
22 
23 import java.io.PrintWriter;
24 import java.util.ArrayList;
25 import java.util.List;
26 
27 public class ContextualButtonGroup extends ButtonDispatcher {
28     private static final int INVALID_INDEX = -1;
29 
30     // List of pairs that contains the button and if the button was visible within this group
31     private final List<ButtonData> mButtonData = new ArrayList<>();
32 
ContextualButtonGroup(@dRes int containerId)33     public ContextualButtonGroup(@IdRes int containerId) {
34         super(containerId);
35     }
36 
37     /**
38      * Add a contextual button to the group. The order of adding increases in its priority. The
39      * priority is used to determine which button should be visible when setting multiple button's
40      * visibility {@see setButtonVisibility}.
41      * @param button the button added to the group
42      */
addButton(@onNull ContextualButton button)43     public void addButton(@NonNull ContextualButton button) {
44         // By default buttons in the context group are not visible until
45         // {@link #setButtonVisibility()) is called to show one of the buttons
46         button.setVisibility(View.INVISIBLE);
47         button.attachToGroup(this);
48         mButtonData.add(new ButtonData(button));
49     }
50 
51     /**
52      * Removes a contextual button from the group.
53      */
removeButton(@dRes int buttonResId)54     public void removeButton(@IdRes int buttonResId) {
55         int index = getContextButtonIndex(buttonResId);
56         if (index != INVALID_INDEX) {
57             mButtonData.remove(index);
58         }
59     }
60 
getContextButton(@dRes int buttonResId)61     public ContextualButton getContextButton(@IdRes int buttonResId) {
62         int index = getContextButtonIndex(buttonResId);
63         if (index != INVALID_INDEX) {
64             return mButtonData.get(index).button;
65         }
66         return null;
67     }
68 
getVisibleContextButton()69     public ContextualButton getVisibleContextButton() {
70         for (int i = mButtonData.size() - 1; i >= 0; --i) {
71             if (mButtonData.get(i).markedVisible) {
72                 return mButtonData.get(i).button;
73             }
74         }
75         return null;
76     }
77 
78     /**
79      * Set the visibility of the button by {@param buttonResId} with {@param visible}. Only one
80      * button is shown at a time. The input button will only show up if it has higher priority than
81      * a previous button, otherwise it will be marked as visible and shown later if all higher
82      * priority buttons are invisible. Therefore hiding a button will show the next marked visible
83      * button. This group's view will be visible if at least one button is visible.
84      * @return if the button is visible after operation
85      * @throws RuntimeException if the input id does not match any of the ids in the group
86      */
setButtonVisibility(@dRes int buttonResId, boolean visible)87     public int setButtonVisibility(@IdRes int buttonResId, boolean visible) {
88         final int index = getContextButtonIndex(buttonResId);
89         if (index == INVALID_INDEX) {
90             throw new RuntimeException("Cannot find the button id of " + buttonResId
91                     + " in context group");
92         }
93         setVisibility(View.INVISIBLE);
94         mButtonData.get(index).markedVisible = visible;
95 
96         // Make all buttons invisible except the first markedVisible button
97         boolean alreadyFoundVisibleButton = false;
98         int i = mButtonData.size() - 1;
99         for (; i >= 0; --i) {
100             final ButtonData buttonData = mButtonData.get(i);
101             if (!alreadyFoundVisibleButton && buttonData.markedVisible) {
102                 buttonData.setVisibility(View.VISIBLE);
103                 setVisibility(View.VISIBLE);
104                 alreadyFoundVisibleButton = true;
105             } else {
106                 buttonData.setVisibility(View.INVISIBLE);
107             }
108         }
109         return mButtonData.get(index).button.getVisibility();
110     }
111 
112     /**
113      * See if button is group visible. Group visible determines if a button can be visible when
114      * higher priority buttons go invisible.
115      * @param buttonResId the button to see if it is group visible
116      * @return true if button is group visible
117      */
isButtonVisibleWithinGroup(@dRes int buttonResId)118     public boolean isButtonVisibleWithinGroup(@IdRes int buttonResId) {
119         final int index = getContextButtonIndex(buttonResId);
120         return index != INVALID_INDEX && mButtonData.get(index).markedVisible;
121     }
122 
123     /**
124      * Update all the icons that are attached to this group. This will get all the buttons to update
125      * their icons for their buttons.
126      */
updateIcons(int lightIconColor, int darkIconColor)127     public void updateIcons(int lightIconColor, int darkIconColor) {
128         for (ButtonData data : mButtonData) {
129             data.button.updateIcon(lightIconColor, darkIconColor);
130         }
131     }
132 
dump(PrintWriter pw)133     public void dump(PrintWriter pw) {
134         View view = getCurrentView();
135         pw.println("ContextualButtonGroup");
136         pw.println("  getVisibleContextButton(): " + getVisibleContextButton());
137         pw.println("  isVisible(): " + isVisible());
138         pw.println("  attached(): " + (view != null && view.isAttachedToWindow()));
139         pw.println("  mButtonData [ ");
140         for (int i = mButtonData.size() - 1; i >= 0; --i) {
141             final ButtonData data = mButtonData.get(i);
142             view = data.button.getCurrentView();
143             pw.println("    " + i + ": markedVisible=" + data.markedVisible
144                     + " visible=" + data.button.getVisibility()
145                     + " attached=" + (view != null && view.isAttachedToWindow())
146                     + " alpha=" + data.button.getAlpha());
147         }
148         pw.println("  ]");
149     }
150 
getContextButtonIndex(@dRes int buttonResId)151     private int getContextButtonIndex(@IdRes int buttonResId) {
152         for (int i = 0; i < mButtonData.size(); ++i) {
153             if (mButtonData.get(i).button.getId() == buttonResId) {
154                 return i;
155             }
156         }
157         return INVALID_INDEX;
158     }
159 
160     private final static class ButtonData {
161         ContextualButton button;
162         boolean markedVisible;
163 
ButtonData(ContextualButton button)164         ButtonData(ContextualButton button) {
165             this.button = button;
166             this.markedVisible = false;
167         }
168 
setVisibility(int visiblity)169         void setVisibility(int visiblity) {
170             button.setVisibility(visiblity);
171         }
172     }
173 }
174