ObservableValue

Holds a value of type V, which can be observed using InvalidationListeners. When the value changes, the InvalidationListeners are informed via InvalidationListener.invalidated.

Property is a notable sub-interface, whose value is mutable. They have ChangeListeners (similar to InvalidationListener, but are also sent the old value and newValue.

Note. It is common to name an ObservableValue xxxProperty, even though it isn't really a Property. For example, suppose we have a Rectangle class, with left, right and width ObservableValues. We could choose to store left and right as Properties, with width as a BinaryFunction. Or we could store left and width as Properties, with right as a BinaryFunction. No matter which we choose, it is acceptable to name them leftProperty, rightProperty and widthProperty, despite one of them not inheriting from Property.

Atomic Updates

An atomic update, guarantees that two or more related properties are never in an inconsistent state, where the value of one property is out-of-date, because it hasn't been updated yet.

Consider SingleSelectionModel used by ListView, TreeView etc. It has two properties selectedIndex and selectedItem. When we change one of these properties, the other property must change before any of your listeners fire, your listener will see an inconsistent state.

Glok doesn't support atomic updates, but does offer some help, by having two sets of listeners. Those added via addBindListener and addBindChangeListener fire before those added by addListener and addChangeListener.

Bound properties, and LazyObservableValue always use addBindListener and addBindChangeListener. In general, your code should use addListener and addChangeListener, and therefore the property values will be consistent.

However, if your (regular) listeners change another property, beware that other listeners of the original property can see inconsistent values. It will see the new value of the original property, but the value of the other property will depend on the order the listeners were added. If it were added before, it will see the old (inconsistent) value.

In my experience, the lack of atomic updates isn't an issue. YMMV. None of my applications directly use addBindListener nor addBindChangeListener, but they do make extensive use of bound properties and LazyObservableValues (such as UnaryFunction, BinaryFunction etc).

Class Diagram

                                              ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
                                              ┆     Observable    ┆
                                              ┆ addListener()     ┆
                                              ┆ removeListener()  ┆
                                              ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯
                                                        △
                               ┌────────────────────────┴──┬────────────────┐
                  ╭╌╌╌╌╌╌╌╌╌╌╌╌┴╌╌╌╌╌╌╌╌╌╌╌╌╮     ╭╌╌╌╌╌╌╌╌┴╌╌╌╌╌╮   ╭╌╌╌╌╌╌┴╌╌╌╌╌╌╮
                  ┆     ObservableValue  ┆     ┆ObservableList┆   ┆ObservableSet┆
                  ┆ val value : V           ┆     ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯   ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╯
                  ┆ addChangeListener()     ┆
                  ┆ removeChangeListener()  ┆
                  ┆                         ┆
                  ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯
                               △                                                          ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
                               ├─────────────────────────────────────────┐                ┆InvalidationListener┆
                     ╭╌╌╌╌╌╌╌╌╌┴╌╌╌╌╌╌╌╌╌╌╮                   ┌──────────┴──────────┐     ┆  invalidated()     ┆
                     ┆   ReadOnlyProperty ┆                   │ ObservableValueBase │◇────┤                    ┆
                     ┆ bean : Any?        ┆                   │  listeners          │     ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯
                     ┆ beanName : String  ┆                   │  changeListeners    │     ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮
                     ┆                    ┆                   │                     │◇────┤ChangeListener┆
                     ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯                   └──────────┬──────────┘     ┆   changed()  ┆
                               △                                         │                ┆              ┆
            ┌──────────────────┴────┐                                    │                ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯
┏━━━━━━━━━━━┷━━━━━━━━━━━━━┓ ╭╌╌╌╌╌╌╌┴╌╌╌╌╌╌╌╌╮    ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮  │
┃ ReadOnlyPropertyWrapper ┃ ┆    Property    ┆    ┆ BidirectionalBind ┆  │
┃   listeners             ┃ ┆  var value : V ┆◀───┤  propertyA        ┆  │
┃   changeListeners       ┃ ┆                ┆◀───┤  propertyB        ┆  │
┃                         ┃ ┆                ┆    ┆  unbind()         ┆  │
┗━━━━━━━━━━━━━━━━━━━━━━━━━┛ ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯    ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯  │
                                     △                                   │
                                     │                                   │
                                     │                                   │
        ┌────────────────────────┬───┴───────────────────────────────────┴───┐
╭╌╌╌╌╌╌╌┴╌╌╌╌╌╌╌╌╌╌╮     ┌───────┴────────┐                      ┌───────────┴──────────┐
┆ StylableProperty ┆     │  PropertyBase  │                      │ LazyObservableValue  │
┆   kClass()       ┆     │                │                      │  invalidate()        │
┆   style()        ┆     │                │                      │  eval()              │
┆   revert()       ┆     └────────────────┘                      │  addDependant()      │
╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯             △                               │  removeDependant()   │
        △ (Used by Themes)       │                               └──────────────────────┘
        │                        │                                           △
        │                        │                         ┌─────────────────┴────────────────────┐
        │               ┏━━━━━━━━┷━━━━━━━━┓       ┏━━━━━━━━┷━━━━━━┓ ┏━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━┷━━━━━━┓
        │               ┃  SimpleProperty ┃       ┃ UnaryFunction ┃ ┃ BinaryFunction ┃ ┃ TernaryFunction ┃
        │               ┃                 ┃       ┃  argA         ┃ ┃  argA          ┃ ┃  argA           ┃
        │               ┃                 ┃       ┃  lambda       ┃ ┃  argB          ┃ ┃  argB           ┃
        │               ┗━━━━━━━━━━━━━━━━━┛       ┗━━━━━━━━━━━━━━━┛ ┃  lambda        ┃ ┃  argC           ┃
        │                        △                                  ┗━━━━━━━━━━━━━━━━┛ ┃  lambda         ┃
        │     ┌──────────────────┘                                                     ┗━━━━━━━━━━━━━━━━━┛
┏━━━━━━━┷━━━━━┷━━━━━━━━┓
┃SimpleStylableProperty┃
┃                      ┃
┃                      ┃
┗━━━━━━━━━━━━━━━━━━━━━━┛

Created with Blokart

Inheritors

Properties

Link copied to clipboard
abstract val value: V

Functions

Link copied to clipboard

Identical to addChangeListener, but these listeners are guaranteed to fire BEFORE other listeners. These should be used for the sole purpose of updating single ObservableValues which are dependent on this ObservableValue. This helps (but doesn't guarantee) that properties change atomically. i.e. when one property changes, a related property also changes before other (regular) listeners fire. Therefore, the (regular) listeners cannot read inconsistent values.

Link copied to clipboard

abstract fun addBindListener(listener: InvalidationListener)

Identical to addListener, but these listeners are guaranteed to fire BEFORE regular listeners. These should be used for the sole purpose of updating other ObservableValues which are dependent on this Observable.

Link copied to clipboard
Link copied to clipboard
abstract fun addListener(listener: InvalidationListener)
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard

Converts an ObservableValue, with a non-nullable to value, to an ObservableValue whose value IS nullable.

Link copied to clipboard
Link copied to clipboard
open operator fun getValue(thisRef: Any, kProperty: KProperty<*>): V

Lets us declare a val using a for the value of this property, using this as a delegate. e.g.

Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
Link copied to clipboard
abstract fun removeListener(listener: InvalidationListener)
Link copied to clipboard

Converts an ObservableValue, with a nullable to value, to an ObservableValue whose value is NOT nullable, by supplying a defaultValue.

Link copied to clipboard
Link copied to clipboard