Package sprouts
It was designed in conjunction with the SwingTree GUI Framework, which has native support for binding to the Sprouts properties.
We recommended using Sprouts as a tool for bridging the gap between
place oriented programming and data oriented programming,
which is especially useful in GUI programming, where data oriented / functional
programming principles are hard to apply due to the inherently place oriented
nature of GUI components.
Sprouts allows you to create lens based properties that make value object based
view models interoperate with your GUI components or other kinds of views.
This is best achieved using the MVI (Model-View-Intent) and MVL (Model-View-Lens) patterns.
Here an example demonstrating how to create
a set of bindable properties from a basic record based
modelling scenario:
View Models:
public record Address(
String street, String city, int postalCode
) {
public Address withStreet(String street) {
return new Address(street, city, postalCode);
}
public Address withCity(String city) {
return new Address(street, city, postalCode);
}
public Address withPostalCode(int postalCode) {
return new Address(street, city, postalCode);
}
}
public record Person(
String forename, String surname, Address address
) {
public Person withForename(String forename) {
return new Person(forename, surname, address);
}
public Person withSurname(String surname) {
return new Person(forename, surname, address);
}
public Person withAddress(Address address) {
return new Person(forename, surname, address);
}
}
View:
public final class PersonView {
public static void main(String[] args) {
Person person = new Person("John", "Doe", new Address("Main Street", "Springfield", 12345));
Var<Person> applicationState = Var.of(person);
var view = new PersonView(applicationState);
// show view
}
public PersonView(Var<Person> vm) {
Var<String> forename = vm.zoomTo(Person::forename, Person::withForename);
Var<String> surname = vm.zoomTo(Person::surname, Person::withSurname);
Val<String> fullName = vm.viewAsString( person -> person.forename() + " " + person.surname() );
Var<Address> address = vm.zoomTo(Person::address, Person::withAddress);
Var<String> street = address.zoomTo(Address::street, Address::withStreet);
Var<String> city = address.zoomTo(Address::city, Address::withCity);
Var<Integer> postalCode = address.zoomTo(Address::postalCode, Address::withPostalCode);
// Use mutable properties in the views GUI...
}
}
For more usage information check out this page,
where you can browse the living documentation of the Sprouts API.
Also check out the SwingTree GUI Framework for more example
code using the Sprouts properties natively.
-
ClassDescriptionAction<D>A functional interface for observing state changes and performing some action in response.Association<K,
V> Defines an association between keys and values as an immutable value object where the values are accessed by the keys in a map-like fashion.This is a marker interface for property event channels.An event is something that can be triggered and reacted to, throughObservables created by theEvent.observable()method.HasId<I>This is a sort of marker interface forVar/Valproperty item types, which tells the property that it wants to use the object returned by theHasId.id()method as a unique identifier for its item when determining theValDelegate.change()type.TheLensinterface defines an access and update operation on an individual part of a nested and immutable data structure.Maybe<T>TheMaybeinterface represents a thing of a specificMaybe.type()which may or may not exist, and it serves as anullsafe blue-print for nomadic types like theResulttype.A non-checked runtime exception thrown when an item is missing from aMaybeobject.This represents an event that can be observed but not triggered.An observer is a callback function stored inside aViewable,Viewablesor more generallyObservable, and it is typically invoked when anEventis triggered, or a property, likeVal,Var,ValsorVars, experienced a state change.
So if you want to observe an event or properties using an observer, then you have to createObservable"views" using the following methods, among others:Event.observable()Val.view()Val.view()Vals.view()Vals.view()An immutable value object representing a pair of two generic values.A problem is a wrapper for information describing an issue that can be reported and attached to aResult.Result<V>ResultItemSupplier<T extends @Nullable Object>Supplier of aResult's item, which may throw aRuntimeExceptionor checkedExceptionwhen used to supply a result item during an invocation of theResult.ofTry(Class, ResultItemSupplier)factory method.
This is a functional interface only intended to be used for the result pattern.Similar toResultItemSupplier, but used for running an operation that does not return a value.Describes how aVarsinstance was mutated.A set of constants that describe how a property item has changed.A subscriber may either be anObserveror anActionand it is used as a marker interface to allow for both types to be identified, grouped and used interchangeably.
A subscriber is specifically designed to be stored in aViewable,Viewablesor more generallyObservable, typically to serve as a simple change listener.
This interface does not have any methods and is only used for type checking or to remove any kind of change listener from an observable, throughObservable.unsubscribe(Subscriber)!An immutable collection of ordered items of the same typeT(seeTuple.type()), whose items can be iterated over and accessed through their indices.
This class can be thought of as an immutable array with an API designed for functional programming and robust handling ofnullvalues.
A read only wrapper around an item which can be mapped to a weakly referencedViewableto then be observed for changes usingActions registered through theViewable.onChange(Channel, Action)method, where theChannelis used to distinguish between changes from different sources (usually application layers like the view model or the view).
UseVal.view()to access a simple no-op live view of the item of this property and register change listeners on it to react to state changes.ValDelegate<T>A read only API of a list of read-only viewed properties that can be observed, iterated over, mapped, filtered, turned into a stream, and more.ValsDelegate<T>ValueSet<E>An immutable collection of non-null elements that contains no duplicates, meaning that it can never contain a pair of elements e1 and e2 such that e1.equals(e2).A mutable wrapper for an item which can also be mapped to a weakly referencedViewableto be observed for changes usingActions registered through theViewable.onChange(Channel, Action)method, where theChannelis used to distinguish between changes from different sources (usually application layers like the view model or the view).
UseVal.view()to access a simple no-op live view of the item of this property and register change listeners on it to react to state changes.A mutable list of mutable properties designed for MVVM, that can be observed for changes through aVals.view()by registeringSubscribertypes on it likeObservers andActions.This is a value object representing a unique ID consisting of two numbers, a lineage and succession, allowing you to identify something and also determine the order in which something was created and updated.Viewable<T>A read-only live view on a delegated item derived from aVarorVal, which can be observed for changes usingActions registered through theViewable.onChange(Channel, Action)method, where theChannelis used to distinguish between changes from different sources (usually application layers like the view model or the view).Viewables<T>A read-only live view on a delegated list of items derived from aVarsorVals, which can be observed for changes usingActions registered through theonChange(Action)method.