Skip to content

Commit 8baba7f

Browse files
authored
Merge pull request #3 from MarkYav/develop
v1.1.0
2 parents 59fc2ef + 27a6509 commit 8baba7f

9 files changed

Lines changed: 324 additions & 10 deletions

File tree

README.md

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,20 @@ This is the first multiplatform drawing library!
1414
- Easy Implementations
1515

1616
**Next releases:**
17-
- Optimizing rendering (convert drawn PATHes)
17+
- Erase tool
18+
- Import/export
19+
1820

1921
**Planned:**
2022
- Different image rations
21-
- Erase tool
2223
- Filling tool
24+
- Optimizing rendering (convert drawn PATHes)
2325
- Migrate from Compose dependencies in DrawController
2426

27+
## Demo
28+
29+
https://user-images.githubusercontent.com/39382424/230722003-e9b91b28-706a-4048-a950-609f0b357151.mp4
30+
2531
## Usage
2632

2733
```kotlin
@@ -33,11 +39,29 @@ DrawBox(drawController = controller, modifier = Modifier.fillMaxSize())
3339

3440
Using Gradle Kotlin DSL:
3541
```kotlin
36-
repository {
37-
implementation("io.github.markyav.drawbox:drawbox:1.0.0")
38-
}
42+
implementation("io.github.markyav.drawbox:drawbox:1.0.0")
3943
```
4044

45+
## Examples
46+
47+
You can find example of the library basic usage in the [sample](sample) package:
48+
- [Android](sample/android/src/main/java/io/github/markyav/drawbox/android/MainActivity.kt)
49+
- [Desktop](sample/desktop/src/jvmMain/kotlin/Main.kt)
50+
51+
Also, I will share a link here to another independent project where you can find more sophisticated example!
52+
53+
## Author
54+
This project was created by [Mark Yavorskyi](https://www.linkedin.com/in/mark-yavorskyi/)
55+
56+
## History
57+
I love my work.
58+
The idea of creating this open-source project appeared because I needed a multiplatform (Android + desktop) library for drawing.
59+
I fround several popular libs for Android but there was **ZERO** for using in KMM/KMP.
60+
I still have some aspects to improve and I will be happy if you share your feedback or propose an idea!
61+
62+
Hope you enjoy it! \
63+
Mark
64+
4165
## License
4266

43-
Licensed under the Apache License, Version 2.0, [click here for the full license](LICENSE.txt).
67+
Licensed under the Apache License, Version 2.0, [click here for the full license](LICENSE.txt).

buildSrc/src/main/kotlin/Android.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@ object Android {
22
val compileSdk = 33
33
val minSdk = 24
44
val targetSdk = 33
5+
val versionCode = Library.version
6+
.split(".")
7+
.map { it.toInt() }
8+
.reduce { acc, i -> acc * 10 + i }
9+
val applicationId = Library.group + "android"
510
}

drawbox/src/commonMain/kotlin/io/github/markyav/drawbox/controller/DrawController.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import androidx.compose.ui.unit.IntSize
88
import io.github.markyav.drawbox.model.PathWrapper
99
import io.github.markyav.drawbox.util.createPath
1010
import io.github.markyav.drawbox.util.pop
11-
import kotlinx.coroutines.flow.Flow
12-
import kotlinx.coroutines.flow.flow
11+
import kotlinx.coroutines.CoroutineScope
12+
import kotlinx.coroutines.flow.*
1313

1414
/**
1515
* DrawController interacts with [DrawBox] and it allows you to control the canvas and all the components with it.
@@ -57,20 +57,23 @@ class DrawController {
5757
fun undo() {
5858
if (drawnPaths.isNotEmpty()) {
5959
canceledPaths.add(drawnPaths.pop())
60+
finalizePath()
6061
}
6162
}
6263

6364
/** Executes redo the drawn path if possible. */
6465
fun redo() {
6566
if (canceledPaths.isNotEmpty()) {
6667
drawnPaths.add(canceledPaths.pop())
68+
finalizePath()
6769
}
6870
}
6971

7072
/** Clear drawn paths and the bitmap image. */
7173
fun reset() {
7274
drawnPaths.clear()
7375
canceledPaths.clear()
76+
completelyDrawnPaths.clear()
7477
}
7578

7679
/** Call this function when user starts drawing a path. */
@@ -121,7 +124,8 @@ class DrawController {
121124
}
122125
}
123126

124-
fun getBitmapFlow(size: Int, subscription: DrawBoxSubscription): Flow<ImageBitmap> {
127+
fun getBitmap(size: Int, coroutineScope: CoroutineScope, subscription: DrawBoxSubscription): StateFlow<ImageBitmap> {
128+
val initialBitmap = ImageBitmap(size, size, ImageBitmapConfig.Argb8888)
125129
return flow {
126130
val bitmap = ImageBitmap(size, size, ImageBitmapConfig.Argb8888)
127131
val canvas = Canvas(bitmap)
@@ -143,6 +147,6 @@ class DrawController {
143147
)
144148
}
145149
emit(bitmap)
146-
}
150+
}.stateIn(coroutineScope, started = SharingStarted.Eagerly, initialValue = initialBitmap)
147151
}
148152
}

sample/android/build.gradle.kts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
plugins {
2+
id("org.jetbrains.compose")
3+
id("com.android.application")
4+
kotlin("android")
5+
}
6+
7+
group = Library.group
8+
version = Library.version
9+
10+
repositories {
11+
jcenter()
12+
}
13+
14+
dependencies {
15+
implementation(project(":drawbox"))
16+
implementation("androidx.activity:activity-compose:1.5.0")
17+
implementation(compose.material)
18+
implementation("androidx.appcompat:appcompat:1.5.1")
19+
implementation("androidx.core:core-ktx:1.9.0")
20+
}
21+
22+
android {
23+
compileSdk = Android.compileSdk
24+
defaultConfig {
25+
applicationId = Android.applicationId
26+
minSdk = Android.minSdk
27+
targetSdk = Android.targetSdk
28+
versionCode = Android.versionCode
29+
versionName = Library.version
30+
}
31+
compileOptions {
32+
sourceCompatibility = JavaVersion.VERSION_1_8
33+
targetCompatibility = JavaVersion.VERSION_1_8
34+
}
35+
buildTypes {
36+
getByName("release") {
37+
isMinifyEnabled = false
38+
}
39+
}
40+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.github.markyav.drawbox.android">
3+
<application
4+
android:allowBackup="false"
5+
android:supportsRtl="true"
6+
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
7+
<activity android:name=".MainActivity" android:exported="true">
8+
<intent-filter>
9+
<action android:name="android.intent.action.MAIN"/>
10+
<category android:name="android.intent.category.LAUNCHER"/>
11+
</intent-filter>
12+
</activity>
13+
</application>
14+
</manifest>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package io.github.markyav.drawbox.android
2+
3+
import android.os.Bundle
4+
import androidx.activity.compose.setContent
5+
import androidx.appcompat.app.AppCompatActivity
6+
import androidx.compose.foundation.Image
7+
import androidx.compose.foundation.border
8+
import androidx.compose.foundation.layout.*
9+
import androidx.compose.material.MaterialTheme
10+
import androidx.compose.material.Text
11+
import androidx.compose.runtime.collectAsState
12+
import androidx.compose.runtime.getValue
13+
import androidx.compose.runtime.remember
14+
import androidx.compose.runtime.rememberCoroutineScope
15+
import androidx.compose.ui.Modifier
16+
import androidx.compose.ui.graphics.Color
17+
import androidx.compose.ui.unit.dp
18+
import io.github.markyav.drawbox.box.DrawBox
19+
import io.github.markyav.drawbox.controller.DrawBoxBackground
20+
import io.github.markyav.drawbox.controller.DrawBoxSubscription
21+
import io.github.markyav.drawbox.controller.DrawController
22+
23+
class MainActivity : AppCompatActivity() {
24+
override fun onCreate(savedInstanceState: Bundle?) {
25+
super.onCreate(savedInstanceState)
26+
setContent {
27+
MaterialTheme {
28+
val controller = remember { DrawController() }
29+
val coroutineSubscription = rememberCoroutineScope()
30+
val bitmap by controller.getBitmap(250, coroutineSubscription, DrawBoxSubscription.DynamicUpdate).collectAsState()
31+
val bitmapFinishDrawingUpdate by controller.getBitmap(250, coroutineSubscription, DrawBoxSubscription.FinishDrawingUpdate).collectAsState()
32+
33+
controller.background = DrawBoxBackground.ColourBackground(color = Color.Blue, alpha = 0.15f)
34+
controller.canvasOpacity = 0.5f
35+
36+
Row {
37+
DrawBox(
38+
controller = controller,
39+
modifier = Modifier
40+
.fillMaxHeight()
41+
.aspectRatio(1f)
42+
.padding(100.dp)
43+
.border(width = 1.dp, color = Color.Blue),
44+
)
45+
Column {
46+
Text("DynamicUpdate:")
47+
Spacer(modifier = Modifier.height(10.dp))
48+
Image(
49+
bitmap,
50+
contentDescription = "drawn bitmap",
51+
modifier = Modifier.size(200.dp).border(width = 1.dp, color = Color.Red),
52+
)
53+
54+
Spacer(modifier = Modifier.height(50.dp))
55+
56+
Text("FinishDrawingUpdate:")
57+
Spacer(modifier = Modifier.height(10.dp))
58+
Image(
59+
bitmapFinishDrawingUpdate,
60+
contentDescription = "drawn bitmap",
61+
modifier = Modifier.size(200.dp).border(width = 1.dp, color = Color.Red),
62+
)
63+
}
64+
}
65+
}
66+
}
67+
}
68+
}

sample/desktop/build.gradle.kts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
2+
3+
plugins {
4+
kotlin("multiplatform")
5+
id("org.jetbrains.compose")
6+
}
7+
8+
group = Library.group
9+
version = Library.version
10+
11+
12+
kotlin {
13+
jvm {
14+
jvmToolchain(11)
15+
withJava()
16+
}
17+
sourceSets {
18+
val jvmMain by getting {
19+
dependencies {
20+
implementation(project(":drawbox"))
21+
implementation(compose.desktop.currentOs)
22+
}
23+
}
24+
val jvmTest by getting
25+
}
26+
}
27+
28+
compose.desktop {
29+
application {
30+
mainClass = "MainKt"
31+
nativeDistributions {
32+
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
33+
packageName = Library.name
34+
packageVersion = Library.version
35+
}
36+
}
37+
}

0 commit comments

Comments
 (0)