• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                 isInSetup -> {
81                     SetupNavLayoutter(
82                         resources,
83                         navButtonsView,
84                         navButtonContainer,
85                         endContextualContainer,
86                         startContextualContainer,
87                         imeSwitcher,
88                         a11yButton,
89                         space,
90                     )
91                 }
92                 isPhoneNavMode -> {
93                     if (!deviceProfile.isLandscape) {
94                         navButtonsView.setIsVertical(false)
95                         PhonePortraitNavLayoutter(
96                             resources,
97                             navButtonContainer,
98                             endContextualContainer,
99                             startContextualContainer,
100                             imeSwitcher,
101                             a11yButton,
102                             space,
103                         )
104                     } else if (surfaceRotation == ROTATION_90) {
105                         navButtonsView.setIsVertical(true)
106                         PhoneLandscapeNavLayoutter(
107                             resources,
108                             navButtonContainer,
109                             endContextualContainer,
110                             startContextualContainer,
111                             imeSwitcher,
112                             a11yButton,
113                             space,
114                         )
115                     } else {
116                         navButtonsView.setIsVertical(true)
117                         PhoneSeascapeNavLayoutter(
118                             resources,
119                             navButtonContainer,
120                             endContextualContainer,
121                             startContextualContainer,
122                             imeSwitcher,
123                             a11yButton,
124                             space,
125                         )
126                     }
127                 }
128                 isPhoneGestureMode -> {
129                     PhoneGestureLayoutter(
130                         resources,
131                         navButtonContainer,
132                         endContextualContainer,
133                         startContextualContainer,
134                         imeSwitcher,
135                         a11yButton,
136                         space,
137                     )
138                 }
139                 deviceProfile.isTaskbarPresent -> {
140                     return when {
141                         isKidsMode -> {
142                             KidsNavLayoutter(
143                                 resources,
144                                 navButtonContainer,
145                                 endContextualContainer,
146                                 startContextualContainer,
147                                 imeSwitcher,
148                                 a11yButton,
149                                 space,
150                             )
151                         }
152                         else ->
153                             TaskbarNavLayoutter(
154                                 resources,
155                                 navButtonContainer,
156                                 endContextualContainer,
157                                 startContextualContainer,
158                                 imeSwitcher,
159                                 a11yButton,
160                                 space,
161                             )
162                     }
163                 }
164                 else -> error("No layoutter found")
165             }
166         }
167     }
168 
169     /** Lays out and provides access to the home, recents, and back buttons for various mischief */
170     interface NavButtonLayoutter {
layoutButtonsnull171         fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean)
172     }
173 }
174