Skip to content

0.5

Choose a tag to compare

@hjohn hjohn released this 03 Feb 19:30

Full Changelog: 0.4...0.5

This release enhances FX Flow with a more flexible, strategy-driven builder model, enabling build-time customizable resolution of text, formatting, and child nodes.

Context‑Aware Build Strategy Infrastructure

A major addition is the build context and strategies framework. This allows builder behavior to be customized and overridden without changing the builders themselves. It introduces:

  • BuildContext, BuildContexts, and BuildStrategy to represent, compose, and resolve strategy implementations.
  • Thread‑local and global root contexts for scoped strategy application.
  • Support for override of strategies such as text formatting (TextStrategy), content resolution (ContentStrategy) and children handling (ChildrenStrategy). This enables advanced use‑cases such as localization and custom node resolution.

Below is an example how text accepting builder methods can be (globally) overridden to do localization:

ChoiceModel<Locale> locales = ChoiceModel.of(Locale.ENGLISH, Locale.GERMAN);

BuildContexts.root(
    BuildContext.of(TextStrategy.class, (node, input, setter) -> {
        if (locales.get().equals(Locale.GERMAN)) {
            setter.accept(Objects.toString(input).toUpperCase());
        }
        else {
            setter.accept(Objects.toString(input));
        }
    })
);

The example:

  • Creates a new BuildContext with an overridden TextStrategy
  • Sets the newly created BuildContext as the root context for builders to use

Generalized text inputs

The text, promptText, and accessibleText builder methods now accept Object instead of String. Values are passed to the active TextStrategy, with the default behavior calling toString(). This enables richer use cases such as enum-based localization, custom formatting, and late or dynamic text resolution without changing builder APIs.

Simplified ComboBox and Spinner typing

ComboBox and Spinner builders no longer require an explicit type witness. The new raw/typed builder split allows the item type to be inferred naturally from methods that supply a type (eg. items(...), value(...), model(...), or comparator(...)), reducing boilerplate while preserving full type safety once the type is established. For example:

FX.comboBox()                       // type is ComboBoxBuilder.Raw
    .items(List.of("A", "B", "C")   // type is now ComboBoxBuilder.Typed<String>
    .comparator( ... )              // accepts Comparator<String> only now
    .build();