1 /*
<lambda>null2 * Copyright (C) 2024 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.qs.panels.ui.model
18
19 import androidx.compose.foundation.lazy.grid.GridItemSpan
20 import androidx.compose.runtime.Immutable
21 import com.android.systemui.qs.panels.shared.model.SizedTile
22 import com.android.systemui.qs.panels.shared.model.splitInRowsSequence
23 import com.android.systemui.qs.panels.ui.viewmodel.EditTileViewModel
24 import com.android.systemui.qs.shared.model.CategoryAndName
25
26 /** Represents an item from a grid associated with a row and a span */
27 sealed interface GridCell {
28 val row: Int
29 val span: GridItemSpan
30 val s: String
31 }
32
33 /**
34 * Represents a [EditTileViewModel] from a grid associated with a tile format and the row and column
35 * it's positioned at
36 */
37 @Immutable
38 data class TileGridCell(
39 override val tile: EditTileViewModel,
40 override val row: Int,
41 override val width: Int,
42 override val span: GridItemSpan = GridItemSpan(width),
43 override val s: String = "${tile.tileSpec.spec}-$row-$width",
44 val column: Int,
45 ) : GridCell, SizedTile<EditTileViewModel>, CategoryAndName by tile {
46 val key: String = "${tile.tileSpec.spec}-$row"
47
48 constructor(
49 sizedTile: SizedTile<EditTileViewModel>,
50 row: Int,
51 column: Int,
52 ) : this(tile = sizedTile.tile, row = row, column = column, width = sizedTile.width)
53 }
54
55 /** Represents an empty space used to fill incomplete rows. Will always display as a 1x1 tile */
56 @Immutable
57 data class SpacerGridCell(
58 override val row: Int,
59 override val span: GridItemSpan = GridItemSpan(1),
60 override val s: String = "spacer",
61 ) : GridCell
62
63 /**
64 * Generates a list of [GridCell] from a list of [SizedTile]
65 *
66 * Builds rows based on the tiles' widths, and fill each hole with a [SpacerGridCell]
67 *
68 * @param startingRow The row index the grid is built from, used in cases where only end rows need
69 * to be regenerated
70 */
Listnull71 fun List<SizedTile<EditTileViewModel>>.toGridCells(
72 columns: Int,
73 startingRow: Int = 0,
74 ): List<GridCell> {
75 return splitInRowsSequence(this, columns)
76 .flatMapIndexed { rowIndex, sizedTiles ->
77 val correctedRowIndex = rowIndex + startingRow
78 var column = 0
79 val row: List<GridCell> =
80 sizedTiles.map {
81 TileGridCell(it, correctedRowIndex, column).also { cell ->
82 column += cell.width
83 }
84 }
85
86 // Fill the incomplete rows with spacers
87 val numSpacers = columns - sizedTiles.sumOf { it.width }
88 row.toMutableList().apply {
89 repeat(numSpacers) { add(SpacerGridCell(correctedRowIndex)) }
90 }
91 }
92 .toList()
93 }
94