Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b8556ce authored by Jordan Silva's avatar Jordan Silva
Browse files

Adding match workspace to SizeSpec for responsive grid support

Added matchWorkspace property to support responsive grid implementation for AllApps and Folders. This property indicates whether the attribute value will be used from the workspace instead of defining a fixed value in the AllApps and Folders XML. The class was updated to be a data class and added a auxiliar constructor new make it more flexible for testing and to add other initializers to support AllApps and Folders.

Bug: 284155638
Flag: ENABLE_RESPONSIVE_WORKSPACE
Test: WorkspaceSpecsTest
Test: SizeSpecTest
Change-Id: I65b71e66be7b8236a1dee62b56a487b87881d991
parent f253000b
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@
        <!-- File that contains the specs for the workspace.
        Needs FeatureFlags.ENABLE_RESPONSIVE_WORKSPACE enabled -->
        <attr name="workspaceSpecsId" format="reference" />

        <!-- By default all categories are enabled -->
        <attr name="deviceCategory" format="integer">
            <!-- Enable on phone only -->
@@ -251,10 +252,11 @@
        <attr name="maxAvailableSize" format="dimension" />
    </declare-styleable>

    <declare-styleable name="SpecSize">
    <declare-styleable name="SizeSpec">
        <attr name="fixedSize" format="dimension" />
        <attr name="ofAvailableSpace" format="float" />
        <attr name="ofRemainderSpace" format="float" />
        <attr name="matchWorkspace" format="boolean" />
    </declare-styleable>

    <declare-styleable name="ProfileDisplayOption">
+73 −0
Original line number Diff line number Diff line
package com.android.launcher3.responsive

import android.content.res.TypedArray
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import com.android.launcher3.R
import com.android.launcher3.util.ResourceHelper

data class SizeSpec(
    val fixedSize: Float,
    val ofAvailableSpace: Float,
    val ofRemainderSpace: Float,
    val matchWorkspace: Boolean
) {

    fun isValid(): Boolean {
        // All attributes are empty
        if (fixedSize < 0f && ofAvailableSpace <= 0f && ofRemainderSpace <= 0f && !matchWorkspace) {
            Log.e(TAG, "SizeSpec#isValid - all attributes are empty")
            return false
        }

        // More than one attribute is filled
        val attrCount =
            (if (fixedSize > 0) 1 else 0) +
                (if (ofAvailableSpace > 0) 1 else 0) +
                (if (ofRemainderSpace > 0) 1 else 0) +
                (if (matchWorkspace) 1 else 0)
        if (attrCount > 1) {
            Log.e(TAG, "SizeSpec#isValid - more than one attribute is filled")
            return false
        }

        // Values should be between 0 and 1
        if (ofAvailableSpace !in 0f..1f || ofRemainderSpace !in 0f..1f) {
            Log.e(TAG, "SizeSpec#isValid - values should be between 0 and 1")
            return false
        }

        // Invalid fixed size
        if (fixedSize < 0f) {
            Log.e(TAG, "SizeSpec#isValid - values should be bigger or equal to zero.")
            return false
        }

        return true
    }

    companion object {
        private const val TAG = "WorkspaceSpecs::SizeSpec"
        private fun getValue(a: TypedArray, index: Int): Float {
            return when (a.getType(index)) {
                TypedValue.TYPE_DIMENSION -> a.getDimensionPixelSize(index, 0).toFloat()
                TypedValue.TYPE_FLOAT -> a.getFloat(index, 0f)
                else -> 0f
            }
        }

        fun create(resourceHelper: ResourceHelper, attrs: AttributeSet): SizeSpec {
            val styledAttrs = resourceHelper.obtainStyledAttributes(attrs, R.styleable.SizeSpec)

            val fixedSize = getValue(styledAttrs, R.styleable.SizeSpec_fixedSize)
            val ofAvailableSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofAvailableSpace)
            val ofRemainderSpace = getValue(styledAttrs, R.styleable.SizeSpec_ofRemainderSpace)
            val matchWorkspace = styledAttrs.getBoolean(R.styleable.SizeSpec_matchWorkspace, false)

            styledAttrs.recycle()

            return SizeSpec(fixedSize, ofAvailableSpace, ofRemainderSpace, matchWorkspace)
        }
    }
}
+13 −63
Original line number Diff line number Diff line
@@ -16,13 +16,12 @@

package com.android.launcher3.workspace

import android.content.res.TypedArray
import android.content.res.XmlResourceParser
import android.util.AttributeSet
import android.util.Log
import android.util.TypedValue
import android.util.Xml
import com.android.launcher3.R
import com.android.launcher3.responsive.SizeSpec
import com.android.launcher3.util.ResourceHelper
import java.io.IOException
import kotlin.math.roundToInt
@@ -95,16 +94,16 @@ class WorkspaceSpecs(resourceHelper: ResourceHelper) {
                                if (type == XmlPullParser.START_TAG) {
                                    when (parser.name) {
                                        XmlTags.START_PADDING -> {
                                            startPadding = SizeSpec(resourceHelper, attr)
                                            startPadding = SizeSpec.create(resourceHelper, attr)
                                        }
                                        XmlTags.END_PADDING -> {
                                            endPadding = SizeSpec(resourceHelper, attr)
                                            endPadding = SizeSpec.create(resourceHelper, attr)
                                        }
                                        XmlTags.GUTTER -> {
                                            gutter = SizeSpec(resourceHelper, attr)
                                            gutter = SizeSpec.create(resourceHelper, attr)
                                        }
                                        XmlTags.CELL_SIZE -> {
                                            cellSize = SizeSpec(resourceHelper, attr)
                                            cellSize = SizeSpec.create(resourceHelper, attr)
                                        }
                                    }
                                }
@@ -270,61 +269,12 @@ data class WorkspaceSpec(
    }

    private fun allSpecsAreValid(): Boolean =
        startPadding.isValid() && endPadding.isValid() && gutter.isValid() && cellSize.isValid()
}

class SizeSpec(resourceHelper: ResourceHelper, attrs: AttributeSet) {
    val fixedSize: Float
    val ofAvailableSpace: Float
    val ofRemainderSpace: Float

    init {
        val styledAttrs = resourceHelper.obtainStyledAttributes(attrs, R.styleable.SpecSize)

        fixedSize = getValue(styledAttrs, R.styleable.SpecSize_fixedSize)
        ofAvailableSpace = getValue(styledAttrs, R.styleable.SpecSize_ofAvailableSpace)
        ofRemainderSpace = getValue(styledAttrs, R.styleable.SpecSize_ofRemainderSpace)

        styledAttrs.recycle()
    }

    private fun getValue(a: TypedArray, index: Int): Float {
        if (a.getType(index) == TypedValue.TYPE_DIMENSION) {
            return a.getDimensionPixelSize(index, 0).toFloat()
        } else if (a.getType(index) == TypedValue.TYPE_FLOAT) {
            return a.getFloat(index, 0f)
        }
        return 0f
    }

    fun isValid(): Boolean {
        // All attributes are empty
        if (fixedSize < 0f && ofAvailableSpace <= 0f && ofRemainderSpace <= 0f) {
            Log.e(TAG, "SizeSpec#isValid - all attributes are empty")
            return false
        }

        // More than one attribute is filled
        val attrCount =
            (if (fixedSize > 0) 1 else 0) +
                (if (ofAvailableSpace > 0) 1 else 0) +
                (if (ofRemainderSpace > 0) 1 else 0)
        if (attrCount > 1) {
            Log.e(TAG, "SizeSpec#isValid - more than one attribute is filled")
            return false
        }

        // Values should be between 0 and 1
        if (ofAvailableSpace !in 0f..1f || ofRemainderSpace !in 0f..1f) {
            Log.e(TAG, "SizeSpec#isValid - values should be between 0 and 1")
            return false
        }

        return true
    }

    override fun toString(): String {
        return "SizeSpec(fixedSize=$fixedSize, ofAvailableSpace=$ofAvailableSpace, " +
            "ofRemainderSpace=$ofRemainderSpace)"
    }
        startPadding.isValid() &&
            endPadding.isValid() &&
            gutter.isValid() &&
            cellSize.isValid() &&
            !startPadding.matchWorkspace &&
            !endPadding.matchWorkspace &&
            !gutter.matchWorkspace &&
            !cellSize.matchWorkspace
}
+2 −2
Original line number Diff line number Diff line
@@ -26,10 +26,10 @@
        <attr name="maxAvailableSize" format="dimension" />
    </declare-styleable>

    <declare-styleable name="SpecSize">
    <declare-styleable name="SizeSpec">
        <attr name="fixedSize" format="dimension" />
        <attr name="ofAvailableSpace" format="float" />
        <attr name="ofRemainderSpace" format="float" />
        <attr name="matchWorkspace" format="boolean" />
    </declare-styleable>

</resources>
+58 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ 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.
  -->

<workspaceSpecs xmlns:launcher="http://schemas.android.com/apk/res-auto">
    <workspaceSpec
        launcher:specType="height"
        launcher:maxAvailableSize="648dp">
        <startPadding
            launcher:ofAvailableSpace="0.0125" />
        <endPadding
            launcher:ofAvailableSpace="0.05" />
        <!--  value in workspace spec using matchWorkspace -->
        <gutter
            launcher:matchWorkspace="true" />
        <cellSize
            launcher:ofRemainderSpace="0.2" />
    </workspaceSpec>

    <workspaceSpec
        launcher:specType="height"
        launcher:maxAvailableSize="9999dp">
        <startPadding
            launcher:ofAvailableSpace="0.0306" />
        <endPadding
            launcher:ofAvailableSpace="0.068" />
        <gutter
            launcher:fixedSize="16dp" />
        <cellSize
            launcher:ofRemainderSpace="0.2" />
    </workspaceSpec>

    <!-- Width spec is always the same -->
    <workspaceSpec
        launcher:specType="width"
        launcher:maxAvailableSize="9999dp">
        <startPadding
            launcher:ofRemainderSpace="0.21436227" />
        <endPadding
            launcher:ofRemainderSpace="0.21436227" />
        <gutter
            launcher:ofRemainderSpace="0.11425509" />
        <cellSize
            launcher:fixedSize="120dp" />
    </workspaceSpec>
</workspaceSpecs>
Loading