1+ /*
2+ * Hikage - An Android responsive UI building tool.
3+ * Copyright (C) 2019 HighCapable
4+ * https://github.com/BetterAndroid/Hikage
5+ *
6+ * Apache License Version 2.0
7+ *
8+ * Licensed under the Apache License, Version 2.0 (the "License");
9+ * you may not use this file except in compliance with the License.
10+ * You may obtain a copy of the License at
11+ *
12+ * https://www.apache.org/licenses/LICENSE-2.0
13+ *
14+ * Unless required by applicable law or agreed to in writing, software
15+ * distributed under the License is distributed on an "AS IS" BASIS,
16+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+ * See the License for the specific language governing permissions and
18+ * limitations under the License.
19+ *
20+ * This file is created by fankes on 2025/5/2.
21+ */
22+ @file:Suppress(" unused" )
23+ @file:JvmName(" StateUtils" )
24+
25+ package com.highcapable.hikage.core.runtime
26+
27+ import com.highcapable.hikage.core.Hikage
28+ import kotlin.properties.ReadWriteProperty
29+ import kotlin.reflect.KProperty
30+
31+ /* *
32+ * Definition a [Hikage] runtime state interface.
33+ */
34+ interface State <T > : ReadWriteProperty <Any ?, T >
35+
36+ /* *
37+ * Definition a [Hikage] runtime state interface for non-nullable type.
38+ */
39+ interface NonNullState <T > : State <T > {
40+
41+ /* * The current value of the state. */
42+ var value: T
43+
44+ /* *
45+ * Observe the state changes.
46+ * @param observer the observer to be notified when the state changes.
47+ */
48+ fun observe (observer : (T ) -> Unit )
49+ }
50+
51+ /* *
52+ * Definition a [Hikage] runtime state interface for nullable type.
53+ */
54+ interface NullableState <T > : State <T ?> {
55+
56+ /* * The current value of the state. */
57+ var value: T ?
58+
59+ /* *
60+ * Observe the state changes.
61+ * @param observer the observer to be notified when the state changes.
62+ */
63+ fun observe (observer : (T ? ) -> Unit )
64+ }
65+
66+ /* *
67+ * Implementing the [State] interface mutable state of [Hikage].
68+ */
69+ class MutableState <T > private constructor() {
70+
71+ /* *
72+ * The non-nullable state of [Hikage].
73+ */
74+ class NonNull <T > internal constructor(private var holder : T ) : NonNullState<T> {
75+
76+ private val observers = mutableSetOf< (T ) -> Unit > ()
77+
78+ override var value get() = holder
79+ set(value) {
80+ if (holder == value) return
81+ holder = value
82+ observers.forEach { it(value) }
83+ }
84+
85+ override fun getValue (thisRef : Any? , property : KProperty <* >) = value
86+
87+ override fun setValue (thisRef : Any? , property : KProperty <* >, value : T ) {
88+ this .value = value
89+ }
90+
91+ override fun observe (observer : (T ) -> Unit ) {
92+ observers + = observer
93+ observer(value)
94+ }
95+ }
96+
97+ /* *
98+ * The nullable state of [Hikage].
99+ */
100+ class Nullable <T > internal constructor(private var holder : T ? ) : NullableState<T?> {
101+
102+ private val observers = mutableSetOf< (T ? ) -> Unit > ()
103+
104+ override var value get() = holder
105+ set(value) {
106+ if (holder == value) return
107+ holder = value
108+ observers.forEach { it(value) }
109+ }
110+
111+ override fun getValue (thisRef : Any? , property : KProperty <* >) = value
112+
113+ override fun setValue (thisRef : Any? , property : KProperty <* >, value : T ? ) {
114+ this .value = value
115+ }
116+
117+ override fun observe (observer : (T ? ) -> Unit ) {
118+ observers + = observer
119+ observer(value)
120+ }
121+ }
122+ }
123+
124+ /* *
125+ * Create a mutable state of [Hikage] with the specified value.
126+ * @param value the initial value of the state.
127+ * @return [MutableState.NonNull]
128+ */
129+ fun <T > mutableStateOf (value : T ) = MutableState .NonNull (value)
130+
131+ /* *
132+ * Create a mutable state of [Hikage] with the specified value.
133+ * @param value the initial value of the state.
134+ * @return [MutableState.Nullable]
135+ */
136+ fun <T > mutableStateOfNull (value : T ? = null) = MutableState .Nullable (value)
137+
138+ /* *
139+ * Set the [Hikage] state value.
140+ *
141+ * Usage:
142+ *
143+ * ```kotlin
144+ * val textState = mutableStateOf("Hello World!")
145+ * var text by textState
146+ * TextView {
147+ * setState(textState) {
148+ * text = it
149+ * }
150+ * }
151+ * // Modify the state.
152+ * text = "Hello Hikage!"
153+ * ```
154+ * @param state the state to be set.
155+ * @param apply the apply body.
156+ */
157+ inline fun <T , R > R.setState (state : NonNullState <T >, crossinline apply : R .(T ) -> Unit ) {
158+ state.observe {
159+ this .apply (it)
160+ }
161+ }
162+
163+ /* *
164+ * Set the [Hikage] state value.
165+ * @see setState
166+ * @param state the state to be set.
167+ * @param apply the apply body.
168+ */
169+ inline fun <T , R > R.setState (state : NullableState <T >, crossinline apply : R .(T ? ) -> Unit ) {
170+ state.observe {
171+ this .apply (it)
172+ }
173+ }
0 commit comments