-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Alignment to Row, Column and Box (#233)
* Add Alignment to Row, Column and Box * Apply suggestions from code review --------- Co-authored-by: Jake Wharton <github@jakewharton.com>
- Loading branch information
1 parent
1a68525
commit f7ec16c
Showing
12 changed files
with
603 additions
and
16 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/IntrinsicMeasurable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.jakewharton.mosaic.layout | ||
|
||
/** | ||
* A part of the composition that can be measured. This represents a layout. | ||
* The instance should never be stored. | ||
*/ | ||
public interface IntrinsicMeasurable { | ||
/** | ||
* Data provided by the `ParentData` | ||
*/ | ||
public val parentData: Any? | ||
} |
2 changes: 1 addition & 1 deletion
2
mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/Measurable.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
package com.jakewharton.mosaic.layout | ||
|
||
public interface Measurable { | ||
public interface Measurable : IntrinsicMeasurable { | ||
public fun measure(): Placeable | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
16 changes: 16 additions & 0 deletions
16
mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/layout/ParentDataModifier.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.jakewharton.mosaic.layout | ||
|
||
import com.jakewharton.mosaic.modifier.Modifier | ||
|
||
/** | ||
* A [Modifier] that provides data to the parent [Layout]. This can be read from within the | ||
* the [Layout] during measurement and positioning, via [IntrinsicMeasurable.parentData]. | ||
* The parent data is commonly used to inform the parent how the child [Layout] should be measured | ||
* and positioned. | ||
*/ | ||
public interface ParentDataModifier : Modifier.Element { | ||
/** | ||
* Provides a parentData, given the [parentData] already provided through the modifier's chain. | ||
*/ | ||
public fun modifyParentData(parentData: Any?): Any? | ||
} |
173 changes: 173 additions & 0 deletions
173
mosaic-runtime/src/commonMain/kotlin/com/jakewharton/mosaic/ui/Alignment.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
package com.jakewharton.mosaic.ui | ||
|
||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.Stable | ||
import com.jakewharton.mosaic.ui.unit.IntOffset | ||
import com.jakewharton.mosaic.ui.unit.IntSize | ||
import kotlin.math.roundToInt | ||
|
||
/** | ||
* An interface to calculate the position of a sized box inside an available space. [Alignment] is | ||
* often used to define the alignment of a layout inside a parent layout. | ||
* | ||
* @see BiasAlignment | ||
*/ | ||
@Stable | ||
public fun interface Alignment { | ||
/** | ||
* Calculates the position of a box of size [size] relative to the top left corner of an area | ||
* of size [space]. The returned offset can be negative or larger than `space - size`, | ||
* meaning that the box will be positioned partially or completely outside the area. | ||
*/ | ||
public fun align(size: IntSize, space: IntSize): IntOffset | ||
|
||
/** | ||
* An interface to calculate the position of box of a certain width inside an available width. | ||
* [Alignment.Horizontal] is often used to define the horizontal alignment of a layout inside a | ||
* parent layout. | ||
*/ | ||
@Stable | ||
public fun interface Horizontal { | ||
/** | ||
* Calculates the horizontal position of a box of width [size] relative to the left | ||
* side of an area of width [space]. The returned offset can be negative or larger than | ||
* `space - size` meaning that the box will be positioned partially or completely outside | ||
* the area. | ||
*/ | ||
public fun align(size: Int, space: Int): Int | ||
} | ||
|
||
/** | ||
* An interface to calculate the position of a box of a certain height inside an available | ||
* height. [Alignment.Vertical] is often used to define the vertical alignment of a | ||
* layout inside a parent layout. | ||
*/ | ||
@Stable | ||
public fun interface Vertical { | ||
/** | ||
* Calculates the vertical position of a box of height [size] relative to the top edge of | ||
* an area of height [space]. The returned offset can be negative or larger than | ||
* `space - size` meaning that the box will be positioned partially or completely outside | ||
* the area. | ||
*/ | ||
public fun align(size: Int, space: Int): Int | ||
} | ||
|
||
/** | ||
* A collection of common [Alignment]s aware of layout direction. | ||
*/ | ||
public companion object { | ||
// 2D Alignments. | ||
@Stable | ||
public val TopStart: Alignment = BiasAlignment(-1f, -1f) | ||
|
||
@Stable | ||
public val TopCenter: Alignment = BiasAlignment(0f, -1f) | ||
|
||
@Stable | ||
public val TopEnd: Alignment = BiasAlignment(1f, -1f) | ||
|
||
@Stable | ||
public val CenterStart: Alignment = BiasAlignment(-1f, 0f) | ||
|
||
@Stable | ||
public val Center: Alignment = BiasAlignment(0f, 0f) | ||
|
||
@Stable | ||
public val CenterEnd: Alignment = BiasAlignment(1f, 0f) | ||
|
||
@Stable | ||
public val BottomStart: Alignment = BiasAlignment(-1f, 1f) | ||
|
||
@Stable | ||
public val BottomCenter: Alignment = BiasAlignment(0f, 1f) | ||
|
||
@Stable | ||
public val BottomEnd: Alignment = BiasAlignment(1f, 1f) | ||
|
||
// 1D Alignment.Verticals. | ||
@Stable | ||
public val Top: Vertical = BiasAlignment.Vertical(-1f) | ||
|
||
@Stable | ||
public val CenterVertically: Vertical = BiasAlignment.Vertical(0f) | ||
|
||
@Stable | ||
public val Bottom: Vertical = BiasAlignment.Vertical(1f) | ||
|
||
// 1D Alignment.Horizontals. | ||
@Stable | ||
public val Start: Horizontal = BiasAlignment.Horizontal(-1f) | ||
|
||
@Stable | ||
public val CenterHorizontally: Horizontal = BiasAlignment.Horizontal(0f) | ||
|
||
@Stable | ||
public val End: Horizontal = BiasAlignment.Horizontal(1f) | ||
} | ||
} | ||
|
||
/** | ||
* An [Alignment] specified by bias: for example, a bias of -1 represents alignment to the | ||
* start/top, a bias of 0 will represent centering, and a bias of 1 will represent end/bottom. | ||
* Any value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained | ||
* alignment will position the aligned size fully inside the available space, while outside the | ||
* range it will the aligned size will be positioned partially or completely outside. | ||
* | ||
* @see Alignment | ||
*/ | ||
@Immutable | ||
public data class BiasAlignment( | ||
val horizontalBias: Float, | ||
val verticalBias: Float | ||
) : Alignment { | ||
|
||
override fun align(size: IntSize, space: IntSize): IntOffset { | ||
// Convert to cells first and only round at the end, to avoid rounding twice while calculating | ||
// the new positions | ||
val centerX = (space.width - size.width).toFloat() / 2f | ||
val centerY = (space.height - size.height).toFloat() / 2f | ||
|
||
val x = centerX * (1 + horizontalBias) | ||
val y = centerY * (1 + verticalBias) | ||
return IntOffset(x.roundToInt(), y.roundToInt()) | ||
} | ||
|
||
/** | ||
* An [Alignment.Horizontal] specified by bias: for example, a bias of -1 represents alignment | ||
* to the start, a bias of 0 will represent centering, and a bias of 1 will represent end. | ||
* Any value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained | ||
* alignment will position the aligned size fully inside the available space, while outside the | ||
* range it will the aligned size will be positioned partially or completely outside. | ||
* | ||
* @see Vertical | ||
*/ | ||
@Immutable | ||
public data class Horizontal(private val bias: Float) : Alignment.Horizontal { | ||
override fun align(size: Int, space: Int): Int { | ||
// Convert to cells first and only round at the end, to avoid rounding twice while | ||
// calculating the new positions. | ||
val center = (space - size).toFloat() / 2f | ||
return (center * (1 + bias)).roundToInt() | ||
} | ||
} | ||
|
||
/** | ||
* An [Alignment.Vertical] specified by bias: for example, a bias of -1 represents alignment | ||
* to the top, a bias of 0 will represent centering, and a bias of 1 will represent bottom. | ||
* Any value can be specified to obtain an alignment. Inside the [-1, 1] range, the obtained | ||
* alignment will position the aligned size fully inside the available space, while outside the | ||
* range it will the aligned size will be positioned partially or completely outside. | ||
* | ||
* @see Horizontal | ||
*/ | ||
@Immutable | ||
public data class Vertical(private val bias: Float) : Alignment.Vertical { | ||
override fun align(size: Int, space: Int): Int { | ||
// Convert to cells first and only round at the end, to avoid rounding twice while | ||
// calculating the new positions. | ||
val center = (space - size).toFloat() / 2f | ||
return (center * (1 + bias)).roundToInt() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.