From 446e70177327ab7f2a148997a6c38a1535506c54 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:21:58 +0000 Subject: [PATCH 1/9] Allow the DrawController to be 'disabled', i.e. don't register any strokes --- .../markyav/drawbox/controller/DrawController.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt index d48bdf2..0446279 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt @@ -1,6 +1,5 @@ package io.github.markyav.drawbox.controller -import androidx.compose.runtime.* import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* import androidx.compose.ui.unit.IntSize @@ -39,6 +38,9 @@ class DrawController { /** A [color] of the stroke */ var color: MutableStateFlow = MutableStateFlow(Color.Red) + /** Whether the controller should register any strokes */ + var enabled: MutableStateFlow = MutableStateFlow(true) + /** A [background] of the background of DrawBox */ var background: MutableStateFlow = MutableStateFlow(DrawBoxBackground.NoBackground) @@ -87,6 +89,8 @@ class DrawController { /** Call this function when user starts drawing a path. */ internal fun updateLatestPath(newPoint: Offset) { + if (!enabled.value) return + (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value != null) val list = activeDrawingPath.value!!.toMutableList() @@ -97,6 +101,8 @@ class DrawController { /** When dragging call this function to update the last path. */ internal fun insertNewPath(newPoint: Offset) { + if (!enabled.value) return + (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value == null) /*val pathWrapper = PathWrapper( @@ -111,6 +117,8 @@ class DrawController { } internal fun finalizePath() { + if (!enabled.value) return + (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value != null) val _drawnPaths = drawnPaths.value.toMutableList() @@ -140,6 +148,8 @@ class DrawController { } internal fun onTap(newPoint: Offset) { + if (!enabled.value) return + insertNewPath(newPoint) finalizePath() } From 166c61af7f7be5d192b4f652a3dee259c226bb77 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:02:35 +0000 Subject: [PATCH 2/9] Give DrawController a tool variable, either BRUSH or ERASER; implement ERASER --- .../io/github/markyav/drawbox/box/DrawBox.kt | 6 +- .../drawbox/controller/DrawController.kt | 63 ++++++++++++++----- .../io/github/markyav/drawbox/model/Tool.kt | 6 ++ 3 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt index 6e28e92..3eaa97a 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt @@ -31,9 +31,9 @@ fun DrawBox( alpha = canvasOpacity, onSizeChanged = controller::connectToDrawBox, onTap = controller::onTap, - onDragStart = controller::insertNewPath, - onDrag = controller::updateLatestPath, - onDragEnd = controller::finalizePath, + onDragStart = controller::onDragStart, + onDrag = controller::onDrag, + onDragEnd = controller::onDragEnd, modifier = Modifier.fillMaxSize(), ) } diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt index 0446279..1aacbfe 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt @@ -4,6 +4,7 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* import androidx.compose.ui.unit.IntSize import io.github.markyav.drawbox.model.PathWrapper +import io.github.markyav.drawbox.model.Tool import io.github.markyav.drawbox.util.addNotNull import io.github.markyav.drawbox.util.combineStates import io.github.markyav.drawbox.util.createPath @@ -16,6 +17,9 @@ import kotlinx.coroutines.flow.* class DrawController { private var state: MutableStateFlow = MutableStateFlow(DrawBoxConnectionState.Disconnected) + /** What tool are we using on the [Canvas] at the minute? */ + var tool: MutableStateFlow = MutableStateFlow(Tool.BRUSH) + /** A stateful list of [Path] that is drawn on the [Canvas]. */ private val drawnPaths: MutableStateFlow> = MutableStateFlow(emptyList()) @@ -87,10 +91,29 @@ class DrawController { openedImage.value = image } - /** Call this function when user starts drawing a path. */ - internal fun updateLatestPath(newPoint: Offset) { + internal fun onDragStart(newPoint: Offset) { + if (!enabled.value) return + + insertNewPath(newPoint) + } + + internal fun onDrag(newPoint: Offset){ + if (!enabled.value) return + + updateLatestPath(newPoint) + } + + internal fun onDragEnd(){ if (!enabled.value) return + when (tool.value){ + Tool.BRUSH -> finalizePath() + Tool.ERASER -> finalizeEraserPath() + } + } + + /** Call this function when user starts drawing a path. */ + internal fun updateLatestPath(newPoint: Offset) { (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value != null) val list = activeDrawingPath.value!!.toMutableList() @@ -101,24 +124,14 @@ class DrawController { /** When dragging call this function to update the last path. */ internal fun insertNewPath(newPoint: Offset) { - if (!enabled.value) return - (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value == null) - /*val pathWrapper = PathWrapper( - points = mutableStateListOf(newPoint.div(it.size.toFloat())), - strokeColor = color.value, - alpha = opacity.value, - strokeWidth = strokeWidth.value.div(it.size.toFloat()), - )*/ activeDrawingPath.value = listOf(newPoint.div(it.size.toFloat())) canceledPaths.value = emptyList() } } internal fun finalizePath() { - if (!enabled.value) return - (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value != null) val _drawnPaths = drawnPaths.value.toMutableList() @@ -136,6 +149,28 @@ class DrawController { } } + internal fun finalizeEraserPath(){ + // TODO should handle onTap as well + // TODO, needs to handle undo/redo + // TODO is sometimes unreliable, I think it's looking for each point, but it should check to see if our [p1] - [p2] intersects their [p1] - [p2] + + (state.value as? DrawBoxConnectionState.Connected)?.let { + require(activeDrawingPath.value != null) + + val toRemove = mutableListOf() + val _erasedPath = activeDrawingPath.value!! + + for (pw in drawnPaths.value) { + if (pw.points.any { p -> _erasedPath.any { e -> e.minus(p).getDistance() < strokeWidth.value.div(it.size.toFloat()) } }) { + toRemove.add(pw) + } + } + + drawnPaths.value -= toRemove.toSet() + activeDrawingPath.value = null + } + } + /** Call this function to connect to the [DrawBox]. */ internal fun connectToDrawBox(size: IntSize) { if ( @@ -177,8 +212,8 @@ class DrawController { (state.value as? DrawBoxConnectionState.Connected)?.let { val pathWrapper = PathWrapper( points = activeDrawingPath.value ?: emptyList(), - strokeColor = color.value, - alpha = opacity.value, + strokeColor = if (tool.value == Tool.BRUSH) color.value else Color.Red, + alpha = if (tool.value == Tool.BRUSH) opacity.value else 0.8f, strokeWidth = strokeWidth.value.div(it.size.toFloat()), ) _a.addNotNull(pathWrapper) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt new file mode 100644 index 0000000..6dd2b3a --- /dev/null +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt @@ -0,0 +1,6 @@ +package io.github.markyav.drawbox.model + +enum class Tool { + BRUSH, + ERASER; +} \ No newline at end of file From 4a254f3f850c4ebe622934fdf22055244da2063e Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:19:43 +0000 Subject: [PATCH 3/9] Fix onTap so that it actually draws something / erases something --- .../markyav/drawbox/controller/DrawController.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt index 1aacbfe..87662c2 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt @@ -136,6 +136,11 @@ class DrawController { require(activeDrawingPath.value != null) val _drawnPaths = drawnPaths.value.toMutableList() + // We need more than one point to draw a proper path, but we can point to the same place twice + if (activeDrawingPath.value!!.size == 1){ + updateLatestPath(activeDrawingPath.value!![0].times(it.size.toFloat())) + } + val pathWrapper = PathWrapper( points = activeDrawingPath.value!!, strokeColor = color.value, @@ -150,7 +155,6 @@ class DrawController { } internal fun finalizeEraserPath(){ - // TODO should handle onTap as well // TODO, needs to handle undo/redo // TODO is sometimes unreliable, I think it's looking for each point, but it should check to see if our [p1] - [p2] intersects their [p1] - [p2] @@ -186,7 +190,11 @@ class DrawController { if (!enabled.value) return insertNewPath(newPoint) - finalizePath() + + when (tool.value){ + Tool.BRUSH -> finalizePath() + Tool.ERASER -> finalizeEraserPath() + } } private fun List.scale(size: Float): List { From 8a79eece0ed96548ffa7f105070216bc746e3614 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 21:49:37 +0000 Subject: [PATCH 4/9] Rename to the slightly more descriptive CanvasTool --- .../drawbox/controller/DrawController.kt | 20 +++++++++---------- .../drawbox/model/{Tool.kt => CanvasTool.kt} | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) rename drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/{Tool.kt => CanvasTool.kt} (73%) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt index 87662c2..f450029 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* import androidx.compose.ui.unit.IntSize import io.github.markyav.drawbox.model.PathWrapper -import io.github.markyav.drawbox.model.Tool +import io.github.markyav.drawbox.model.CanvasTool import io.github.markyav.drawbox.util.addNotNull import io.github.markyav.drawbox.util.combineStates import io.github.markyav.drawbox.util.createPath @@ -18,7 +18,7 @@ class DrawController { private var state: MutableStateFlow = MutableStateFlow(DrawBoxConnectionState.Disconnected) /** What tool are we using on the [Canvas] at the minute? */ - var tool: MutableStateFlow = MutableStateFlow(Tool.BRUSH) + var canvasTool: MutableStateFlow = MutableStateFlow(CanvasTool.BRUSH) /** A stateful list of [Path] that is drawn on the [Canvas]. */ private val drawnPaths: MutableStateFlow> = MutableStateFlow(emptyList()) @@ -106,9 +106,9 @@ class DrawController { internal fun onDragEnd(){ if (!enabled.value) return - when (tool.value){ - Tool.BRUSH -> finalizePath() - Tool.ERASER -> finalizeEraserPath() + when (canvasTool.value){ + CanvasTool.BRUSH -> finalizePath() + CanvasTool.ERASER -> finalizeEraserPath() } } @@ -191,9 +191,9 @@ class DrawController { insertNewPath(newPoint) - when (tool.value){ - Tool.BRUSH -> finalizePath() - Tool.ERASER -> finalizeEraserPath() + when (canvasTool.value){ + CanvasTool.BRUSH -> finalizePath() + CanvasTool.ERASER -> finalizeEraserPath() } } @@ -220,8 +220,8 @@ class DrawController { (state.value as? DrawBoxConnectionState.Connected)?.let { val pathWrapper = PathWrapper( points = activeDrawingPath.value ?: emptyList(), - strokeColor = if (tool.value == Tool.BRUSH) color.value else Color.Red, - alpha = if (tool.value == Tool.BRUSH) opacity.value else 0.8f, + strokeColor = if (canvasTool.value == CanvasTool.BRUSH) color.value else Color.Red, + alpha = if (canvasTool.value == CanvasTool.BRUSH) opacity.value else 0.8f, strokeWidth = strokeWidth.value.div(it.size.toFloat()), ) _a.addNotNull(pathWrapper) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasTool.kt similarity index 73% rename from drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt rename to drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasTool.kt index 6dd2b3a..561c573 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/Tool.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasTool.kt @@ -1,6 +1,6 @@ package io.github.markyav.drawbox.model -enum class Tool { +enum class CanvasTool { BRUSH, ERASER; } \ No newline at end of file From 26cab2df3f9449069c728a35060e532ba4835a32 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:40:30 +0000 Subject: [PATCH 5/9] Allow erasings to be undone/redone --- .../drawbox/controller/DrawController.kt | 77 +++++++++++-------- .../markyav/drawbox/model/CanvasAction.kt | 6 ++ 2 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasAction.kt diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt index f450029..85924a5 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt @@ -3,6 +3,7 @@ package io.github.markyav.drawbox.controller import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.* import androidx.compose.ui.unit.IntSize +import io.github.markyav.drawbox.model.CanvasAction import io.github.markyav.drawbox.model.PathWrapper import io.github.markyav.drawbox.model.CanvasTool import io.github.markyav.drawbox.util.addNotNull @@ -20,13 +21,11 @@ class DrawController { /** What tool are we using on the [Canvas] at the minute? */ var canvasTool: MutableStateFlow = MutableStateFlow(CanvasTool.BRUSH) - /** A stateful list of [Path] that is drawn on the [Canvas]. */ - private val drawnPaths: MutableStateFlow> = MutableStateFlow(emptyList()) - private val activeDrawingPath: MutableStateFlow?> = MutableStateFlow(null) - /** A stateful list of [Path] that was drawn on the [Canvas] but user retracted his action. */ - private val canceledPaths: MutableStateFlow> = MutableStateFlow(emptyList()) + private val actions = MutableStateFlow>(emptyList()) + private val drawnPaths = actions.mapState { getPathsFromActions(it) } + private val undoneActions = MutableStateFlow>(emptyList()) val openedImage: MutableStateFlow = MutableStateFlow(null) @@ -49,41 +48,41 @@ class DrawController { var background: MutableStateFlow = MutableStateFlow(DrawBoxBackground.NoBackground) /** Indicate how many redos it is possible to do. */ - val undoCount = drawnPaths.mapState { it.size } + val undoCount = actions.mapState { it.size } /** Indicate how many undos it is possible to do. */ - val redoCount = canceledPaths.mapState { it.size } + val redoCount = undoneActions.mapState { it.size } /** Executes undo the drawn path if possible. */ fun undo() { - if (drawnPaths.value.isNotEmpty()) { - val _drawnPaths = drawnPaths.value.toMutableList() - val _canceledPaths = canceledPaths.value.toMutableList() + if (actions.value.isNotEmpty()) { + val _actions = actions.value.toMutableList() + val _undoneActions = undoneActions.value.toMutableList() - _canceledPaths.add(_drawnPaths.removeLast()) + _undoneActions.add(_actions.removeLast()) - drawnPaths.value = _drawnPaths - canceledPaths.value = _canceledPaths + actions.value = _actions + undoneActions.value = _undoneActions } } /** Executes redo the drawn path if possible. */ fun redo() { - if (canceledPaths.value.isNotEmpty()) { - val _drawnPaths = drawnPaths.value.toMutableList() - val _canceledPaths = canceledPaths.value.toMutableList() + if (undoneActions.value.isNotEmpty()) { + val _actions = actions.value.toMutableList() + val _undoneActions = undoneActions.value.toMutableList() - _drawnPaths.add(_canceledPaths.removeLast()) + _actions.add(_undoneActions.removeLast()) - drawnPaths.value = _drawnPaths - canceledPaths.value = _canceledPaths + actions.value = _actions + undoneActions.value = _undoneActions } } /** Clear drawn paths and the bitmap image. */ fun reset() { - drawnPaths.value = emptyList() - canceledPaths.value = emptyList() + actions.value = emptyList() + undoneActions.value = emptyList() } fun open(image: ImageBitmap) { @@ -127,14 +126,14 @@ class DrawController { (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value == null) activeDrawingPath.value = listOf(newPoint.div(it.size.toFloat())) - canceledPaths.value = emptyList() + undoneActions.value = emptyList() } } internal fun finalizePath() { (state.value as? DrawBoxConnectionState.Connected)?.let { require(activeDrawingPath.value != null) - val _drawnPaths = drawnPaths.value.toMutableList() + val _actions = actions.value.toMutableList() // We need more than one point to draw a proper path, but we can point to the same place twice if (activeDrawingPath.value!!.size == 1){ @@ -147,15 +146,14 @@ class DrawController { alpha = opacity.value, strokeWidth = strokeWidth.value.div(it.size.toFloat()), ) - _drawnPaths.add(pathWrapper) + _actions.add(CanvasAction.Draw(pathWrapper)) - drawnPaths.value = _drawnPaths + actions.value = _actions activeDrawingPath.value = null } } internal fun finalizeEraserPath(){ - // TODO, needs to handle undo/redo // TODO is sometimes unreliable, I think it's looking for each point, but it should check to see if our [p1] - [p2] intersects their [p1] - [p2] (state.value as? DrawBoxConnectionState.Connected)?.let { @@ -164,13 +162,19 @@ class DrawController { val toRemove = mutableListOf() val _erasedPath = activeDrawingPath.value!! - for (pw in drawnPaths.value) { - if (pw.points.any { p -> _erasedPath.any { e -> e.minus(p).getDistance() < strokeWidth.value.div(it.size.toFloat()) } }) { - toRemove.add(pw) + for (pw in actions.value) { + if (pw !is CanvasAction.Draw) continue + + if (pw.path.points.any { p -> _erasedPath.any { e -> e.minus(p).getDistance() < strokeWidth.value.div(it.size.toFloat()) } }) { + toRemove.add(pw.path) } } - drawnPaths.value -= toRemove.toSet() + if (toRemove.isNotEmpty()) { + actions.value += CanvasAction.Erase(toRemove) + undoneActions.value = emptyList() + } + activeDrawingPath.value = null } } @@ -207,6 +211,19 @@ class DrawController { } } + private fun getPathsFromActions(actions: List): List { + val result = mutableListOf() + + actions.forEach { action -> + when(action) { + is CanvasAction.Draw -> result.add(action.path) + is CanvasAction.Erase -> result.removeAll(action.erased.toSet()) + } + } + + return result + } + fun getDrawPath(subscription: DrawBoxSubscription): StateFlow> { return when (subscription) { is DrawBoxSubscription.DynamicUpdate -> getDynamicUpdateDrawnPath() diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasAction.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasAction.kt new file mode 100644 index 0000000..957f1c6 --- /dev/null +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/model/CanvasAction.kt @@ -0,0 +1,6 @@ +package io.github.markyav.drawbox.model + +sealed class CanvasAction { + data class Draw(val path: PathWrapper) : CanvasAction() + data class Erase(val erased: List) : CanvasAction() +} \ No newline at end of file From 9d3004d158546ad55f801e8b83a1418d8a55048e Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:41:16 +0000 Subject: [PATCH 6/9] Move erase tool to features; fix small spelling mistake --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0506d79..eee687a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ This is the first multiplatform drawing library! - Cross-platform! - Customisable stoke size, color and opacity +- Erase tool - Inbuilt Undo and Redo options - Reset option - Background with color/image @@ -14,7 +15,6 @@ This is the first multiplatform drawing library! - Easy Implementations **Next releases:** -- Erase tool - Import/export - Background content scale @@ -57,7 +57,7 @@ This project was created by [Mark Yavorskyi](https://www.linkedin.com/in/mark-ya ## History I love my work. The idea of creating this open-source project appeared because I needed a multiplatform (Android + desktop) library for drawing. -I fround several popular libs for Android but there was **ZERO** for using in KMM/KMP. +I found several popular libs for Android but there was **ZERO** for using in KMM/KMP. I still have some aspects to improve and I will be happy if you share your feedback or propose an idea! Hope you enjoy it! \ From d649ad756302fe5d28e25d877ffc89ab6efec865 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:55:24 +0000 Subject: [PATCH 7/9] I personally want to display a Composable BoxScope in the background; Modifiers should really come unmodified by default --- .../kotlin/io/github/markyav/drawbox/box/DrawBox.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt index 3eaa97a..8e77f96 100644 --- a/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt +++ b/drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/box/DrawBox.kt @@ -1,6 +1,7 @@ package io.github.markyav.drawbox.box import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.* import androidx.compose.ui.Modifier @@ -13,7 +14,8 @@ import kotlinx.coroutines.flow.StateFlow @Composable fun DrawBox( controller: DrawController, - modifier: Modifier = Modifier.fillMaxSize(), + modifier: Modifier = Modifier, + backgroundContent: (@Composable BoxScope.() -> Unit)? = null ) { val path: StateFlow> = remember { controller.getPathWrappersForDrawbox(DrawBoxSubscription.DynamicUpdate) } val openedImage: StateFlow = remember { controller.getOpenImageForDrawbox(null) } @@ -25,6 +27,7 @@ fun DrawBox( background = background, modifier = Modifier.fillMaxSize(), ) + backgroundContent?.invoke(this@Box) DrawBoxCanvas( pathListWrapper = path, openedImage = openedImage, From 92a2e2b88caed7750dc4c0839eed2872835a2cbc Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Fri, 9 Jan 2026 00:00:45 +0000 Subject: [PATCH 8/9] Had to up Gradle to 8.5 for this to build --- gradle/wrapper/gradle-wrapper.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586..6c8855a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Jan 08 17:26:51 GMT 2026 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 3c88784f3b5ce78494c2e305df77e5cf3c0516a3 Mon Sep 17 00:00:00 2001 From: BosunCyrus <81359374+BosunCyrus@users.noreply.github.com> Date: Fri, 9 Jan 2026 00:02:48 +0000 Subject: [PATCH 9/9] Bump version number to 1.4.0 --- README.md | 2 +- buildSrc/src/main/kotlin/Library.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eee687a..f1bac21 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ DrawBox(drawController = controller, modifier = Modifier.fillMaxSize()) Using Gradle Kotlin DSL: ```kotlin -implementation("io.github.markyav.drawbox:drawbox:1.3.1") +implementation("io.github.markyav.drawbox:drawbox:1.4.0") ``` ## Examples diff --git a/buildSrc/src/main/kotlin/Library.kt b/buildSrc/src/main/kotlin/Library.kt index c378c9e..af68715 100644 --- a/buildSrc/src/main/kotlin/Library.kt +++ b/buildSrc/src/main/kotlin/Library.kt @@ -5,7 +5,7 @@ object Library { val group = "io.github.markyav.drawbox" val artifact = "drawbox" - val version = "1.3.1" + val version = "1.4.0" object License { val name = "Apache-2.0"