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 17 package com.android.launcher3.responsive 18 19 import android.content.res.TypedArray 20 import android.util.Log 21 import com.android.launcher3.R 22 import com.android.launcher3.responsive.ResponsiveSpec.SpecType 23 import com.android.launcher3.util.ResourceHelper 24 25 private const val TAG = "WorkspaceSpecs" 26 27 class WorkspaceSpecs(widthSpecs: List<WorkspaceSpec>, heightSpecs: List<WorkspaceSpec>) : 28 ResponsiveSpecs<WorkspaceSpec>(widthSpecs, heightSpecs) { 29 getCalculatedWidthSpecnull30 fun getCalculatedWidthSpec(columns: Int, availableWidth: Int): CalculatedWorkspaceSpec { 31 val spec = getWidthSpec(availableWidth) 32 return CalculatedWorkspaceSpec(availableWidth, columns, spec) 33 } 34 getCalculatedHeightSpecnull35 fun getCalculatedHeightSpec(rows: Int, availableHeight: Int): CalculatedWorkspaceSpec { 36 val spec = getHeightSpec(availableHeight) 37 return CalculatedWorkspaceSpec(availableHeight, rows, spec) 38 } 39 40 companion object { 41 private const val XML_WORKSPACE_SPEC = "workspaceSpec" 42 43 @JvmStatic createnull44 fun create(resourceHelper: ResourceHelper): WorkspaceSpecs { 45 val parser = ResponsiveSpecsParser(resourceHelper) 46 val specs = parser.parseXML(XML_WORKSPACE_SPEC, ::WorkspaceSpec) 47 val (widthSpecs, heightSpecs) = specs.partition { it.specType == SpecType.WIDTH } 48 return WorkspaceSpecs(widthSpecs, heightSpecs) 49 } 50 } 51 } 52 53 data class WorkspaceSpec( 54 override val maxAvailableSize: Int, 55 override val specType: SpecType, 56 override val startPadding: SizeSpec, 57 override val endPadding: SizeSpec, 58 override val gutter: SizeSpec, 59 override val cellSize: SizeSpec 60 ) : ResponsiveSpec(maxAvailableSize, specType, startPadding, endPadding, gutter, cellSize) { 61 62 init { <lambda>null63 check(isValid()) { "Invalid WorkspaceSpec found." } 64 } 65 66 constructor( 67 attrs: TypedArray, 68 specs: Map<String, SizeSpec> 69 ) : this( 70 maxAvailableSize = 71 attrs.getDimensionPixelSize(R.styleable.ResponsiveSpec_maxAvailableSize, 0), 72 specType = 73 SpecType.values()[ 74 attrs.getInt(R.styleable.ResponsiveSpec_specType, SpecType.HEIGHT.ordinal)], 75 startPadding = specs.getOrError(SizeSpec.XmlTags.START_PADDING), 76 endPadding = specs.getOrError(SizeSpec.XmlTags.END_PADDING), 77 gutter = specs.getOrError(SizeSpec.XmlTags.GUTTER), 78 cellSize = specs.getOrError(SizeSpec.XmlTags.CELL_SIZE) 79 ) 80 isValidnull81 override fun isValid(): Boolean { 82 // Workspace spec should not match workspace 83 if ( 84 startPadding.matchWorkspace || 85 endPadding.matchWorkspace || 86 gutter.matchWorkspace || 87 cellSize.matchWorkspace 88 ) { 89 Log.e(TAG, "WorkspaceSpec#isValid - workspace shouldn't contain matchWorkspace!") 90 return false 91 } 92 93 return super.isValid() 94 } 95 } 96 97 class CalculatedWorkspaceSpec(availableSpace: Int, cells: Int, spec: WorkspaceSpec) : 98 CalculatedResponsiveSpec(availableSpace, cells, spec) 99