tentackle-fx-atlanta — The AtlantaFX Theme and Component Layer¶
Overview and Motivation¶
tentackle-fx-atlanta integrates AtlantaFX
into Tentackle's desktop UI stack. It provides two things:
- A modern look and feel — a
ThemeUtilitiesimplementation that drives the AtlantaFX user-agent stylesheets (Primer, Cupertino, Nord, each in a light and a dark variant) plus the Tentackle-specific CSS that colors mandatory, error, and info states. - Extended AtlantaFX controls — a handful of AtlantaFX controls and
containers wrapped as first-class Tentackle FX components, so they bind to the
model, validate, and switch read-only exactly like the standard
tentackle-fxcomponents.
The module lives in package org.tentackle.fx.atlanta (JPMS module
org.tentackle.fx.atlanta). On the module path it requires transitive org.tentackle.fx.rdc —
so a module reading org.tentackle.fx.atlanta also reads the whole extended FX layer and the
Rich Data Components — and requires transitive atlantafx.base for the AtlantaFX controls
themselves. The atlantafx-base dependency comes from io.github.mkpaz.
The Maven dependency on tentackle-fx-rdc, however, is declared <optional>, so it is not
inherited: an application declares tentackle-fx-rdc itself, next to tentackle-fx-atlanta
(the project archetype's gui module does exactly that).
Why a separate module?¶
AtlantaFX is an optional, third-party styling and control library. Keeping it in its own module means:
- An application opts into the AtlantaFX theme by adding a single dependency; the core FX layer carries no AtlantaFX coupling.
- The extra controls AtlantaFX ships (a
Calendar, aToggleSwitch, masked/custom text fields,Card/Tile/InputGroupcontainers) become available as bindable Tentackle components without bloatingtentackle-fx. - The theme is selected via the SPI (
@Service(ThemeUtilities.class)), so simply having the module on the path makes it the active theme:RdcThemeUtilitiesis registered for the same service, but a module always overrides the services of the modules it depends on (see Ordering and Overriding). The generic theme API — dark mode, theme switching and the persisted user preference — is described in tentackle-fx.
Design principles¶
The module follows the exact conventions of tentackle-fx — read
fx.md first; everything there
about components, delegates, builders, configurators, value translators, and SPI
discovery applies here unchanged. This module only adds new instances of those
patterns for the AtlantaFX controls:
- Wrap, don't replace. Each component extends its AtlantaFX control
(
FxToggleSwitch extends ToggleSwitch), adding theFxComponent/FxContainercontract on top. - Delegate over inheritance. The cross-cutting behavior lives in a delegate; the component is a thin wurblet-generated shell forwarding to it.
- Configure by convention, override by service. Builders, configurators, and
value translators are all SPI services discovered by
FxFactory.
The Theme — AtlantaThemeUtilities¶
AtlantaThemeUtilities is the heart of the module. It is registered as
@Service(ThemeUtilities.class) and extends RdcThemeUtilities, so it inherits
the RDC theming behavior and overrides the AtlantaFX-specific parts.
| Aspect | Behavior |
|---|---|
| Supported themes | Primer, Cupertino, Nord (getSupportedThemes()) |
| Default theme | Cupertino on macOS, otherwise Primer (chosen in the constructor) |
| Default font size | 14 |
| User-agent stylesheet | applyUserAgentStylesheet() selects /atlantafx/base/theme/<theme>-light.css or -dark.css according to isDarkMode() |
| Scene stylesheets | applyStylesheets(scene) replaces the scene's stylesheets with tentackle.css (or tentackle-dark.css in dark mode) plus this module's pdo-style.css, instead of the RDC pdo-style.css |
| Resource redirection | getResourceURL(...) redirects the CSS lookups of NotificationBuilder, Note and TotalsTableView to this module, so they pick up the AtlantaFX-tuned stylesheets |
| Auto-adjust padding | getAutoAdjustPadding() returns 16 |
Bundled stylesheets and assets¶
The CSS and image resources live in src/main/resources/org/tentackle/fx/atlanta:
| Resource | Role |
|---|---|
tentackle.css / tentackle-dark.css |
Tentackle extensions on top of the AtlantaFX theme (see below). The dark variant uses darker shades of the same palette. |
pdo-style.css / pdo-style.png |
The .tt-pdo-style decoration marking a field that references a PDO (for an editable combobox, on its arrow button) |
note.css / note-dark.css |
Styling for the Note speech-bubble component (error, info and sticky notes). The variants differ only in the color of a sticky note's link. |
notification.css |
Styling for the toast/notification overlay built by DefaultNotificationBuilder |
totalstable.css |
Styling for TotalsTableView (fixed row height, hidden header and scrollbars) |
i18n-style.png |
Icon marking an internationalized field |
tentackle.css (and its dark variant) contributes:
- the variables
-tt-mandatory-color,-tt-error-color,-tt-alert-colorand-tt-info-color, mapped to the AtlantaFX warning, danger and success palette, plus-tt-filter-active-color(the accent color) for the filter button of a filtered table column; - the
.tt-mandatory,.tt-errorand.tt-infostyle classes and the:tt-alertpseudo-class, which overrides the state classes while anInputAlertflashes; - the
.tt-i18ndecoration of multilingual text fields; - a uniform cell and header size of
2emfor table, tree-table and list views; - a reduced opacity (0.6) for disabled check boxes, radio buttons, combo- and choice boxes, text inputs, buttons, toggle buttons and toggle switches;
- the styles of the expand button and the expanded editor of one-line
FxTextAreas (.tt-expand-button,.tt-expanded-text-pane); - the styles of the column filter (
TableFilterSupport):.tt-filter-column,.tt-filter-button,.tt-filter-button-activeand the filter popup.tt-filter-popup-pane.
Extended Components¶
All four components implement the standard FxComponent / FxTextComponent
contract through a delegate, with the forwarding methods generated by the
delegate/component/textcomponent wurblets (see the delegate pattern in
fx.md).
| Component | Extends (AtlantaFX) | View type | Notes |
|---|---|---|---|
FxCalendar |
Calendar |
LocalDate |
An inline month calendar to pick a date. Binds to LocalDate, java.util.Date and its subclasses (see Value Translators). |
FxToggleSwitch |
ToggleSwitch |
Boolean |
A modern on/off switch. Binds to Boolean or boolean. |
FxCustomTextField |
CustomTextField |
String |
A text field that can carry leading/trailing nodes (icons, buttons). Full FxTextComponent feature set (columns, pattern, case conversion, auto-completion, …). |
FxMaskTextField |
MaskTextField |
String |
A text field with an input mask, otherwise identical to FxCustomTextField. |
Component delegates¶
The delegates supply the toolkit-specific glue:
FxCalendarDelegate(extends FxComponentDelegate) — reads/writesCalendar.valueProperty()as aLocalDate, setting it only if it differs from the current value; onsetType(...)it creates a translator from the model type toLocalDate(unless the application already set one).FxToggleSwitchDelegate(extends FxComponentDelegate) — reads/writesToggleSwitch.selectedProperty()as aBoolean, showingnullas "off"; creates a model↔Booleantranslator onsetType(...).FxCustomTextFieldDelegate/FxMaskTextFieldDelegate(bothextends AbstractTextFieldDelegate<…>) — treat all-whitespace text asnull, mapcolumnsto the control'sprefColumnCount(maxColumnsdoes so too, unlesscolumnswas set explicitly), and apply the configured text alignment when a value is set.
Configurators¶
Per-type Configurators (registered with @ConfiguratorService) run against
every instance:
CalendarConfiguratorandToggleSwitchConfiguratorextendComponentConfigurator. They subscribe to the control'svalueProperty()/selectedProperty()and push the change into the model immediately — so a switch toggle or a calendar pick updates the bound value instantly, not only on focus-lost.CustomTextFieldConfiguratorandMaskTextFieldConfiguratorextendTextInputControlConfigurator, inheriting the standard text-field setup.
Builders¶
Each component has an @BuilderService builder (CalendarBuilder,
ToggleSwitchBuilder, CustomTextFieldBuilder, MaskTextFieldBuilder) that the
FXML BuilderFactory uses to instantiate the Tentackle component whenever the
FXML references the corresponding AtlantaFX control — so a <Calendar/> in FXML
becomes an FxCalendar automatically.
Extended Containers¶
Three AtlantaFX layout controls are wrapped as FxContainers, with the
container behavior supplied by a delegate (fxcontainer wurblet):
| Container | Extends (AtlantaFX) | Role |
|---|---|---|
FxCard |
Card |
A card with header, subheader, body and footer regions |
FxTile |
Tile |
A titled row with description, optional graphic and an action node |
FxInputGroup |
InputGroup |
Glues several inputs together into one visually-joined control group |
The delegate's getComponents() determines which nodes take part in the container cascade
(updateView, updateModel, changeability, view-modified tracking):
FxInputGroupis aPane: its components are its children.FxCardandFxTileare controls whose children are the nodes of their skin. Their components are therefore the nodes set in their slots: header, subheader, body and footer forFxCard, graphic and action forFxTile— the same approachFxTitledPanetakes with its content. As withFxTitledPane, a component inside such a slot is parented by the skin, not by the container, so it does not find the container viagetParentContainer().
CardConfigurator and TileConfigurator are currently pass-through hooks reserved for future
look-and-feel tweaks, and InputGroupConfigurator extends the (equally empty) PaneConfigurator.
Each container has the matching @BuilderService builder.
Value Translators¶
Two translators are added for the Calendar control (whose view type is
LocalDate), registered with @ValueTranslatorService in package
org.tentackle.fx.atlanta.translate:
LocalDateLocalDateTranslator— anIdentityTranslator<LocalDate>for the common case where the model itself is aLocalDate.DateLocalDateTranslator— converts between ajava.util.Date(or any subclass) and the calendar'sLocalDate. Translating back to the model, it returns the same class as the bound component's model type:java.util.Date,java.sql.Date,java.sql.Timestamp,org.tentackle.common.Timestamp, ororg.tentackle.common.Datefor all other types. Timestamps are set to the start of the picked day.
These are the only translators to LocalDate: other model types cannot be bound to an
FxCalendar unless the application provides a translator. FxToggleSwitch uses the
BooleanBooleanTranslator of tentackle-fx. The delegate picks the translator via
FxFactory.createValueTranslator(...), which also matches superclasses of the model type.
Module Integration¶
org.tentackle.fx.atlanta.service.Hookis provided as aorg.tentackle.common.ModuleHook, giving the framework a per-module entry point for resource-bundle loading.- The module is declared
open, so reflection-based access (FXML loading, TRIP) works on the module path.
How It Fits Together¶
- Adding
tentackle-fx-atlantato an application putsAtlantaThemeUtilitieson the path, which the SPI selects as the activeThemeUtilities. - At startup the theme applies the chosen AtlantaFX user-agent stylesheet plus
the Tentackle
tentackle.css/pdo-style.css, so mandatory/error/info states and PDO decorations render in the AtlantaFX palette. - FXML (or programmatic) views can use the AtlantaFX controls; the builders turn
them into
FxCalendar,FxToggleSwitch,FxCustomTextField,FxMaskTextField,FxCard,FxTileandFxInputGroup. - Configurators wire the new controls for immediate model updates, and the delegates plus value translators bind them to the model in the model's own type — just like every other Tentackle FX component.
Package Reference¶
| Package | Role |
|---|---|
org.tentackle.fx.atlanta |
AtlantaThemeUtilities — the AtlantaFX ThemeUtilities and bundled stylesheets/assets |
org.tentackle.fx.atlanta.component |
Extended components: FxCalendar, FxToggleSwitch, FxCustomTextField, FxMaskTextField |
org.tentackle.fx.atlanta.component.delegate |
Component delegates holding the behavior |
org.tentackle.fx.atlanta.component.config |
Per-component Configurators |
org.tentackle.fx.atlanta.component.build |
Component builders used by the FXML builder factory |
org.tentackle.fx.atlanta.container |
Extended containers: FxCard, FxTile, FxInputGroup |
org.tentackle.fx.atlanta.container.delegate / .config / .build |
Container delegates, configurators and builders |
org.tentackle.fx.atlanta.translate |
LocalDateLocalDateTranslator, DateLocalDateTranslator for the Calendar control |
org.tentackle.fx.atlanta.service |
Module hook (Hook) registered as a ModuleHook (not exported) |
See also: fx.md for the extended FX layer this module builds on, and rdc.md for the Rich Data Components it depends on.