blob: 67eaac051efb26803c265cde1b1fe5b0a47804b6 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.responsive
import com.android.launcher3.responsive.ResponsiveSpec.Companion.ResponsiveSpecType
import com.android.launcher3.responsive.ResponsiveSpec.DimensionType
import com.android.launcher3.util.ResourceHelper
/**
* A class to provide responsive grid specs for workspace, folder and all apps.
*
* This class is responsible for provide width and height [CalculatedResponsiveSpec] to be used for
* the correct placement of the workspace, all apps and folders.
*
* @param type A [ResponsiveSpecType] to indicates the type of the spec.
* @param groupOfSpecs Groups of responsive specifications
*/
class ResponsiveSpecsProvider(
val type: ResponsiveSpecType,
groupOfSpecs: List<ResponsiveSpecGroup<ResponsiveSpec>>
) {
private val groupOfSpecs: List<ResponsiveSpecGroup<ResponsiveSpec>>
init {
this.groupOfSpecs =
groupOfSpecs
.onEach { group ->
check(group.widthSpecs.isNotEmpty() && group.heightSpecs.isNotEmpty()) {
"${this::class.simpleName} is incomplete - " +
"width list size = ${group.widthSpecs.size}; " +
"height list size = ${group.heightSpecs.size}."
}
}
.sortedBy { it.aspectRatio }
}
fun getSpecsByAspectRatio(aspectRatio: Float): ResponsiveSpecGroup<ResponsiveSpec> {
check(aspectRatio > 0f) { "Invalid aspect ratio! The value should be bigger than 0." }
val specsGroup = groupOfSpecs.firstOrNull { aspectRatio <= it.aspectRatio }
checkNotNull(specsGroup) { "No available spec with aspectRatio within $aspectRatio." }
return specsGroup
}
/**
* Retrieves a responsive grid specification that matches the number of [numCells],
* * [availableSpace] and [aspectRatio].
*
* @param aspectRatio the device width divided by device height (aspect ratio) to filter the
* specifications
* @param dimensionType the grid axis of the spec width is x axis, height is y axis.
* @param numCells number of rows/columns in the grid
* @param availableSpace available width to filter the specifications
* @return A [CalculatedResponsiveSpec] that matches the parameters provided.
*/
fun getCalculatedSpec(
aspectRatio: Float,
dimensionType: DimensionType,
numCells: Int,
availableSpace: Int,
): CalculatedResponsiveSpec {
val specsGroup = getSpecsByAspectRatio(aspectRatio)
val spec = specsGroup.getSpec(dimensionType, availableSpace)
return CalculatedResponsiveSpec(aspectRatio, availableSpace, numCells, spec)
}
/**
* Retrieves a responsive grid specification that matches the number of [numCells],
* * [availableSpace] and [aspectRatio]. This function uses a [CalculatedResponsiveSpec] to
* match workspace when its true.
*
* @param aspectRatio the device width divided by device height (aspect ratio) to filter the
* specifications
* @param dimensionType the grid axis of the spec width is x axis, height is y axis.
* @param numCells number of rows/columns in the grid
* @param availableSpace available width to filter the specifications
* @param calculatedWorkspaceSpec the calculated workspace specification to use its values as
* base when matchWorkspace is true.
* @return A [CalculatedResponsiveSpec] that matches the parameters provided.
*/
fun getCalculatedSpec(
aspectRatio: Float,
dimensionType: DimensionType,
numCells: Int,
availableSpace: Int,
calculatedWorkspaceSpec: CalculatedResponsiveSpec
): CalculatedResponsiveSpec {
check(calculatedWorkspaceSpec.spec.dimensionType == dimensionType) {
"Invalid specType for CalculatedWorkspaceSpec. " +
"Expected: $dimensionType - " +
"Found: ${calculatedWorkspaceSpec.spec.dimensionType}}"
}
check(calculatedWorkspaceSpec.isResponsiveSpecType(ResponsiveSpecType.Workspace)) {
"Invalid specType for CalculatedWorkspaceSpec. " +
"Expected: ${ResponsiveSpecType.Workspace} - " +
"Found: ${calculatedWorkspaceSpec.spec.specType}}"
}
val specsGroup = getSpecsByAspectRatio(aspectRatio)
val spec = specsGroup.getSpec(dimensionType, availableSpace)
return CalculatedResponsiveSpec(
aspectRatio,
availableSpace,
numCells,
spec,
calculatedWorkspaceSpec
)
}
companion object {
@JvmStatic
fun create(
resourceHelper: ResourceHelper,
type: ResponsiveSpecType
): ResponsiveSpecsProvider {
val parser = ResponsiveSpecsParser(resourceHelper)
val specs = parser.parseXML(type, ::ResponsiveSpec)
return ResponsiveSpecsProvider(type, specs)
}
}
}