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.Gravity
21 import android.view.ViewGroup
22 import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
23 import android.widget.FrameLayout
24 import android.widget.ImageView
25 import android.widget.LinearLayout
26 import android.widget.Space
27 import com.android.launcher3.R
28 import com.android.launcher3.taskbar.TaskbarActivityContext
29 
30 /** Layoutter for rendering task bar in large screen, both in 3-button and gesture nav mode. */
31 class TaskbarNavLayoutter(
32     resources: Resources,
33     navBarContainer: LinearLayout,
34     endContextualContainer: ViewGroup,
35     startContextualContainer: ViewGroup,
36     imeSwitcher: ImageView?,
37     a11yButton: ImageView?,
38     space: Space?
39 ) :
40     AbstractNavButtonLayoutter(
41         resources,
42         navBarContainer,
43         endContextualContainer,
44         startContextualContainer,
45         imeSwitcher,
46         a11yButton,
47         space
48     ) {
49 
layoutButtonsnull50     override fun layoutButtons(context: TaskbarActivityContext, isA11yButtonPersistent: Boolean) {
51         // Add spacing after the end of the last nav button
52         var navMarginEnd =
53             resources.getDimension(context.deviceProfile.inv.inlineNavButtonsEndSpacing).toInt()
54 
55         val cutout = context.display.cutout
56         val bottomRect = cutout?.boundingRectBottom
57         if (bottomRect != null && !bottomRect.isEmpty) {
58             navMarginEnd = bottomRect.width()
59         }
60 
61         val contextualWidth = endContextualContainer.width
62         // If contextual buttons are showing, we check if the end margin is enough for the
63         // contextual button to be showing - if not, move the nav buttons over a smidge
64         if (isA11yButtonPersistent && navMarginEnd < contextualWidth) {
65             // Additional spacing, eat up half of space between last icon and nav button
66             navMarginEnd += resources.getDimensionPixelSize(R.dimen.taskbar_hotseat_nav_spacing) / 2
67         }
68 
69         val navButtonParams =
70             FrameLayout.LayoutParams(
71                 FrameLayout.LayoutParams.WRAP_CONTENT,
72                 ViewGroup.LayoutParams.MATCH_PARENT
73             )
74         navButtonParams.apply {
75             gravity = Gravity.END or Gravity.CENTER_VERTICAL
76             marginEnd = navMarginEnd
77         }
78         navButtonContainer.orientation = LinearLayout.HORIZONTAL
79         navButtonContainer.layoutParams = navButtonParams
80 
81         // Add the spaces in between the nav buttons
82         val spaceInBetween = resources.getDimensionPixelSize(R.dimen.taskbar_button_space_inbetween)
83         for (i in 0 until navButtonContainer.childCount) {
84             val navButton = navButtonContainer.getChildAt(i)
85             val buttonLayoutParams = navButton.layoutParams as LinearLayout.LayoutParams
86             buttonLayoutParams.weight = 0f
87             when (i) {
88                 0 -> {
89                     buttonLayoutParams.marginEnd = spaceInBetween / 2
90                 }
91                 navButtonContainer.childCount - 1 -> {
92                     buttonLayoutParams.marginStart = spaceInBetween / 2
93                 }
94                 else -> {
95                     buttonLayoutParams.marginStart = spaceInBetween / 2
96                     buttonLayoutParams.marginEnd = spaceInBetween / 2
97                 }
98             }
99         }
100 
101         endContextualContainer.removeAllViews()
102         startContextualContainer.removeAllViews()
103 
104         if (!context.deviceProfile.isGestureMode) {
105             val contextualMargin =
106                 resources.getDimensionPixelSize(R.dimen.taskbar_contextual_button_padding)
107             repositionContextualContainer(endContextualContainer, WRAP_CONTENT, 0, 0, Gravity.END)
108             repositionContextualContainer(
109                 startContextualContainer,
110                 WRAP_CONTENT,
111                 contextualMargin,
112                 contextualMargin,
113                 Gravity.START
114             )
115 
116             if (imeSwitcher != null) {
117                 val imeStartMargin =
118                     resources.getDimensionPixelSize(
119                         R.dimen.taskbar_ime_switcher_button_margin_start
120                     )
121                 startContextualContainer.addView(imeSwitcher)
122                 val imeSwitcherButtonParams =
123                     FrameLayout.LayoutParams(
124                         FrameLayout.LayoutParams.MATCH_PARENT,
125                         ViewGroup.LayoutParams.MATCH_PARENT
126                     )
127                 imeSwitcherButtonParams.apply {
128                     marginStart = imeStartMargin
129                     gravity = Gravity.CENTER_VERTICAL
130                 }
131                 imeSwitcher.layoutParams = imeSwitcherButtonParams
132             }
133             if (a11yButton != null) {
134                 endContextualContainer.addView(a11yButton)
135                 a11yButton.layoutParams = getParamsToCenterView()
136             }
137         }
138     }
139 }
140