All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.peanuuutz.fork.ui.foundation.layout.Fill.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2020 The Android Open Source Project
 * Modifications Copyright 2022 Peanuuutz
 *
 * 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 net.peanuuutz.fork.ui.foundation.layout

import androidx.compose.runtime.Stable
import net.peanuuutz.fork.ui.inspection.InspectInfo
import net.peanuuutz.fork.ui.ui.layout.Constraints
import net.peanuuutz.fork.ui.ui.layout.LayoutOrientation
import net.peanuuutz.fork.ui.ui.layout.LayoutOrientation.Option.Both
import net.peanuuutz.fork.ui.ui.layout.LayoutOrientation.Option.Horizontal
import net.peanuuutz.fork.ui.ui.layout.LayoutOrientation.Option.Vertical
import net.peanuuutz.fork.ui.ui.layout.Measurable
import net.peanuuutz.fork.ui.ui.layout.MeasureResult
import net.peanuuutz.fork.ui.ui.modifier.Modifier
import net.peanuuutz.fork.ui.ui.modifier.ModifierNodeElement
import net.peanuuutz.fork.ui.ui.node.LayoutModifierNode
import net.peanuuutz.fork.ui.ui.node.ModifierNode
import net.peanuuutz.fork.ui.ui.unit.IntOffset
import kotlin.math.roundToInt

@Stable
fun Modifier.fillMaxWidth(fraction: Float = 1.0f): Modifier {
    val element = if (fraction == 1.0f) {
        FillWholeWidth
    } else {
        FillModifier(
            orientation = Horizontal,
            fraction = fraction
        )
    }
    return this then element
}

@Stable
fun Modifier.fillMaxHeight(fraction: Float = 1.0f): Modifier {
    val element = if (fraction == 1.0f) {
        FillWholeHeight
    } else {
        FillModifier(
            orientation = Vertical,
            fraction = fraction
        )
    }
    return this then element
}

@Stable
fun Modifier.fillMaxSize(fraction: Float = 1.0f): Modifier {
    val element = if (fraction == 1.0f) {
        FillWholeSize
    } else {
        FillModifier(
            orientation = Both,
            fraction = fraction
        )
    }
    return this then element
}

@Stable
fun Modifier.fillMaxSize(
    widthFraction: Float = 1.0f,
    heightFraction: Float = 1.0f
): Modifier {
    return this
        .fillMaxWidth(widthFraction)
        .fillMaxHeight(heightFraction)
}

// ======== Internal ========

private val FillWholeWidth: FillModifier = FillModifier(
    orientation = Horizontal,
    fraction = 1.0f
)

private val FillWholeHeight: FillModifier = FillModifier(
    orientation = Vertical,
    fraction = 1.0f
)

private val FillWholeSize: FillModifier = FillModifier(
    orientation = Both,
    fraction = 1.0f
)

private data class FillModifier(
    val orientation: LayoutOrientation.Option,
    val fraction: Float
) : ModifierNodeElement() {
    override fun create(): FillModifierNode {
        return FillModifierNode(
            orientation = orientation,
            fraction = fraction
        )
    }

    override fun update(node: FillModifierNode) {
        node.orientation = orientation
        node.fraction = fraction
    }

    override fun InspectInfo.inspect() {
        set("orientation", orientation)
        set("fraction", fraction)
    }
}

private class FillModifierNode(
    var orientation: LayoutOrientation.Option,
    var fraction: Float
) : ModifierNode(), LayoutModifierNode {
    override fun measure(measurable: Measurable, constraints: Constraints): MeasureResult {
        var (minWidth, maxWidth, minHeight, maxHeight) = constraints
        if (orientation != Vertical) {
            val width = (maxWidth * fraction).roundToInt().coerceIn(minWidth, maxWidth)
            minWidth = width
            maxWidth = width
        }
        if (orientation != Horizontal) {
            val height = (maxHeight * fraction).roundToInt().coerceIn(minHeight, maxHeight)
            minHeight = height
            maxHeight = height
        }
        val contentConstraints = Constraints(
            minWidth = minWidth,
            maxWidth = maxWidth,
            minHeight = minHeight,
            maxHeight = maxHeight
        )
        val placeable = measurable.measure(contentConstraints)
        return MeasureResult(placeable.width, placeable.height) {
            placeable.place(IntOffset.Zero)
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy