diff --git a/.idea/copyright/Apache.xml b/.idea/copyright/Apache.xml
new file mode 100644
index 0000000..e7e1510
--- /dev/null
+++ b/.idea/copyright/Apache.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..2102cda
--- /dev/null
+++ b/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/README.md b/README.md
index 49d38fc..569d995 100644
--- a/README.md
+++ b/README.md
@@ -133,6 +133,7 @@ val commonMain by getting {
- [Welcome](examples/welcome/welcome) - multi-module example of user on-boarding flow
- [Parallel](examples/multi/parallel) - two machines running in parallel in one proxy state
- [Navbar](examples/multi/navbar) - several machines running in proxy state, one of them active at a time
+- [Mixed](examples/multi/mixed) - two machines of different gesture/UI system mixed in one state
- [Lifecycle](examples/lifecycle) - track your Android app lifecycle to pause pending operations when the app is suspended
## The basic task - Load-Content-Error
@@ -1258,12 +1259,12 @@ private sealed class MultiGesture {
data class StringGesture(val data: String) : MultiGesture()
}
-private open class TestState : MultiMachineState() {
+private open class TestState : MultiMachineState() {
private data object IntKey : MachineKey(null) // Int for gesture and state
private data object StringKey : MachineKey(null) // String for gesture and state
- override val container: ProxyMachineContainer = AllTogetherMachineContainer(
+ override val container: ProxyMachineContainer = AllTogetherMachineContainer(
listOf(
object : MachineInit {
override val key: MachineKey = IntKey
@@ -1310,8 +1311,8 @@ private open class TestState : MultiMachineState() {
private data object StringKey : MachineKey(null) // String for gesture and state
// ... machine init omitted
-
- override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, *>?): String {
+
+ override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, out Any>?): String {
val i: Int = provider.getValue(IntKey) // Cast to Int
val s: String = provider.getValue(StringKey) // Cast to String
return "$i - $s" // Combined state of any kind you like
@@ -1347,7 +1348,7 @@ private open class TestState : MultiMachineState() {
// ... machine init omitted
// Our parent gesture is
- override fun mapGesture(parent: MultiGesture, processor: GestureProcessor) = when(parent) {
+ override fun mapGesture(parent: MultiGesture, processor: GestureProcessor) = when(parent) {
is MultiGesture.IntGesture -> {
processor.process(IntKey, parent.data) // Int expected
}
diff --git a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/CommonStateMachine.kt b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/CommonStateMachine.kt
index 7ba27f3..b9b1a4b 100644
--- a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/CommonStateMachine.kt
+++ b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/CommonStateMachine.kt
@@ -17,7 +17,7 @@ package com.motorro.commonstatemachine
* Common state machine input - from the outside world to the current state
* @param G UI gesture
*/
-interface MachineInput {
+interface MachineInput {
/**
* Updates state with UI gesture
* @param gesture UI gesture to proceed
@@ -51,7 +51,7 @@ interface MachineOutput {
/**
* Current public machine status
*/
-interface MachineStatus {
+interface MachineStatus {
/**
* Checks if machine is started
*/
@@ -71,6 +71,11 @@ interface MachineStatus {
*/
interface CommonStateMachine : MachineInput, MachineOutput, MachineStatus {
+ /**
+ * Starts the machine
+ */
+ fun start()
+
/**
* Base state-machine implementation
* @param G UI gesture
@@ -104,9 +109,9 @@ interface CommonStateMachine : MachineInput, MachineOutput : MachineInput, MachineOutput(
init: MachineInit,
- onUiChanged: (MachineKey<*, *>, Any) -> Unit
+ onUiChanged: (MachineKey, U) -> Unit
) : CommonStateMachine, Activated {
/**
* Machine lifecycle
@@ -41,7 +41,10 @@ internal class ActiveStateMachine(
{ onUiChanged(init.key, it.child) }
)
- init {
+ /**
+ * Starts the machine
+ */
+ override fun start() {
machine.start()
}
diff --git a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineAccess.kt b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineAccess.kt
index a2f6889..0cd36cc 100644
--- a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineAccess.kt
+++ b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineAccess.kt
@@ -13,24 +13,51 @@
package com.motorro.commonstatemachine.multi
-import com.motorro.commonstatemachine.CommonStateMachine
+/**
+ * Provides access to the state-machine
+ * @param CG Child gesture system
+ * @param CU Child UI-state system
+ */
+interface MachineAccess {
+ /**
+ * Keys collection
+ */
+ val keys: Set>
+
+ /**
+ * Retrieves UI state.
+ * [MachineInit] and [key] bind types securely.
+ * @param U Concrete UI state bound with the [key], subtype of CU
+ * @param key Machine key
+ */
+ fun getState(key: MachineKey<*, U>): U?
+
+ /**
+ * Processes machine gesture.
+ * [MachineInit] and [key] bind types securely.
+ * @param G Concrete gesture, subtype of th [CG]
+ * @param key Machine key
+ * @param gesture Gesture to process
+ */
+ fun process(key: MachineKey, gesture: G)
+}
/**
* Retrieves a ui-state given the [MachineKey]
*/
-interface UiStateProvider {
+interface UiStateProvider {
/**
* Retrieves all running machine keys
*/
- fun getMachineKeys(): Set>
+ fun getMachineKeys(): Set>
/**
* Gets a concrete UI-state
* @param key Machine key your state is bound to
* @throws IllegalStateException if state is not found in common state
*/
- fun getValue(key: MachineKey<*, U>): U = checkNotNull(get(key)) {
+ fun getValue(key: MachineKey<*, out U>): U = checkNotNull(get(key)) {
"Key $key not found in machine map"
}
@@ -38,30 +65,19 @@ interface UiStateProvider {
* Gets a concrete UI-state
* @param key Machine key your state is bound to
*/
- operator fun get(key: MachineKey<*, U>): U?
+ operator fun get(key: MachineKey<*, U>): U?
}
/**
* Redirects your gesture to be processed with a child machine
* identified by [MachineKey]
*/
-interface GestureProcessor {
+interface GestureProcessor {
/**
* Redirects your gesture to be processed by child machine
* if machine identified by [key] is found
* @param key Machine key
* @param gesture Gesture to process
*/
- fun process(key: MachineKey, gesture: G)
-}
-
-/**
- * Runs [block] with machine stored in [machineMap] under this key
- */
-@Suppress("UNCHECKED_CAST")
-internal inline fun withMachine(
- key: MachineKey,
- machineMap: MachineMap,
- block: CommonStateMachine.() -> R
-): R? = (machineMap[key] as? CommonStateMachine)?.block()
-
+ fun process(key: MachineKey, gesture: G)
+}
\ No newline at end of file
diff --git a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MultiMachineState.kt b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MultiMachineState.kt
index 9baff18..7c2eba2 100644
--- a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MultiMachineState.kt
+++ b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MultiMachineState.kt
@@ -21,11 +21,11 @@ import com.motorro.commonstatemachine.CommonMachineState
* - Override [mapUiState] to build a combined UI state af all the machines
* - Override [container] with a [ProxyMachineContainer] of your choice
*/
-abstract class MultiMachineState : CommonMachineState() {
+abstract class MultiMachineState : CommonMachineState() {
/**
* Proxy machines container
*/
- protected abstract val container: ProxyMachineContainer
+ protected abstract val container: ProxyMachineContainer
/**
* A part of [start] template to initialize state
@@ -45,20 +45,18 @@ abstract class MultiMachineState : CommonMachineState(
* Updates machine view-state
*/
@Suppress("UNUSED_PARAMETER")
- private fun onUiStateChange(key: MachineKey<*, *>, uiState: Any) {
+ private fun onUiStateChange(key: MachineKey<*, out CU>, uiState: CU) {
setUiState(buildUiState(key))
}
/**
* Builds common UI state
*/
- private fun buildUiState(changedKey: MachineKey<*, *>?): PU {
- val machineMap = container.getMachines()
- val uiStateProvider = object : UiStateProvider {
- override fun getMachineKeys(): Set> = machineMap.keys
- override fun get(key: MachineKey<*, U>): U? {
- return withMachine(key, machineMap) { getUiState() }
- }
+ private fun buildUiState(changedKey: MachineKey<*, out CU>?): PU {
+ val access = container.machineAccess
+ val uiStateProvider = object : UiStateProvider {
+ override fun getMachineKeys(): Set> = access.keys
+ override fun get(key: MachineKey<*, U>): U? = access.getState(key)
}
return mapUiState(uiStateProvider, changedKey)
}
@@ -74,10 +72,10 @@ abstract class MultiMachineState : CommonMachineState(
* A part of [process] template to process UI gesture
*/
override fun doProcess(gesture: PG) {
- val machineMap = container.getMachines()
- val processor = object : GestureProcessor {
- override fun process(key: MachineKey, gesture: G) {
- withMachine(key, machineMap) { process(gesture) }
+ val access = container.machineAccess
+ val processor = object : GestureProcessor {
+ override fun process(key: MachineKey, gesture: G) {
+ access.process(key, gesture)
}
}
mapGesture(gesture, processor)
@@ -88,7 +86,7 @@ abstract class MultiMachineState : CommonMachineState(
* @param parent Parent gesture
* @param processor Use it to send child gesture to the relevant child machine
*/
- protected abstract fun mapGesture(parent: PG, processor: GestureProcessor)
+ protected abstract fun mapGesture(parent: PG, processor: GestureProcessor)
/**
* Maps combined child UI state to parent
@@ -96,5 +94,5 @@ abstract class MultiMachineState : CommonMachineState(
* @param changedKey Key of machine that changed the UI state. Null if called explicitly via [updateUi]
* @see updateUi
*/
- protected abstract fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, *>?): PU
+ protected abstract fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, out CU>?): PU
}
\ No newline at end of file
diff --git a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/ProxyMachineContainer.kt b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/ProxyMachineContainer.kt
index f20feb7..dc55f0c 100644
--- a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/ProxyMachineContainer.kt
+++ b/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/ProxyMachineContainer.kt
@@ -13,25 +13,32 @@
package com.motorro.commonstatemachine.multi
+import com.motorro.commonstatemachine.CommonStateMachine
import com.motorro.commonstatemachine.ProxyStateMachine
import com.motorro.commonstatemachine.lifecycle.MachineLifecycle
/**
- * Holds proxy-machines
+ * A machine container. Holds proxied machines.
+ * The [CG] and [CU] type binding are done via explicit cast to be able
+ * to host heterogeneous machines
+ * [MachineInit] binds the key with correct machine type
+ * @param CG Child gesture system
+ * @param CU Child UI-state system
*/
-interface ProxyMachineContainer {
+interface ProxyMachineContainer {
/**
- * Starts machines
+ * Machine access
*/
- fun start(onUiChanged: (key: MachineKey<*, *>, uiState: Any) -> Unit)
+ val machineAccess: MachineAccess
/**
- * Returns a map of proxy machines
+ * Starts machines in the container
+ * @param onUiChanged UI change handler from hosting state
*/
- fun getMachines(): MachineMap
+ fun start(onUiChanged: (key: MachineKey<*, out CU>, uiState: CU) -> Unit)
/**
- * Clears machines
+ * Clears contained machines
*/
fun clear()
@@ -41,7 +48,9 @@ interface ProxyMachineContainer {
* always [MachineLifecycle.State.ACTIVE]
* @param init Machine init
*/
- fun allTogether(init: Collection>): ProxyMachineContainer = AllTogetherMachineContainer(init)
+ fun allTogether(
+ init: Collection>
+ ): ProxyMachineContainer = AllTogetherMachineContainer(init)
/**
* Creates a container where machines may be activated and deactivated
@@ -52,45 +61,130 @@ interface ProxyMachineContainer {
* @param init Machine init
* @param initiallyActive Machines that are initially active. Defaults to first machine in [init]
*/
- fun some(
- init: Collection>,
- initiallyActive: Set> = setOf(init.first().key)
- ): ActiveMachineContainer = SomeActiveMachineContainer(init, initiallyActive)
+ fun some(
+ init: Collection>,
+ initiallyActive: Set> = setOf(init.first().key)
+ ): ActiveMachineContainer = SomeActiveMachineContainer(init, initiallyActive)
+ }
+
+ /**
+ * Base machine container that binds gesture/ui type system with machines
+ * The [CG] and [CU] type binding are done via explicit cast to be able
+ * to host heterogeneous machines
+ * [MachineInit] binds the key with correct machine type
+ * @param CG Common gesture type
+ * @param CU Common UI type
+ * @param M Concrete machine type
+ * @param init Initialisation structures to create machines
+ */
+ abstract class Base>(
+ private val init: Collection>
+ ) : ProxyMachineContainer {
+ /**
+ * Creates a specific machine for this container
+ * @param init Initialization structure
+ * @param onUiChanged UI change handler from hosting state
+ */
+ abstract fun create(
+ init: MachineInit<*, out CU>,
+ onUiChanged: (key: MachineKey<*, out CU>, uiState: CU) -> Unit
+ ): M
+
+ /**
+ * Machines bound with keys
+ */
+ protected var machines: Map, M> = emptyMap()
+
+ /**
+ * Machine access
+ */
+ override val machineAccess: MachineAccess = object : MachineAccess {
+ /**
+ * Keys collection
+ */
+ override val keys: Set> get() = machines.keys
+
+ /**
+ * Processes machine gesture.
+ * [MachineInit] and [key] bind types securely.
+ * @param G Concrete gesture, subtype of th [CG]
+ * @param key Machine key
+ * @param gesture Gesture to process
+ */
+ @Suppress("UNCHECKED_CAST")
+ override fun process(key: MachineKey, gesture: G) {
+ (machines[key] as? CommonStateMachine)?.process(gesture)
+ }
+
+ /**
+ * Retrieves UI state.
+ * [MachineInit] and [key] bind types securely.
+ * @param U Concrete UI state bound with the [key], subtype of CU
+ * @param key Machine key
+ */
+ @Suppress("UNCHECKED_CAST")
+ override fun getState(key: MachineKey<*, U>): U? {
+ return machines[key]?.getUiState() as? U
+ }
+ }
+
+ /**
+ * Starts machines in the container
+ * @param onUiChanged UI change handler from hosting state
+ */
+ override fun start(onUiChanged: (key: MachineKey<*, out CU>, uiState: CU) -> Unit) {
+ machines = init.associate { i -> i.key to create(i, onUiChanged) }
+ machines.forEach { (_, machine) -> machine.start() }
+ doStart()
+ }
+
+ /**
+ * A part of [start] template called after initial startup
+ * Machines are created at this point
+ */
+ open fun doStart() = Unit
+
+ /**
+ * Clears contained machines
+ */
+ override fun clear() {
+ machines.forEach { (_, machine) -> machine.clear() }
+ }
}
}
/**
* Container that activates machine
*/
-interface ActiveMachineContainer : ProxyMachineContainer {
+interface ActiveMachineContainer : ProxyMachineContainer {
/**
* Retrieves currently active machine key
*/
- fun getActive(): Set>
+ fun getActive(): Set>
/**
* Sets active machine given the keys
*/
- fun setActive(keys: Set>)
+ fun setActive(keys: Set>)
/**
* Sets active machine given the key
*/
- fun setActive(vararg key: MachineKey<*, *>) = setActive(key.toSet())
+ fun setActive(vararg key: MachineKey<*, out CU>) = setActive(key.toSet())
/**
* Disposes machines. All machines by [keys] are deactivated disposed and dereferenced.
* When activating again - a new machine is created using the same init.
* Use to cleanup memory for example on low memory alert from system
*/
- fun dispose(keys: Set>)
+ fun dispose(keys: Set>)
/**
* Disposes machines. All machines by [key] are deactivated disposed and dereferenced.
* When activating again - a new machine is created using the same init.
* Use to cleanup memory for example on low memory alert from system
*/
- fun dispose(vararg key: MachineKey<*, *>) = dispose(key.toSet())
+ fun dispose(vararg key: MachineKey<*, out CU>) = dispose(key.toSet())
/**
* Disposes all inactive machines
@@ -103,13 +197,9 @@ interface ActiveMachineContainer : ProxyMachineContainer {
* All machines run in parallel without any lifecycle management
* @param init Machine init
*/
-internal class AllTogetherMachineContainer(private val init: Collection>) : ProxyMachineContainer {
-
- /**
- * Proxy machines
- */
- private var machines: Map, ProxyStateMachine<*, *>> = emptyMap()
-
+internal class AllTogetherMachineContainer(
+ init: Collection>
+) : ProxyMachineContainer.Base>(init) {
/**
* Machine lifecycle that is always started
*/
@@ -121,34 +211,23 @@ internal class AllTogetherMachineContainer(private val init: Collection MachineInit.machine(onUiChanged: (key: MachineKey<*, *>, uiState: Any) -> Unit) = ProxyStateMachine(
+ private fun MachineInit<*, U>.machine(onUiChanged: (MachineKey<*, U>, U) -> Unit) = ProxyStateMachine(
initialUiState,
{ init(lifecycle) },
{ onUiChanged(key, it) }
)
/**
- * Starts machines
- */
- override fun start(onUiChanged: (key: MachineKey<*, *>, uiState: Any) -> Unit) {
- machines = init.associate { i -> i.key to i.machine(onUiChanged) }
- machines.forEach { it.value.start() }
- }
-
- /**
- * Returns a map of proxy machines
- */
- override fun getMachines(): MachineMap = machines
-
- /**
- * Clears machines
+ * Creates a specific machine for this container
+ * @param init Initialization structure
+ * @param onUiChanged UI change handler from hosting state
*/
- override fun clear() {
- machines.forEach { it.value.clear() }
- }
+ override fun create(
+ init: MachineInit<*, out CU>,
+ onUiChanged: (key: MachineKey<*, out CU>, uiState: CU) -> Unit
+ ): CommonStateMachine<*, out CU> = init.machine(onUiChanged)
}
/**
@@ -157,47 +236,39 @@ internal class AllTogetherMachineContainer(private val init: Collection>,
- private val initiallyActive: Set>
-) : ActiveMachineContainer {
-
+internal class SomeActiveMachineContainer(
+ private val init: Collection>,
+ private val initiallyActive: Set>
+) : ProxyMachineContainer.Base>(init), ActiveMachineContainer {
/**
- * Proxy machines
+ * Creates a specific machine for this container
+ * @param init Initialization structure
+ * @param onUiChanged UI change handler from hosting state
*/
- private var machines: Map, ActiveStateMachine<*, *>> = emptyMap()
+ override fun create(
+ init: MachineInit<*, out CU>,
+ onUiChanged: (key: MachineKey<*, out CU>, uiState: CU) -> Unit
+ ): ActiveStateMachine<*, out CU> = ActiveStateMachine(init, onUiChanged)
/**
- * Starts machines
+ * A part of [start] template called after initial startup
+ * Machines are created at this point
*/
- override fun start(onUiChanged: (key: MachineKey<*, *>, uiState: Any) -> Unit) {
- machines = init.associate { i -> i.key to ActiveStateMachine(i, onUiChanged) }
+ override fun doStart() {
setActive(initiallyActive)
}
- /**
- * Returns a map of proxy machines
- */
- override fun getMachines(): MachineMap = machines
-
- /**
- * Clears machines
- */
- override fun clear() {
- machines.forEach { it.value.clear() }
- }
-
/**
* Retrieves currently active machine key
*/
- override fun getActive(): Set> {
- return machines.entries.filter { (_, machine) -> machine.isActive() }.map { it.key }.toSet()
- }
+ override fun getActive(): Set> = machines.entries
+ .filter { (_, machine) -> machine.isActive() }
+ .map { it.key }.toSet()
/**
* Sets active machine given the key
*/
- override fun setActive(keys: Set>) {
+ override fun setActive(keys: Set>) {
val active = getActive()
val toDeactivate = active.minus(keys)
val toActivate = keys.minus(active)
@@ -215,7 +286,7 @@ internal class SomeActiveMachineContainer(
* When activating again - a new machine is created using the same init.
* Use to cleanup memory for example on low memory alert from system
*/
- override fun dispose(keys: Set>) {
+ override fun dispose(keys: Set>) {
machines.forEach { (key, machine) ->
if (keys.contains(key)) {
machine.dispose()
diff --git a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/mocks.kt b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/mocks.kt
index c8a9269..f31c535 100644
--- a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/mocks.kt
+++ b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/mocks.kt
@@ -40,8 +40,13 @@ class MachineMock(uiState: U) : CommonStateMachine {
val processed = mutableListOf()
val uiStates = mutableListOf(uiState)
var cleared = false
+ var started = false
+
+ override fun start() {
+ started = true
+ }
- override fun isStarted(): Boolean = true
+ override fun isStarted(): Boolean = started
override fun getUiState(): U = uiStates.last()
diff --git a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/ActiveStateMachineTest.kt b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/ActiveStateMachineTest.kt
index 88482e2..d8384d6 100644
--- a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/ActiveStateMachineTest.kt
+++ b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/ActiveStateMachineTest.kt
@@ -47,6 +47,7 @@ class ActiveStateMachineTest {
}
}
machine = ActiveStateMachine(init) { _, u -> uiState.add(u) }
+ machine.start()
}
@Test
diff --git a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/MultiMachineStateTest.kt b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/MultiMachineStateTest.kt
index ab59e39..e97d70a 100644
--- a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/MultiMachineStateTest.kt
+++ b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/MultiMachineStateTest.kt
@@ -44,8 +44,8 @@ class MultiMachineStateTest {
data class StringGesture(val data: String) : MultiGesture()
}
- private open class TestState : MultiMachineState() {
- override val container: ProxyMachineContainer = AllTogetherMachineContainer(
+ private open class TestState : MultiMachineState() {
+ override val container: ProxyMachineContainer = AllTogetherMachineContainer(
listOf(
object : MachineInit {
override val key: MachineKey = IntKey
@@ -64,7 +64,7 @@ class MultiMachineStateTest {
)
)
- override fun mapGesture(parent: MultiGesture, processor: GestureProcessor) = when(parent) {
+ override fun mapGesture(parent: MultiGesture, processor: GestureProcessor) = when(parent) {
is MultiGesture.IntGesture -> {
processor.process(IntKey, parent.data)
}
@@ -73,7 +73,7 @@ class MultiMachineStateTest {
}
}
- override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, *>?): String {
+ override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, out Any>?): String {
val i: Int = provider.getValue(IntKey)
val s: String = provider.getValue(StringKey)
return "$i - $s"
@@ -110,7 +110,7 @@ class MultiMachineStateTest {
fun providesActiveMachinesKeys() {
var tested = false
val state = object : TestState() {
- override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, *>?): String {
+ override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, out Any>?): String {
assertEquals(
setOf(IntKey, StringKey),
provider.getMachineKeys()
diff --git a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/SomeActiveMachineContainerTest.kt b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/SomeActiveMachineContainerTest.kt
index dd0218f..3f13f8b 100644
--- a/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/SomeActiveMachineContainerTest.kt
+++ b/commonstatemachine/src/commonTest/kotlin/com/motorro/commonstatemachine/multi/SomeActiveMachineContainerTest.kt
@@ -26,7 +26,7 @@ class SomeActiveMachineContainerTest {
private lateinit var intState: StateMock
private lateinit var stringState: StateMock
- private lateinit var container: SomeActiveMachineContainer
+ private lateinit var container: SomeActiveMachineContainer
private val intKey = object : MachineKey() { }
private val stringKey = object : MachineKey() { }
diff --git a/coroutines/src/commonTest/kotlin/com/motorro/commonstatemachine/coroutines/mocks.kt b/coroutines/src/commonTest/kotlin/com/motorro/commonstatemachine/coroutines/mocks.kt
index 9211f40..70090fb 100644
--- a/coroutines/src/commonTest/kotlin/com/motorro/commonstatemachine/coroutines/mocks.kt
+++ b/coroutines/src/commonTest/kotlin/com/motorro/commonstatemachine/coroutines/mocks.kt
@@ -43,8 +43,13 @@ class MachineMock(uiState: U) : CommonStateMachine {
val processed = mutableListOf()
val uiStates = mutableListOf(uiState)
var cleared = false
+ var started = false
+
+ override fun start() {
+ started = true
+ }
- override fun isStarted(): Boolean = true
+ override fun isStarted(): Boolean = started
override fun getUiState(): U = uiStates.last()
diff --git a/examples/multi/mixed/.gitignore b/examples/multi/mixed/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/examples/multi/mixed/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/examples/multi/mixed/build.gradle.kts b/examples/multi/mixed/build.gradle.kts
new file mode 100644
index 0000000..862f4d5
--- /dev/null
+++ b/examples/multi/mixed/build.gradle.kts
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
+plugins {
+ alias(libs.plugins.android.app)
+ alias(libs.plugins.kotlin.android)
+}
+
+val versionCode: String by project.extra
+val versionName: String by project.extra
+val androidMinSdkVersion: Int by project.extra
+val androidTargetSdkVersion: Int by project.extra
+val androidCompileSdkVersion: Int by project.extra
+
+android {
+ namespace = "com.motorro.statemachine.multi.mixed"
+ compileSdk = androidCompileSdkVersion
+
+ defaultConfig {
+ applicationId = "com.motorro.statemachine.multi.mixed"
+ minSdk = androidMinSdkVersion
+ targetSdk = androidTargetSdkVersion
+ versionCode = versionCode
+ versionName = versionName
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ vectorDrawables {
+ useSupportLibrary = true
+ }
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ isCoreLibraryDesugaringEnabled = true
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+ kotlinOptions {
+ jvmTarget = "17"
+ }
+ buildFeatures {
+ compose = true
+ }
+ composeOptions {
+ kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
+ }
+ packaging {
+ resources {
+ excludes += "/META-INF/{AL2.0,LGPL2.1}"
+ }
+ }
+}
+
+dependencies {
+ implementation(project(":commonstatemachine"))
+ implementation(project(":coroutines"))
+ implementation(project(":examples:commoncore"))
+ implementation(project(":examples:androidcore"))
+ implementation(project(":examples:timer"))
+
+ coreLibraryDesugaring(libs.desugaring)
+
+ implementation(libs.androidx.core)
+ implementation(libs.androidx.lifecycle.runtime)
+ implementation(libs.androidx.lifecycle.livedata)
+ implementation(libs.androidx.lifecycle.viewmodel)
+
+ implementation(libs.kotlin.coroutines.core)
+ implementation(libs.kotlin.coroutines.android)
+
+ implementation(libs.bundles.compose.core)
+ implementation(libs.compose.activity)
+ implementation(libs.compose.viewmodel)
+ implementation(libs.compose.foundation)
+ implementation(libs.compose.foundation.layouts)
+
+ debugImplementation(libs.compose.tooling)
+
+ testImplementation(libs.bundles.test.core)
+ testImplementation(libs.test.androidx.arch)
+ testImplementation(libs.test.kotlin.coroutines)
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/proguard-rules.pro b/examples/multi/mixed/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/examples/multi/mixed/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/AndroidManifest.xml b/examples/multi/mixed/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..dff16cc
--- /dev/null
+++ b/examples/multi/mixed/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/App.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/App.kt
new file mode 100644
index 0000000..7809c87
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/App.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed
+
+import android.app.Application
+import timber.log.Timber
+
+class App : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ setupLogger()
+ }
+
+ private fun setupLogger() {
+ Timber.plant(Timber.DebugTree())
+ }
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/MainActivity.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/MainActivity.kt
new file mode 100644
index 0000000..080b13c
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/MainActivity.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Button
+import androidx.compose.material3.ButtonDefaults
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.unit.dp
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.motorro.statemachine.androidcore.ui.theme.CommonStateMachineTheme
+import com.motorro.statemachine.mixed.model.MainViewModel
+import com.motorro.statemachine.mixed.model.data.MixedGesture
+import com.motorro.statemachine.mixed.model.data.SomeGesture
+import com.motorro.statemachine.mixed.model.data.SomeUiState
+import com.motorro.statemachine.timer.ui.TimerScreen
+
+class MainActivity : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContent {
+ val model: MainViewModel = viewModel()
+ val state by model.uiState.collectAsState()
+
+ CommonStateMachineTheme {
+ Scaffold { padding ->
+ Column(
+ Modifier
+ .fillMaxSize()
+ .padding(padding),
+ verticalArrangement = Arrangement.SpaceEvenly
+ ) {
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f)
+ .padding(8.dp)
+ .border(1.dp, Color.Black),
+ contentAlignment = Alignment.Center
+ ) {
+ Button(
+ colors = ButtonDefaults.buttonColors(
+ containerColor = when(state.some) {
+ SomeUiState.Off -> Color.Red
+ SomeUiState.On -> Color.Green
+ }
+ ),
+ onClick = { model.update(MixedGesture.Some(SomeGesture.StateToggled)) }
+ ) {
+ Text(
+ text = when(state.some) {
+ SomeUiState.Off -> "Off"
+ SomeUiState.On -> "On"
+ }
+ )
+ }
+ }
+ Box(
+ modifier = Modifier
+ .fillMaxWidth()
+ .weight(1f)
+ .padding(8.dp)
+ .border(1.dp, Color.Black)
+ ) {
+ TimerScreen(
+ modifier = Modifier.padding(padding),
+ title = "Bottom",
+ state = state.timer
+ ) {
+ model.update(MixedGesture.Timer(it))
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/MainViewModel.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/MainViewModel.kt
new file mode 100644
index 0000000..978851f
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/MainViewModel.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model
+
+import androidx.lifecycle.ViewModel
+import com.motorro.commonstatemachine.coroutines.FlowStateMachine
+import com.motorro.statemachine.mixed.model.data.MixedGesture
+import com.motorro.statemachine.mixed.model.data.MixedUiState
+import com.motorro.statemachine.mixed.model.data.SomeUiState
+import com.motorro.statemachine.mixed.model.state.MixedState
+import com.motorro.statemachine.timer.data.TimerUiState
+import kotlinx.coroutines.flow.StateFlow
+import kotlin.time.Duration
+
+class MainViewModel : ViewModel() {
+ private val machine = FlowStateMachine(MixedUiState(SomeUiState.Off, TimerUiState.Stopped(Duration.ZERO))) {
+ MixedState()
+ }
+
+ val uiState: StateFlow get() = machine.uiState
+
+ fun update(gesture: MixedGesture) = machine.process(gesture)
+
+ override fun onCleared() {
+ machine.clear()
+ }
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedGesture.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedGesture.kt
new file mode 100644
index 0000000..60cee14
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedGesture.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model.data
+
+import com.motorro.statemachine.timer.data.TimerGesture
+
+/**
+ * Application gestures
+ */
+sealed class MixedGesture {
+ /**
+ * Some gesture
+ */
+ data class Some(val gesture: SomeGesture) : MixedGesture()
+
+ /**
+ * Timer gesture
+ */
+ data class Timer(val gesture: TimerGesture) : MixedGesture()
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedUiState.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedUiState.kt
new file mode 100644
index 0000000..296ad07
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/MixedUiState.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model.data
+
+import androidx.compose.runtime.Immutable
+import com.motorro.statemachine.timer.data.TimerUiState
+
+/**
+ * Common state for both active machines
+ */
+@Immutable
+data class MixedUiState(
+ val some: SomeUiState,
+ val timer: TimerUiState
+)
\ No newline at end of file
diff --git a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineMap.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeGesture.kt
similarity index 74%
rename from commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineMap.kt
rename to examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeGesture.kt
index 9c26a7a..193d9ab 100644
--- a/commonstatemachine/src/commonMain/kotlin/com/motorro/commonstatemachine/multi/MachineMap.kt
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeGesture.kt
@@ -11,11 +11,14 @@
* limitations under the License.
*/
-package com.motorro.commonstatemachine.multi
-
-import com.motorro.commonstatemachine.CommonStateMachine
+package com.motorro.statemachine.mixed.model.data
/**
- * A map of state machines
+ * Some gesture
*/
-internal typealias MachineMap = Map, CommonStateMachine<*, *>>
+sealed class SomeGesture {
+ /**
+ * State toggled
+ */
+ data object StateToggled : SomeGesture()
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeUiState.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeUiState.kt
new file mode 100644
index 0000000..22053fa
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/data/SomeUiState.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model.data
+
+/**
+ * Some UI state
+ */
+sealed class SomeUiState {
+ /**
+ * Something is ON
+ */
+ data object On : SomeUiState()
+
+ /**
+ * Something is off
+ */
+ data object Off : SomeUiState()
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/MixedState.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/MixedState.kt
new file mode 100644
index 0000000..ae82198
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/MixedState.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model.state
+
+import com.motorro.commonstatemachine.CommonMachineState
+import com.motorro.commonstatemachine.lifecycle.MachineLifecycle
+import com.motorro.commonstatemachine.multi.GestureProcessor
+import com.motorro.commonstatemachine.multi.MachineInit
+import com.motorro.commonstatemachine.multi.MachineKey
+import com.motorro.commonstatemachine.multi.MultiMachineState
+import com.motorro.commonstatemachine.multi.ProxyMachineContainer
+import com.motorro.commonstatemachine.multi.UiStateProvider
+import com.motorro.statemachine.commoncore.log.Logger
+import com.motorro.statemachine.mixed.model.data.MixedGesture
+import com.motorro.statemachine.mixed.model.data.MixedUiState
+import com.motorro.statemachine.mixed.model.data.SomeGesture
+import com.motorro.statemachine.mixed.model.data.SomeUiState
+import com.motorro.statemachine.timer.data.TimerGesture
+import com.motorro.statemachine.timer.data.TimerKey
+import com.motorro.statemachine.timer.data.TimerUiState
+import com.motorro.statemachine.timer.state.TimerState
+import kotlin.time.Duration
+
+/**
+ * Machines run in parallel. All machines are active
+ */
+internal class MixedState : MultiMachineState() {
+ private val someKey = object : MachineKey("some") { }
+ private val timerKey = TimerKey("bottom")
+
+ /**
+ * Machines run in parallel and always active
+ */
+ override val container: ProxyMachineContainer = ProxyMachineContainer.allTogether(
+ listOf(
+ object : MachineInit {
+ override val key: MachineKey = someKey
+ override val initialUiState: SomeUiState = SomeUiState.Off
+ override val init: (MachineLifecycle) -> CommonMachineState = {
+ SomeState()
+ }
+ },
+ object : MachineInit {
+ override val key: TimerKey = timerKey
+ override val initialUiState: TimerUiState = TimerUiState.Stopped(Duration.ZERO)
+ override val init: (MachineLifecycle) -> CommonMachineState = {
+ val tag = requireNotNull(key.tag)
+ Logger.i("Creating machine for $tag")
+ TimerState.init(tag, it)
+ }
+ }
+ )
+ )
+
+ /**
+ * Updates child machines with gestures if relevant
+ * @param parent Parent gesture
+ * @param processor Use it to send child gesture to the relevant child machine
+ */
+ override fun mapGesture(parent: MixedGesture, processor: GestureProcessor) = when(parent) {
+ is MixedGesture.Some -> {
+ Logger.i("Top gesture: $parent")
+ processor.process(someKey, parent.gesture)
+ }
+ is MixedGesture.Timer -> {
+ Logger.i("Bottom gesture: $parent")
+ processor.process(timerKey, parent.gesture)
+ }
+ }
+
+ /**
+ * Maps combined child UI state to parent
+ * @param provider Provides child UI states
+ * @param changedKey Key of machine that changed the UI state. Null if called explicitly via [updateUi]
+ * @see updateUi
+ */
+ override fun mapUiState(
+ provider: UiStateProvider,
+ changedKey: MachineKey<*, out Any>?
+ ): MixedUiState = MixedUiState(
+ some = provider.getValue(someKey),
+ timer = provider.getValue(timerKey)
+ )
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/SomeState.kt b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/SomeState.kt
new file mode 100644
index 0000000..b0ed608
--- /dev/null
+++ b/examples/multi/mixed/src/main/java/com/motorro/statemachine/mixed/model/state/SomeState.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorro.statemachine.mixed.model.state
+
+import com.motorro.commonstatemachine.CommonMachineState
+import com.motorro.statemachine.mixed.model.data.SomeGesture
+import com.motorro.statemachine.mixed.model.data.SomeUiState
+
+/**
+ * Some machine state with internal data
+ */
+class SomeState : CommonMachineState() {
+
+ private var isOn = false
+
+ override fun doStart() {
+ render()
+ }
+
+ override fun doProcess(gesture: SomeGesture) {
+ isOn = isOn.not()
+ render()
+ }
+
+ private fun render() {
+ setUiState(if (isOn) SomeUiState.On else SomeUiState.Off)
+ }
+}
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/drawable/ic_launcher_background.xml b/examples/multi/mixed/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..7469e64
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/multi/mixed/src/main/res/drawable/ic_launcher_foreground.xml b/examples/multi/mixed/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 0000000..c499cdf
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..d18dad9
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..d18dad9
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher.webp b/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 0000000..c209e78
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..b2dfe3d
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher.webp b/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 0000000..4f0f1d6
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..62b611d
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher.webp b/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 0000000..948a307
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..1b9a695
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..28d4b77
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9287f50
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 0000000..aa7d642
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 0000000..9126ae3
Binary files /dev/null and b/examples/multi/mixed/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/examples/multi/mixed/src/main/res/values/colors.xml b/examples/multi/mixed/src/main/res/values/colors.xml
new file mode 100644
index 0000000..4ccd21c
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/values/colors.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/values/strings.xml b/examples/multi/mixed/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e81002c
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/values/strings.xml
@@ -0,0 +1,16 @@
+
+
+
+ Parallel
+
\ No newline at end of file
diff --git a/examples/multi/mixed/src/main/res/values/themes.xml b/examples/multi/mixed/src/main/res/values/themes.xml
new file mode 100644
index 0000000..fe0d9c1
--- /dev/null
+++ b/examples/multi/mixed/src/main/res/values/themes.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/App.kt b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/App.kt
index d89214f..d0a9593 100644
--- a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/App.kt
+++ b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/App.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Nikolai Kotchetkov.
+ * Copyright 2023 Nikolai Kotchetkov.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
diff --git a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/MainViewModel.kt b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/MainViewModel.kt
index d64f97a..03754c4 100644
--- a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/MainViewModel.kt
+++ b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/MainViewModel.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.navbar.model
import androidx.lifecycle.ViewModel
diff --git a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarGesture.kt b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarGesture.kt
index f25cf8c..b501208 100644
--- a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarGesture.kt
+++ b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarGesture.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.navbar.model.data
import com.motorro.statemachine.timer.data.TimerGesture
diff --git a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarUiState.kt b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarUiState.kt
index 147d72f..dcc91ce 100644
--- a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarUiState.kt
+++ b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/data/NavbarUiState.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.navbar.model.data
import androidx.compose.runtime.Immutable
diff --git a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/state/NavbarState.kt b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/state/NavbarState.kt
index 486550e..3e27426 100644
--- a/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/state/NavbarState.kt
+++ b/examples/multi/navbar/src/main/java/com/motorro/statemachine/navbar/model/state/NavbarState.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.navbar.model.state
import com.motorro.commonstatemachine.CommonMachineState
@@ -21,7 +34,7 @@ import kotlin.time.Duration
/**
* Machines are lazily created and paused when not active
*/
-internal class NavbarState : MultiMachineState() {
+internal class NavbarState : MultiMachineState() {
private val keys = listOf(
TimerKey("one"),
@@ -33,7 +46,7 @@ internal class NavbarState : MultiMachineState() {
/**
* Machines are lazily created and paused when not active
*/
- override val container: ActiveMachineContainer = ProxyMachineContainer.some(
+ override val container: ActiveMachineContainer = ProxyMachineContainer.some(
keys.map { key ->
object : MachineInit {
override val key: TimerKey = key
@@ -52,7 +65,7 @@ internal class NavbarState : MultiMachineState() {
* @param parent Parent gesture
* @param processor Use it to send child gesture to the relevant child machine
*/
- override fun mapGesture(parent: NavbarGesture, processor: GestureProcessor) = when(parent) {
+ override fun mapGesture(parent: NavbarGesture, processor: GestureProcessor) = when(parent) {
is NavbarGesture.ActiveSelected -> {
Logger.i("Activating: ${parent.key}")
container.setActive(parent.key)
@@ -74,7 +87,7 @@ internal class NavbarState : MultiMachineState() {
* @param changedKey Key of machine that changed the UI state. Null if called explicitly via [updateUi]
* @see updateUi
*/
- override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, *>?): NavbarUiState {
+ override fun mapUiState(provider: UiStateProvider, changedKey: MachineKey<*, out TimerUiState>?): NavbarUiState {
return NavbarUiState(
keys.map { key ->
key to provider.getValue(key)
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/App.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/App.kt
index 548585e..c72ebf9 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/App.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/App.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Nikolai Kotchetkov.
+ * Copyright 2023 Nikolai Kotchetkov.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/MainActivity.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/MainActivity.kt
index 773e569..59186af 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/MainActivity.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/MainActivity.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.parallel
import android.os.Bundle
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/MainViewModel.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/MainViewModel.kt
index 7ef5231..fe88091 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/MainViewModel.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/MainViewModel.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.parallel.model
import androidx.lifecycle.ViewModel
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelGesture.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelGesture.kt
index 1a9a3d5..fdb9081 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelGesture.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelGesture.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.parallel.model.data
import com.motorro.statemachine.timer.data.TimerGesture
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelUiState.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelUiState.kt
index ec7e9ea..93cba4e 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelUiState.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/data/ParallelUiState.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.parallel.model.data
import androidx.compose.runtime.Immutable
diff --git a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/state/ParallelState.kt b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/state/ParallelState.kt
index 7310631..0df4d43 100644
--- a/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/state/ParallelState.kt
+++ b/examples/multi/parallel/src/main/java/com/motorro/statemachine/parallel/model/state/ParallelState.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.parallel.model.state
import com.motorro.commonstatemachine.CommonMachineState
@@ -20,14 +33,14 @@ import kotlin.time.Duration
/**
* Machines run in parallel. All machines are active
*/
-internal class ParallelState : MultiMachineState() {
+internal class ParallelState : MultiMachineState() {
private val topKey = TimerKey("top")
private val bottomKey = TimerKey("bottom")
/**
* Machines run in parallel and always active
*/
- override val container: ProxyMachineContainer = ProxyMachineContainer.allTogether(
+ override val container: ProxyMachineContainer = ProxyMachineContainer.allTogether(
listOf(
object : MachineInit {
override val key: TimerKey = topKey
@@ -55,7 +68,7 @@ internal class ParallelState : MultiMachineState) = when(parent) {
is ParallelGesture.Top -> {
Logger.i("Top gesture: $parent")
processor.process(topKey, parent.gesture)
@@ -72,7 +85,10 @@ internal class ParallelState : MultiMachineState?): ParallelUiState = ParallelUiState(
+ override fun mapUiState(
+ provider: UiStateProvider,
+ changedKey: MachineKey<*, out TimerUiState>?
+ ): ParallelUiState = ParallelUiState(
top = provider.getValue(topKey),
bottom = provider.getValue(bottomKey)
)
diff --git a/examples/timer/build.gradle.kts b/examples/timer/build.gradle.kts
index 1cdabb8..b93eb95 100644
--- a/examples/timer/build.gradle.kts
+++ b/examples/timer/build.gradle.kts
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Nikolai Kotchetkov.
+ * Copyright 2023 Nikolai Kotchetkov.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
diff --git a/examples/timer/src/androidMain/kotlin/com/motorro/statemachine/timer/ui/TimerScreen.kt b/examples/timer/src/androidMain/kotlin/com/motorro/statemachine/timer/ui/TimerScreen.kt
index 86826de..5416064 100644
--- a/examples/timer/src/androidMain/kotlin/com/motorro/statemachine/timer/ui/TimerScreen.kt
+++ b/examples/timer/src/androidMain/kotlin/com/motorro/statemachine/timer/ui/TimerScreen.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.timer.ui
import androidx.compose.foundation.layout.Arrangement
diff --git a/examples/timer/src/commonMain/kotlin/com/motorro/statemachine/timer/state/TimerState.kt b/examples/timer/src/commonMain/kotlin/com/motorro/statemachine/timer/state/TimerState.kt
index e18bc95..5e7cd4b 100644
--- a/examples/timer/src/commonMain/kotlin/com/motorro/statemachine/timer/state/TimerState.kt
+++ b/examples/timer/src/commonMain/kotlin/com/motorro/statemachine/timer/state/TimerState.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.timer.state
import com.motorro.commonstatemachine.coroutines.CoroutineState
diff --git a/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/RunningTest.kt b/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/RunningTest.kt
index 22c378f..90fdc1a 100644
--- a/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/RunningTest.kt
+++ b/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/RunningTest.kt
@@ -1,3 +1,16 @@
+/*
+ * Copyright 2023 Nikolai Kotchetkov.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package com.motorro.statemachine.timer.state
import com.motorro.commonstatemachine.lifecycle.ActivatedMachineLifecycle
diff --git a/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/mocks.kt b/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/mocks.kt
index b25ebd0..9a68d43 100644
--- a/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/mocks.kt
+++ b/examples/timer/src/commonTest/kotlin/com/motorro/statemachine/timer/state/mocks.kt
@@ -1,5 +1,5 @@
/*
- * Copyright 2022 Nikolai Kotchetkov.
+ * Copyright 2023 Nikolai Kotchetkov.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -21,8 +21,13 @@ class MachineMock(uiState: U) : CommonStateMachine {
val processed = mutableListOf()
val uiStates = mutableListOf(uiState)
var cleared = false
+ var started = false
- override fun isStarted(): Boolean = true
+ override fun start() {
+ started = true
+ }
+
+ override fun isStarted(): Boolean = started
override fun getUiState(): U = uiStates.last()
diff --git a/examples/welcome/commonregister/src/commonTest/kotlin/com/motorro/statemachine/register/mocks.kt b/examples/welcome/commonregister/src/commonTest/kotlin/com/motorro/statemachine/register/mocks.kt
index 63e27f9..0eeeb1e 100644
--- a/examples/welcome/commonregister/src/commonTest/kotlin/com/motorro/statemachine/register/mocks.kt
+++ b/examples/welcome/commonregister/src/commonTest/kotlin/com/motorro/statemachine/register/mocks.kt
@@ -53,6 +53,11 @@ class MachineMock : CommonStateMachine {
val processed = mutableListOf()
val uiStates = mutableListOf()
var cleared = false
+ var started = false
+
+ override fun start() {
+ started = true
+ }
override fun isStarted(): Boolean = true