Node Reference
All node factory methods return objects with a fluent builder API. Every node can be given an id and className for StyleSheet targeting.
Text & Display
Text
Single-line text with inline styling.
Text.of("hello") // plain text
Text.of("hello").bold() // bold
Text.of("hello").italic() // italic
Text.of("hello").underline() // underlined
Text.of("hello").strikethrough() // strikethrough
Text.of("hello").dim() // dimmed/muted
Text.of("hello").color(Color.CYAN) // foreground color
Text.of("hello").background(Color.BLUE) // background color
Text.of("hello").style(myStyle) // full Style object
Inline Markdown
Supported tokens: **bold**, *italic*, `code`, ~~strikethrough~~.
Paragraph
Word-wrapped multi-line text. Useful for long descriptions that should reflow to the terminal width.
Paragraph.of("This is a long paragraph that will be word-wrapped...")
Paragraph.ofMarkdown("**Important:** This paragraph supports *inline markdown* too.")
Divider
Layout
VBox
Stacks children vertically.
VBox.of(node1, node2, node3)
VBox.of(nodes).gap(1) // 1 blank line between children
VBox.of(List.of(node1, node2)) // from a list
HBox
Stacks children horizontally.
BoxNode (bordered container)
Combining layouts
Nest VBox and HBox freely to build complex layouts:
Interactive Widgets
Button
ButtonNode btn = Button.of("[ OK ]", () -> handleClick());
registerFocusable(btn); // participate in Tab cycling
- Press
Tabto focus,Enterto activate. - The callback fires immediately on click or Enter.
Input (single line)
InputNode input = Input.of("initial value", value -> setState(() -> this.text = value));
registerFocusable(input);
- When focused, typed characters update the value.
- The callback is invoked on every keystroke.
TextArea (multi-line)
TextAreaNode area = TextArea.of("", 5); // empty, 5 visible rows
registerFocusable(area);
// Programmatic manipulation
area.insertChar('h');
area.insertChar('i');
String content = area.getText();
Checkbox
CheckboxNode cb = Checkbox.of("Enable feature", false,
() -> setState(() -> checked = !checked));
registerFocusable(cb);
// Space (ASCII 32) is a CHARACTER — detect it via registerCharacter
eventBus.registerCharacter(c -> {
if (c == ' ' && cb.isFocused()) setState(() -> cb.toggle());
});
- Displayed as
[✓] labelwhen checked,[ ] labelwhen unchecked. toggle()flips the state and fires theonChangecallback.
RadioGroup
RadioGroupNode radio = RadioGroup.of("Option A", "Option B", "Option C");
registerFocusable(radio);
// Wire arrow keys to navigate when focused
onKey(KeyType.ARROW_DOWN, () -> {
if (radio.isFocused()) setState(() ->
radio.setSelectedIndex(Math.min(
radio.getSelectedIndex() + 1, radio.getOptions().size() - 1)));
});
onKey(KeyType.ARROW_UP, () -> {
if (radio.isFocused()) setState(() ->
radio.setSelectedIndex(Math.max(radio.getSelectedIndex() - 1, 0)));
});
// Read/write selection
int idx = radio.getSelectedIndex();
radio.setSelectedIndex(1);
Select (dropdown-style)
Renders as a single-row [ Option ▾ ] header. When opened it expands below to show all options with a › cursor.
SelectNode sel = Select.of("Red", "Green", "Blue");
registerFocusable(sel);
// Enter opens/closes the dropdown when focused
onKey(KeyType.ENTER, () -> {
if (sel.isFocused()) setState(() -> sel.toggle());
});
// Arrow keys navigate when the dropdown is open
onKey(KeyType.ARROW_DOWN, () -> {
if (sel.isOpen()) setState(() -> sel.moveDown());
});
onKey(KeyType.ARROW_UP, () -> {
if (sel.isOpen()) setState(() -> sel.moveUp());
});
// Enter also confirms selection when open; Escape cancels
onKey(KeyType.ESCAPE, () -> {
if (sel.isOpen()) setState(() -> sel.close());
});
// Read selected value
String current = sel.getSelectedValue();
sel.setSelectedIndex(2); // programmatic selection
Lists & Tables
Table
Scrollable tabular data with keyboard navigation.
List<String> headers = List.of("Name", "Role", "City");
List<List<String>> rows = List.of(
List.of("Alice", "Engineer", "Berlin"),
List.of("Bob", "Designer", "London"),
List.of("Carol", "Manager", "Paris")
);
TableNode table = Table.of(headers, rows, 8); // show 8 rows at a time
// Navigation
table.selectDown();
table.selectUp();
Wire navigation to key handlers:
onKey(KeyType.ARROW_DOWN, () -> setState(() -> table.selectDown()));
onKey(KeyType.ARROW_UP, () -> setState(() -> table.selectUp()));
VirtualList (large data sets)
Renders only the visible rows — suitable for lists with thousands of items.
List<String> items = IntStream.range(1, 100_001)
.mapToObj(i -> "Item " + i)
.collect(toList());
VirtualListNode list = VirtualList.of(items, 15); // 15 visible rows
// Navigation
list.selectDown();
list.selectUp();
list.pageDown();
list.pageUp();
list.selectFirst();
list.selectLast();
int idx = list.getSelectedIndex();
registerFocusable(list);
Viewport (scrollable window)
Wraps any Node tree in a scrollable window showing a fixed number of rows.
Node content = VBox.of(/* many nodes */);
ViewportNode vp = Viewport.of(content, 10); // 10 visible rows
// Scroll methods
vp.scrollDown();
vp.scrollUp();
vp.pageDown();
vp.pageUp();
vp.scrollToTop();
vp.scrollToBottom();
vp.showScrollbar(false); // hide the scroll indicator
Wire to key handlers (store vp as a field):
onKey(KeyType.ARROW_DOWN, () -> setState(() -> vp.scrollDown()));
onKey(KeyType.ARROW_UP, () -> setState(() -> vp.scrollUp()));
onKey(KeyType.PAGE_DOWN, () -> setState(() -> vp.pageDown()));
onKey(KeyType.PAGE_UP, () -> setState(() -> vp.pageUp()));
Progress Bar
ProgressBarNode bar = new ProgressBarNode(0.65); // 65%
bar.setProgress(0.80); // update progress
// Custom styling
bar.filledStyle(Style.DEFAULT.withForeground(Color.GREEN));
bar.emptyStyle(Style.DEFAULT.withForeground(Color.BRIGHT_BLACK));
Progress value is a double in the range 0.0 – 1.0.
Spinner
An animated spinner that cycles through frames.
// Default frames: | / - \
SpinnerNode spin = Spinner.of();
// Braille dot frames
SpinnerNode spin = Spinner.of(new String[]{ "⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏" });
// Advance frame on a timer
AliveJTUI.scheduleRepeating(100, () -> setState(() -> spin.nextFrame()));
Collapsible
An expandable/collapsible section with a title.
// Starts collapsed
Node section = Collapsible.of("Settings",
Text.of(" Option A"),
Text.of(" Option B"),
Text.of(" Option C")
);
// Starts expanded
Node section = Collapsible.expanded("Settings",
Text.of(" Option A"),
Text.of(" Option B")
);
// Cast to manipulate programmatically
CollapsibleNode col = (CollapsibleNode) section;
col.toggle();
col.expand();
col.collapse();
boolean open = col.isExpanded();
Dialog (overlay)
Push a dialog on top of the current UI. The dialog is rendered as an overlay; the background UI is still visible but inactive.
Node dialog = Dialog.of("Confirm Delete", VBox.of(
Text.of(" Are you sure you want to delete this file?"),
Text.of(""),
HBox.of(
Button.of(" [Yes] ", () -> {
AliveJTUI.popOverlay();
setState(() -> performDelete());
}),
Button.of(" [No] ", () -> AliveJTUI.popOverlay())
)
));
AliveJTUI.pushOverlay(dialog);
Button registration in dialogs
Buttons inside dialogs that need focus/Enter handling should be registered with registerFocusable() before pushing the overlay.
Help Panel
Display a keyboard shortcut reference at the bottom of the screen.
Node help = HelpPanel.of(
new KeyBinding("Tab", "Next field"),
new KeyBinding("Enter", "Confirm"),
new KeyBinding("↑ ↓", "Navigate"),
new KeyBinding("ESC", "Quit")
);
Node Quick Reference
| Node | Factory | Focusable |
|---|---|---|
TextNode |
Text.of(string) |
No |
ParagraphNode |
Paragraph.of(string) |
No |
Divider |
Divider.horizontal() / .vertical() |
No |
VBoxNode |
VBox.of(...) |
No |
HBoxNode |
HBox.of(...) |
No |
BoxNode |
new BoxNode(child, border, style) |
No |
ButtonNode |
Button.of(label, action) |
Yes |
InputNode |
Input.of(value, onChange) |
Yes |
TextAreaNode |
TextArea.of(value, rows) |
Yes |
CheckboxNode |
Checkbox.of(label, checked, toggle) |
Yes |
RadioGroupNode |
RadioGroup.of(option...) |
Yes |
SelectNode |
Select.of(option...) |
Yes |
TableNode |
Table.of(headers, rows, visibleRows) |
No |
VirtualListNode |
VirtualList.of(items, visibleRows) |
Yes |
ViewportNode |
Viewport.of(content, visibleRows) |
No |
ProgressBarNode |
new ProgressBarNode(progress) |
No |
SpinnerNode |
Spinner.of() |
No |
CollapsibleNode |
Collapsible.of(title, children...) |
No |
DialogNode |
Dialog.of(title, content) |
No |
HelpPanelNode |
HelpPanel.of(bindings...) |
No |