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 
17 package com.android.launcher3.taskbar.navbutton
18 
19 import android.content.res.Resources
20 import android.view.Surface.ROTATION_90
21 import android.view.Surface.Rotation
22 import android.view.ViewGroup
23 import android.widget.ImageView
24 import android.widget.LinearLayout
25 import android.widget.Space
26 import com.android.launcher3.DeviceProfile
27 import com.android.launcher3.taskbar.TaskbarActivityContext
28 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_CONTEXTUAL_BUTTONS
29 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_END_NAV_BUTTONS
30 import com.android.launcher3.taskbar.navbutton.LayoutResourceHelper.ID_START_CONTEXTUAL_BUTTONS
31 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.Companion
32 import com.android.launcher3.taskbar.navbutton.NavButtonLayoutFactory.NavButtonLayoutter
33 
34 /**
35  * Select the correct layout for nav buttons
36  *
37  * Since layouts are done dynamically for the nav buttons on Taskbar, this class returns a
38  * corresponding [NavButtonLayoutter] via [Companion.getUiLayoutter] that can help position the
39  * buttons based on the current [DeviceProfile]
40  */
41 class NavButtonLayoutFactory {
42     companion object {
43         /**
44          * Get the correct instance of [NavButtonLayoutter]
45          *
46          * No layouts supported for configurations where:
47          * * taskbar isn't showing AND
48          * * the device is not in [phoneMode] OR
49          * * phone is showing
50          * * device is using gesture navigation
51          *
52          * @param navButtonsView ViewGroup that contains start, end, nav button ViewGroups
53          * @param isKidsMode no-op when taskbar is hidden/not showing
54          * @param isInSetup no-op when taskbar is hidden/not showing
55          * @param phoneMode refers to the device using the taskbar window on phones
56          * @param isThreeButtonNav are no-ops when taskbar is present/showing
57          */
getUiLayoutternull58         fun getUiLayoutter(
59             deviceProfile: DeviceProfile,
60             navButtonsView: NearestTouchFrame,
61             imeSwitcher: ImageView?,
62             a11yButton: ImageView?,
63             space: Space?,
64             resources: Resources,
65             isKidsMode: Boolean,
66             isInSetup: Boolean,
67             isThreeButtonNav: Boolean,
68             phoneMode: Boolean,
69             @Rotation surfaceRotation: Int
70         ): NavButtonLayoutter {
71             val navButtonContainer =
72                 navButtonsView.requireViewById<LinearLayout>(ID_END_NAV_BUTTONS)
73             val endContextualContainer =
74                 navButtonsView.requireViewById<ViewGroup>(ID_END_CONTEXTUAL_BUTTONS)
75             val startContextualContainer =
76                 navButtonsView.requireViewById<ViewGroup>(ID_START_CONTEXTUAL_BUTTONS)
77             val isPhoneNavMode = phoneMode && isThreeButtonNav
78             val isPhoneGestureMode = phoneMode && !isThreeButtonNav
79             return when {
80                 isPhoneNavMode -> {
81                     if (!deviceProfile.isLandscape) {
82                         navButtonsView.setIsVertical(false)
83                         PhonePortraitNavLayoutter(
84                             resources,
85                             navButtonContainer,
86                             endContextualContainer,
87                             startContextualContainer,
88                             imeSwitcher,
89                             a11yButton,
90                             space
91                         )
92                     } else if (surfaceRotation == ROTATION_90) {
93                         navButtonsView.setIsVertical(true)
94                         PhoneLandscapeNavLayoutter(
95                             resources,
96                             navButtonContainer,
97                             endContextualContainer,
98                             startContextualContainer,
99                             imeSwitcher,
100                             a11yButton,
101                             space
102                         )
103                     } else {
104                         navButtonsView.setIsVertical(true)
105                         PhoneSeascapeNavLayoutter(
106                             resources,
107                             navButtonContainer,
108                             endContextualContainer,
109                             startContextualContainer,
110                             imeSwitcher,
111                             a11yButton,
112                             space
113                         )
114                     }
115                 }
116                 isPhoneGestureMode -> {
117                     PhoneGestureLayoutter(
118                         resources,
119                         navButtonsView,
120                         navButtonContainer,
121                         endContextualContainer,
122                         startContextualContainer,
123                         imeSwitcher,
124                         a11yButton,
125                         space
126                     )
127                 }
128                 deviceProfile.isTaskbarPresent -> {
129                     return when {
130                         isInSetup -> {
131                             SetupNavLayoutter(
132                                 resources,
133                                 navButtonsView,
134                                 navButtonContainer,
135                                 endContextualContainer,
136                                 startContextualContainer,
137                                 imeSwitcher,
138                                 a11yButton,
139                                 space
140                             )
141                         }
142                         isKidsMode -> {
143                             KidsNavLayoutter(
144                                 resources,
145                                 navButtonContainer,
146                                 endContextualContainer,
147                                 startContextualContainer,
148                                 imeSwitcher,
149                                 a11yButton,
150                                 space
151                             )
152                         }
153                         else ->
154                             TaskbarNavLayoutter(
155                                 resources,
156                                 navButtonContainer,
157                                 endContextualContainer,
158                                 startContextualContainer,
159                                 imeSwitcher,
160                                 a11yButton,
161                                 space
162                             )
163                     }
164                 }
165                 else -> error("No layoutter found")
166             }
167         }
168     }
169 
170     /** Lays out and provides access to the home, recents, and back buttons for various mischief */
171     interface NavButtonLayoutter {
layoutButtonsnull172         fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean)
173     }
174 }
175