diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..b948907
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,34 @@
+# CHANGELOG
+
+## 1.4.0 (2022-04-29)
+* add `DrawingViewState` containing all the needed information to draw image on canvas
+* bump Kotlin to 1.6.21, Gradle plugin to 7.1.3
+* bump buildToolsVersion to 32.0.0, compileSdkVersion and targetSdkVersion to 32
+
+## 1.3.0 (2020-08-05)
+* bump Gradle plugin to 7.0.0
+* update publish scripts
+
+## 1.2.0 (2021-03-24)
+* add `undoAll()`, `redoAll()`, `clearRedoHistory()`, `isDrawingEmpty()`
+* add explicit callbacks parameter names to `listenerEmptyState` and `listenerDrawingInProgress`
+* add option to define canvas colour
+* remove reference to additional canvas
+* better documentation of public methods and parameters
+
+## 1.1.0 (2021-03-23)
+* add `sizeChanged` flag to determine when to create new canvas instead of creating it from
+ bitmap on every size change
+* bump Kotlin to 1.4.31, Gradle plugin to 4.1.3, Build tools to 30.0.3
+
+## 1.0.2 (2020-12-05)
+* add documentation
+* remove deprecated Kotlin extensions from example app
+* bump to Kotlin 1.4.20 and Gradle plugin 4.1.1
+
+## 1.0.1 (2020-08-24)
+* add license
+* bump Kotlin to 1.4.0, Gradle plugin to 4.0.1 and build tools to 30.0.2
+
+## 1.0.0 (2020-05-26)
+* initial public release
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 24287a9..8f6ef76 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,11 +17,6 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
@@ -40,10 +35,10 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
- implementation 'androidx.appcompat:appcompat:1.3.0'
+ implementation 'androidx.appcompat:appcompat:1.4.0'
implementation project(":drawingview")
testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.2'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8be1b4c..fba4038 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,19 +3,22 @@
package="com.vojtkovszky.drawingview.example">
-
+
+
-
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 3150a38..4aad04c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
buildscript {
ext {
- kotlin_version = "1.5.21" /* https://github.com/JetBrains/kotlin */
- dokka_version = '1.5.0' /* https://github.com/Kotlin/dokka/releases */
+ kotlin_version = "1.6.21" /* https://github.com/JetBrains/kotlin */
+ dokka_version = '1.6.20' /* https://github.com/Kotlin/dokka/releases */
}
repositories {
@@ -10,7 +10,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.0.0'
+ classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
}
diff --git a/drawingview/build.gradle b/drawingview/build.gradle
index e948cf7..47880ff 100644
--- a/drawingview/build.gradle
+++ b/drawingview/build.gradle
@@ -12,7 +12,6 @@ android {
defaultConfig {
minSdkVersion project.properties['minSdkVersion'] as Integer
targetSdkVersion project.properties['targetSdkVersion'] as Integer
- versionName project.properties['versionName'] as String
}
sourceSets {
diff --git a/drawingview/gradle.properties b/drawingview/gradle.properties
index 198b997..b16d25c 100644
--- a/drawingview/gradle.properties
+++ b/drawingview/gradle.properties
@@ -3,4 +3,4 @@ buildTypes=debug,release
groupId=com.github.mvojtkovszky
artifactId=DrawingView
moduleId=drawingview
-versionName=1.3.0
\ No newline at end of file
+versionName=1.4.0
\ No newline at end of file
diff --git a/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingView.kt b/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingView.kt
index fc012ae..614c717 100644
--- a/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingView.kt
+++ b/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingView.kt
@@ -33,21 +33,19 @@ class DrawingView @JvmOverloads constructor(
strokeWidth = 30f
}
- private val drawPathHistory = mutableListOf()
- private val drawPaintHistory = mutableListOf()
- private val undonePaths = mutableListOf()
- private val undonePaints = mutableListOf()
+ /**
+ * State holding all necessary information to populate the view and keeping track of it's
+ * active history
+ */
+ var state = DrawingViewState()
+ set(value) {
+ field = value
+ invalidate()
+ }
private var xStart: Float = 0f // reference positions for last move (x)
private var yStart: Float = 0f // reference positions for last move (y)
private var isCurrentlyMoving = false
- private var isDrawingEmpty = true // track if anything written
- set(value) {
- field = value
- if (value) {
- listenerEmptyState?.let { it(true) }
- }
- }
// endregion
// region Public attributes
@@ -117,11 +115,13 @@ class DrawingView @JvmOverloads constructor(
override fun onDraw(canvas: Canvas) {
canvas.drawColor(canvasColor)
- for (i in drawPathHistory.indices) {
- val path = drawPathHistory[i]
- val paint = drawPaintHistory[i]
- canvas.drawPath(path, paint)
+ val numStepsInHistory = state.numHistorySteps()
+ if (numStepsInHistory > 0) {
+ for (i in 0 until numStepsInHistory) {
+ canvas.drawPath(state.getPathFromHistory(i), state.getPaintFromHistory(i))
+ }
}
+
canvas.drawPath(drawPath, drawPaint)
super.onDraw(canvas)
@@ -140,8 +140,7 @@ class DrawingView @JvmOverloads constructor(
when (event.action) {
MotionEvent.ACTION_DOWN -> {
- undonePaths.clear()
- undonePaints.clear()
+ state.clearRedoHistory()
drawPath.reset()
drawPath.moveTo(touchX, touchY)
@@ -149,7 +148,7 @@ class DrawingView @JvmOverloads constructor(
xStart = touchX
yStart = touchY
- listenerDrawingInProgress?.let { it(true) }
+ listenerDrawingInProgress?.invoke(true)
}
MotionEvent.ACTION_MOVE -> {
@@ -169,16 +168,19 @@ class DrawingView @JvmOverloads constructor(
drawPath.addCircle(touchX, touchY, 0.1f, Path.Direction.CW)
}
- drawPathHistory.add(drawPath)
- drawPaintHistory.add(Paint(drawPaint))
+ val drawingEmptyBeforeAdding = state.isHistoryEmpty()
+
+ state.addToHistory(drawPath, drawPaint)
drawPath = Path()
- if (isDrawingEmpty) listenerEmptyState?.let { it(false) }
- isDrawingEmpty = false
+ // moved from empty to no longer empty
+ if (drawingEmptyBeforeAdding) {
+ listenerEmptyState?.invoke(false)
+ }
isCurrentlyMoving = false
- listenerDrawingInProgress?.let { it(false) }
+ listenerDrawingInProgress?.invoke(false)
}
else -> return false
@@ -193,28 +195,22 @@ class DrawingView @JvmOverloads constructor(
* Clear canvas. Will also clear all history
*/
fun startNew() {
- drawPathHistory.clear()
- drawPaintHistory.clear()
- undonePaths.clear()
- undonePaints.clear()
-
+ state.startNew()
invalidate()
-
- isDrawingEmpty = true
+ listenerEmptyState?.invoke(true)
}
/**
* Undo
*/
fun undo() {
- if (drawPathHistory.size > 0) {
- undonePaths.add(drawPathHistory.removeAt(drawPathHistory.size - 1))
- undonePaints.add(drawPaintHistory.removeAt(drawPaintHistory.size - 1))
+ if (!state.isHistoryEmpty()) {
+ state.undo()
invalidate()
}
- if (drawPathHistory.isEmpty()) {
- isDrawingEmpty = true
+ if (state.isHistoryEmpty()) {
+ listenerEmptyState?.invoke(true)
}
}
@@ -224,7 +220,7 @@ class DrawingView @JvmOverloads constructor(
* [redo] or [redoAll]
*/
fun undoAll() {
- repeat(drawPathHistory.size) {
+ repeat(state.numHistorySteps()) {
undo()
}
}
@@ -233,13 +229,9 @@ class DrawingView @JvmOverloads constructor(
* Redo
*/
fun redo() {
- if (undonePaths.size > 0) {
- drawPathHistory.add(undonePaths.removeAt(undonePaths.size - 1))
- drawPaintHistory.add(undonePaints.removeAt(undonePaints.size - 1))
-
+ if (!state.isUndoneEmpty()) {
+ state.redo()
invalidate()
-
- isDrawingEmpty = false
}
}
@@ -247,7 +239,7 @@ class DrawingView @JvmOverloads constructor(
* Redo all known undone steps
*/
fun redoAll() {
- repeat(undonePaths.size) {
+ repeat(state.numUndoneSteps()) {
redo()
}
}
@@ -256,7 +248,7 @@ class DrawingView @JvmOverloads constructor(
* Clears undone history, essentially making [redo] do nothing
*/
fun clearRedoHistory() {
- undonePaths.clear()
+ state.clearRedoHistory()
}
/**
@@ -271,7 +263,7 @@ class DrawingView @JvmOverloads constructor(
* Determine if canvas is empty.
*/
fun isDrawingEmpty(): Boolean {
- return isDrawingEmpty
+ return state.isHistoryEmpty()
}
// endregion
}
\ No newline at end of file
diff --git a/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingViewState.kt b/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingViewState.kt
new file mode 100644
index 0000000..5838ccd
--- /dev/null
+++ b/drawingview/src/main/kotlin/com/vojtkovszky/drawingview/DrawingViewState.kt
@@ -0,0 +1,85 @@
+package com.vojtkovszky.drawingview
+
+import android.graphics.Paint
+import android.graphics.Path
+import java.io.Serializable
+
+/**
+ * Class holding all the necessary information required to draw paths and paints
+ * on the canvas.
+ */
+class DrawingViewState: Serializable {
+
+ private val drawPathHistory = mutableListOf()
+ private val drawPaintHistory = mutableListOf()
+ private val undonePaths = mutableListOf()
+ private val undonePaints = mutableListOf()
+
+ // add path and paint to history
+ internal fun addToHistory(path: Path, paint: Paint) {
+ drawPathHistory.add(path)
+ drawPaintHistory.add(Paint(paint))
+ }
+
+ // clears redo history by cleaning undone paths and paints
+ internal fun clearRedoHistory() {
+ undonePaths.clear()
+ undonePaints.clear()
+ }
+
+ // return single path from history on index
+ internal fun getPathFromHistory(index: Int): Path {
+ return drawPathHistory[index]
+ }
+
+ // return single paint from history on index
+ internal fun getPaintFromHistory(index: Int): Paint {
+ return drawPaintHistory[index]
+ }
+
+ // return number of available undone steps
+ internal fun numUndoneSteps(): Int {
+ return undonePaths.size
+ }
+
+ // return number of available history steps
+ internal fun numHistorySteps(): Int {
+ return drawPathHistory.size
+ }
+
+ // moves latest path and pant from undone list to history list
+ // by removing from undone list and adding to history list
+ internal fun redo() {
+ drawPathHistory.add(undonePaths.removeAt(undonePaths.size - 1))
+ drawPaintHistory.add(undonePaints.removeAt(undonePaints.size - 1))
+ }
+
+ // reset the history and undone lists
+ internal fun startNew() {
+ drawPathHistory.clear()
+ drawPaintHistory.clear()
+ undonePaths.clear()
+ undonePaints.clear()
+ }
+
+ // moves latest path and pant from history list to undone list
+ // by removing from history list and adding to undone list
+ internal fun undo() {
+ undonePaths.add(drawPathHistory.removeAt(drawPathHistory.size - 1))
+ undonePaints.add(drawPaintHistory.removeAt(drawPaintHistory.size - 1))
+ }
+
+ /**
+ * Determine if we have any paths or paints in history
+ */
+ fun isHistoryEmpty(): Boolean {
+ return drawPathHistory.isEmpty() //&& drawPaintHistory.isEmpty()
+ }
+
+ /**
+ * Determine if we have any paths or paints in undo history
+ */
+ fun isUndoneEmpty(): Boolean {
+ return undonePaths.isEmpty() //&& undonePaints.isEmpty()
+ }
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 4ff0831..651e144 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,8 +20,14 @@ android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
+# Software Components will not be created automatically for Maven publishing from
+# Android Gradle Plugin 8.0. To opt-in to the future behavior, set the Gradle property
+# android.disableAutomaticComponentCreation=true in the `gradle.properties` file or use the new
+# publishing DSL.
+android.disableAutomaticComponentCreation=true
+
# base versions
-buildToolsVersion=30.0.3
-compileSdkVersion=30
+buildToolsVersion=32.0.0
+compileSdkVersion=32
minSdkVersion=16
-targetSdkVersion=30
+targetSdkVersion=32
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 796df92..8b17419 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Thu Aug 05 09:37:59 CEST 2021
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME