mirror of
https://github.com/corda/corda.git
synced 2025-02-01 16:58:27 +00:00
client: Add lengthier explanation of Models
This commit is contained in:
parent
6b6c51b8d4
commit
2869889769
@ -19,12 +19,51 @@ import kotlin.reflect.KProperty
|
|||||||
* This allows decoupling of UI logic from stream initialisation and provides us with a central place to inspect data
|
* This allows decoupling of UI logic from stream initialisation and provides us with a central place to inspect data
|
||||||
* flows. It also allows detecting of looping logic by constructing a stream dependency graph TODO do this.
|
* flows. It also allows detecting of looping logic by constructing a stream dependency graph TODO do this.
|
||||||
*
|
*
|
||||||
* General rule of thumb: A stream/observable should be a model if it may be reused several times.
|
|
||||||
*
|
|
||||||
* Usage:
|
* Usage:
|
||||||
* // Inject service -> client event stream
|
* // Inject service -> client event stream
|
||||||
* private val serviceToClient: EventStream<ServiceToClientEvent> by eventStream(WalletMonitorModel::serviceToClient)
|
* private val serviceToClient: EventStream<ServiceToClientEvent> by eventStream(WalletMonitorModel::serviceToClient)
|
||||||
*
|
*
|
||||||
|
* Each Screen code should have a code layout like this:
|
||||||
|
*
|
||||||
|
* class Screen {
|
||||||
|
* val root = (..)
|
||||||
|
*
|
||||||
|
* [ inject UI elements using fxid()/inject() ]
|
||||||
|
*
|
||||||
|
* [ inject observable dependencies using observable()/eventSink() etc]
|
||||||
|
*
|
||||||
|
* [ define screen-specific observables ]
|
||||||
|
*
|
||||||
|
* init {
|
||||||
|
* [ wire up UI elements ]
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* For example if I wanted to display a list of all USD cash states:
|
||||||
|
* class USDCashStatesScreen {
|
||||||
|
* val root: Pane by fxml()
|
||||||
|
*
|
||||||
|
* val usdCashStatesListView: ListView<Cash.State> by fxid("USDCashStatesListView")
|
||||||
|
*
|
||||||
|
* val cashStates: ObservableList<Cash.State> by observableList(ContractStateModel::cashStates)
|
||||||
|
*
|
||||||
|
* val usdCashStates = cashStates.filter { it.(..).currency == USD }
|
||||||
|
*
|
||||||
|
* init {
|
||||||
|
* Bindings.bindContent(usdCashStatesListView.items, usdCashStates)
|
||||||
|
* usdCashStatesListView.setCellValueFactory(somethingsomething)
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* The UI code can just assume that the cash state list comes from somewhere outside. The initialisation of that
|
||||||
|
* observable is decoupled, it may be mocked or be streamed from the network etc.
|
||||||
|
*
|
||||||
|
* Later on we may even want to move all screen-specific observables to a separate Model as well (like usdCashStates) - this
|
||||||
|
* would allow moving all of the aggregation logic to e.g. a different machine, all the UI will do is inject these and wire
|
||||||
|
* them up with the UI elements.
|
||||||
|
*
|
||||||
|
* Another advantage of this separation is that once we start adding a lot of screens we can still track data dependencies
|
||||||
|
* in a central place as opposed to ad-hoc wiring up the observables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
inline fun <reified M : Any, T> observable(noinline observableProperty: (M) -> Observable<T>) =
|
inline fun <reified M : Any, T> observable(noinline observableProperty: (M) -> Observable<T>) =
|
||||||
@ -56,6 +95,10 @@ inline fun <reified M : Any, T> observableListReadOnly(noinline observableListPr
|
|||||||
|
|
||||||
object Models {
|
object Models {
|
||||||
private val modelStore = HashMap<KClass<*>, Any>()
|
private val modelStore = HashMap<KClass<*>, Any>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds a class->dependencies map that tracks what screens are depending on what model.
|
||||||
|
*/
|
||||||
private val dependencyGraph = HashMap<KClass<*>, MutableSet<KClass<*>>>()
|
private val dependencyGraph = HashMap<KClass<*>, MutableSet<KClass<*>>>()
|
||||||
|
|
||||||
fun <M : Any> initModel(klass: KClass<M>) = modelStore.getOrPut(klass) { klass.java.newInstance() }
|
fun <M : Any> initModel(klass: KClass<M>) = modelStore.getOrPut(klass) { klass.java.newInstance() }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user