Skip to content

Commit

Permalink
Merge pull request #48 from mori-atsushi/border
Browse files Browse the repository at this point in the history
Add BorderStyle
  • Loading branch information
mori-atsushi authored Nov 24, 2023
2 parents 73cdaa9 + 1119f0f commit 770b31e
Show file tree
Hide file tree
Showing 11 changed files with 299 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.moriatsushi.compose.stylesheet.surface

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.isSpecified
import com.moriatsushi.compose.stylesheet.StyleSheet
import com.moriatsushi.compose.stylesheet.border.BorderStyle
import com.moriatsushi.compose.stylesheet.component.Component
import com.moriatsushi.compose.stylesheet.component.componentCommonStyle
import com.moriatsushi.compose.stylesheet.content.ContentStyle
Expand Down Expand Up @@ -38,7 +38,7 @@ fun Surface(
tags: TagModifier<SurfaceStyle> = TagModifier(),
background: Color = Color.Unspecified,
shape: Shape? = null,
border: BorderStroke? = null,
border: BorderStyle? = null,
contentColor: Color = Color.Unspecified,
surfaceStyle: SurfaceStyle = SurfaceStyle.Default,
content: @Composable () -> Unit,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
package com.moriatsushi.compose.stylesheet

import com.moriatsushi.compose.stylesheet.token.Token
import com.moriatsushi.compose.stylesheet.token.TokenSetter

/**
* An interface for building a [style][T].
*/
interface StyleBuilder<T> {
/**
* Sets the given [token] to [this].
*/
operator fun <T> TokenSetter<T>.plusAssign(token: Token<T>?) {
if (token != null) {
this.token = token
}
}

/**
* Sets the given [value] to [this].
*/
operator fun <T> TokenSetter<T>.plusAssign(value: T) {
this.token = Token(value)
}

/**
* Merges this style with the given [other] style.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.moriatsushi.compose.stylesheet.border

import androidx.compose.foundation.BorderStroke
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.Dp
import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi
import com.moriatsushi.compose.stylesheet.graphics.BrushSetterCallback
import com.moriatsushi.compose.stylesheet.graphics.BrushStyle
import com.moriatsushi.compose.stylesheet.token.TokenSetterCallback

class BorderSetter @StyleSheetComponentApi constructor() {
@StyleSheetComponentApi
var value: BorderStyle? = null
private set

/**
* A width of the border.
*/
val width: TokenSetterCallback<Dp> = TokenSetterCallback {
value = value?.copy(width = it) ?: BorderStyle(width = it)
}

/**
* A brush of the border.
*/
val brush: BrushSetterCallback = BrushSetterCallback {
value = value?.copy(brush = it) ?: BorderStyle(brush = it)
}

/**
* A color of the border.
*/
val color: TokenSetterCallback<Color> = TokenSetterCallback {
brush += BrushStyle(it)
}

operator fun plusAssign(border: BorderStyle?) {
if (border != null) {
value = border
}
}

operator fun plusAssign(border: BorderStroke) {
this.value = BorderStyle(border)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.moriatsushi.compose.stylesheet.border

import androidx.compose.foundation.BorderStroke
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.unit.Dp
import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi
import com.moriatsushi.compose.stylesheet.graphics.BrushStyle
import com.moriatsushi.compose.stylesheet.token.Token
import com.moriatsushi.compose.stylesheet.token.value

@Immutable
sealed interface BorderStyle {
val width: Token<Dp>
val brush: Token<BrushStyle>

companion object {
val Unspecified: BorderStyle = BorderStyle()
}
}

@Composable
@StyleSheetComponentApi
fun BorderStyle.asBorderStroke(): BorderStroke? =
if (this != BorderStyle.Unspecified) {
BorderStroke(width = width.value, brush = brush.value.asBrush())
} else {
null
}

internal fun BorderStyle.copy(
width: Token<Dp> = this.width,
brush: Token<BrushStyle> = this.brush,
): BorderStyle = BorderStyle(width = width, brush = brush)

internal fun BorderStyle(
width: Token<Dp> = Token(Dp.Unspecified),
brush: Token<BrushStyle> = Token(BrushStyle.Unspecified),
): BorderStyle = BorderStyleImpl(width = width, brush = brush)

internal fun BorderStyle(borderStroke: BorderStroke): BorderStyle =
BorderStyle(width = Token(borderStroke.width), brush = Token(BrushStyle(borderStroke.brush)))

@Immutable
private data class BorderStyleImpl(
override val width: Token<Dp>,
override val brush: Token<BrushStyle>,
) : BorderStyle
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.moriatsushi.compose.stylesheet.component

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.runtime.Composable
Expand All @@ -11,6 +10,8 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.isSpecified
import com.moriatsushi.compose.stylesheet.border.BorderStyle
import com.moriatsushi.compose.stylesheet.border.asBorderStroke
import com.moriatsushi.compose.stylesheet.component.padding.ComponentPadding
import com.moriatsushi.compose.stylesheet.component.padding.componentPadding
import com.moriatsushi.compose.stylesheet.component.size.ComponentSize
Expand All @@ -28,7 +29,7 @@ data class ComponentCommonStyle internal constructor(
val padding: ComponentPadding? = null,
internal val background: Token<Color>? = null,
internal val shape: Token<Shape?>? = null,
internal val border: Token<BorderStroke?>? = null,
internal val border: BorderStyle? = null,
) {
companion object {
/**
Expand All @@ -52,7 +53,7 @@ fun Modifier.componentCommonStyle(
): Modifier {
val shape = style.shape?.value ?: RectangleShape

val border = style.border?.value
val border = style.border?.asBorderStroke()
val borderModifier = if (border != null) {
Modifier.border(border, shape)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.moriatsushi.compose.stylesheet.component

import androidx.compose.foundation.BorderStroke
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.moriatsushi.compose.stylesheet.StyleBuilder
import com.moriatsushi.compose.stylesheet.border.BorderSetter
import com.moriatsushi.compose.stylesheet.component.padding.ComponentPadding
import com.moriatsushi.compose.stylesheet.component.padding.PaddingSetter
import com.moriatsushi.compose.stylesheet.component.size.ComponentFillSize
Expand Down Expand Up @@ -177,8 +177,17 @@ abstract class ComponentStyleBuilder<T : ComponentStyle> : StyleBuilder<T> {

/**
* A background border.
*
* Example:
* ```
* border += BorderStroke(1.dp, Color.Black)
* border += BorderStyle.Unspecified // Clear border
* border.width += 1.dp
* border.color += Color.Black
* border.brush += Brush.horizontalGradient(listOf(Color.Red, Color.Blue))
* ```
*/
val border: TokenSetter<BorderStroke?> = TokenSetter()
val border: BorderSetter = BorderSetter()

/**
* A value for filling the component.
Expand Down Expand Up @@ -259,6 +268,6 @@ abstract class ComponentStyleBuilder<T : ComponentStyle> : StyleBuilder<T> {
padding = padding.value,
background = background.token,
shape = shape.token,
border = border.token,
border = border.value,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.moriatsushi.compose.stylesheet.graphics

import androidx.compose.ui.graphics.Brush
import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi
import com.moriatsushi.compose.stylesheet.token.Token

class BrushSetterCallback @StyleSheetComponentApi constructor(
private val onSet: (Token<BrushStyle>) -> Unit,
) {
/**
* Sets the given [token].
*/
operator fun plusAssign(token: Token<BrushStyle>?) {
if (token != null) {
onSet(token)
}
}

/**
* Sets the given [brush].
*/
operator fun plusAssign(brush: BrushStyle) {
onSet(Token(brush))
}

/**
* Sets the given [brush].
*/
operator fun plusAssign(brush: Brush) {
onSet(Token(BrushStyle(brush)))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.moriatsushi.compose.stylesheet.graphics

import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi
import com.moriatsushi.compose.stylesheet.token.Token
import com.moriatsushi.compose.stylesheet.token.value

sealed interface BrushStyle {
@StyleSheetComponentApi
@Composable
fun asBrush(): Brush

companion object {
val Unspecified: BrushStyle = BrushStyle(Color.Unspecified)
}
}

fun BrushStyle(color: Token<Color>): BrushStyle = SolidColorBrush(color = color)

fun BrushStyle(color: Color): BrushStyle = BrushStyle(color = Token(color))

fun BrushStyle(brush: Brush): BrushStyle = BrushHolder(brush = brush)

private data class SolidColorBrush(val color: Token<Color>) : BrushStyle {
@Composable
override fun asBrush(): Brush = SolidColor(color.value)
}

private data class BrushHolder(private val brush: Brush) : BrushStyle {
@Composable
override fun asBrush(): Brush = brush
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,23 @@ package com.moriatsushi.compose.stylesheet.token
import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi

class TokenSetter<T> @StyleSheetComponentApi constructor() {
@StyleSheetComponentApi
var token: Token<T>? = null
internal set
private set

/**
* Sets the given [token].
*/
operator fun plusAssign(token: Token<T>?) {
if (token != null) {
this.token = token
}
}

/**
* Sets the given [value].
*/
operator fun plusAssign(value: T) {
this.token = Token(value)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.moriatsushi.compose.stylesheet.token

import com.moriatsushi.compose.stylesheet.component.StyleSheetComponentApi

class TokenSetterCallback<T> @StyleSheetComponentApi constructor(
private val onSet: (Token<T>) -> Unit,
) {
/**
* Sets the given [token].
*/
operator fun plusAssign(token: Token<T>?) {
if (token != null) {
onSet(token)
}
}

/**
* Sets the given [value].
*/
operator fun plusAssign(value: T) {
onSet(Token(value))
}
}
Loading

0 comments on commit 770b31e

Please sign in to comment.