1 /*
2  * Copyright (C) 2023 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.launcher3.util
17 
18 import com.android.launcher3.Utilities
19 import kotlin.math.max
20 
21 class CellContentDimensions(
22     var iconSizePx: Int,
23     var iconDrawablePaddingPx: Int,
24     var iconTextSizePx: Int
25 ) {
26     /**
27      * This method goes through some steps to reduce the padding between icon and label, icon size
28      * and then label size, until it can fit in the [cellHeightPx].
29      *
30      * @return the height of the content after being sized down.
31      */
resizeToFitCellHeightnull32     fun resizeToFitCellHeight(cellHeightPx: Int, iconSizeSteps: IconSizeSteps): Int {
33         var cellContentHeight = getCellContentHeight()
34 
35         // Step 1. Decrease drawable padding
36         if (cellContentHeight > cellHeightPx) {
37             val diff = cellContentHeight - cellHeightPx
38             iconDrawablePaddingPx = max(0, iconDrawablePaddingPx - diff)
39             cellContentHeight = getCellContentHeight()
40         }
41 
42         while (
43             (iconTextSizePx > iconSizeSteps.minimumIconLabelSize ||
44                 iconSizePx > iconSizeSteps.minimumIconSize()) && cellContentHeight > cellHeightPx
45         ) {
46             // Step 2. Decrease icon size
47             iconSizePx = iconSizeSteps.getNextLowerIconSize(iconSizePx)
48             cellContentHeight = getCellContentHeight()
49 
50             // Step 3. Decrease label size
51             if (
52                 cellContentHeight > cellHeightPx &&
53                     iconTextSizePx > iconSizeSteps.minimumIconLabelSize
54             ) {
55                 iconTextSizePx =
56                     max(
57                         iconSizeSteps.minimumIconLabelSize,
58                         iconTextSizePx - IconSizeSteps.TEXT_STEP
59                     )
60                 cellContentHeight = getCellContentHeight()
61             }
62         }
63 
64         // For some cases, depending on the display size, the content might not fit inside the
65         // cell height after considering the minimum icon and label size allowed.
66         // For these extreme cases, we will allow the icon size to be smaller than
67         // [IconSizeSteps.minimumIconSize] to fit inside the cell height without cropping.
68         while (
69             cellContentHeight > cellHeightPx && iconSizePx > IconSizeSteps.ICON_SIZE_STEP_EXTRA
70         ) {
71             iconSizePx -= IconSizeSteps.ICON_SIZE_STEP_EXTRA
72             cellContentHeight = getCellContentHeight()
73         }
74 
75         return cellContentHeight
76     }
77 
78     /** Calculate new cellContentHeight */
getCellContentHeightnull79     fun getCellContentHeight(): Int {
80         val iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx.toFloat())
81         return iconSizePx + iconDrawablePaddingPx + iconTextHeight
82     }
83 }
84