RichTextFX is a JavaFX library that adds rich-text editing to Aussom. Unlike
the standard TextArea, which only supports plain text, RichTextFX lets you
apply styles to arbitrary character ranges -- either as inline CSS strings or
as CSS class names. It also supports line number gutters, syntax highlighting
callbacks, undo/redo, and clipboard operations.
Three classes are available, each suited to a different use case:
| Class | Use When |
|---|---|
InlineCssTextArea |
You need to apply styles programmatically at runtime and do not want to manage a CSS file. |
StyleClassedTextArea |
You want to separate style rules from code using a CSS file. Preferred for syntax highlighting. |
CodeArea |
You are building a code editor. Extends StyleClassedTextArea with a monospace font and adds setSyntaxHighlighter(). |
Include the class you want along with fx and any layout components:
include fx;
include fx.VBox;
include fx.CodeArea;
Create and configure the area, then add it to your layout:
app = fx.fxApp("My Editor", 900, 700);
editor = new CodeArea();
editor.setPrefSize(880.0, 660.0);
editor.setWrapText(false);
app.setLayout(editor);
app.show(true);
fx.shutdown();
Best for tools where the user or the program decides styling at runtime without a predefined stylesheet. Each styled range carries a CSS string directly:
area.setStyle(0, 5, "-fx-font-weight: bold; -fx-fill: blue;");
The CSS string uses the same properties as JavaFX text nodes: -fx-fill,
-fx-font-weight, -fx-font-style, -fx-font-size, -fx-font-family.
Best for syntax highlighting or any case where you define the visual rules in a CSS file and assign named classes to ranges:
area.getStylesheets().invoke("add", "syntax.css");
area.setStyleClass(0, 6, "keyword");
Where syntax.css defines:
.keyword { -fx-fill: #cc7832; -fx-font-weight: bold; }
Extends StyleClassedTextArea. Use it when you want a monospace code editor
with optional line numbers and a syntax highlighting callback that fires on
every text change:
editor = new CodeArea();
editor.setLineNumbers(true);
editor.setSyntaxHighlighter(::highlight);
public highlight(Text) {
editor.clearStyles();
// parse Text and apply style classes
}
include fx;
include fx.VBox;
include fx.HBox;
include fx.Button;
include fx.InlineCssTextArea;
app = fx.fxApp("Rich Text Editor", 800, 600);
area = new InlineCssTextArea("Type something here...");
area.setWrapText(true);
area.setPrefSize(780.0, 500.0);
boldBtn = new Button("Bold");
boldBtn.onClick(::applyBold);
italicBtn = new Button("Italic");
italicBtn.onClick(::applyItalic);
toolbar = new HBox();
toolbar.setSpacing(5.0);
toolbar.add([boldBtn, italicBtn]);
root = new VBox();
root.setSpacing(5.0);
root.add([toolbar, area]);
app.setLayout(root);
app.show(true);
fx.shutdown();
public applyBold(Event) {
sel = area.getSelection();
start = sel.invoke("getStart");
end = sel.invoke("getEnd");
if (start < end) {
area.setStyle(start, end, "-fx-font-weight: bold;");
}
}
public applyItalic(Event) {
sel = area.getSelection();
start = sel.invoke("getStart");
end = sel.invoke("getEnd");
if (start < end) {
area.setStyle(start, end, "-fx-font-style: italic;");
}
}
include fx;
include fx.CodeArea;
app = fx.fxApp("Code Editor", 900, 700);
editor = new CodeArea();
editor.setLineNumbers(true);
editor.setWrapText(false);
editor.setPrefSize(880.0, 660.0);
editor.getStylesheets().invoke("add", "syntax.css");
editor.setSyntaxHighlighter(::highlight);
editor.appendText("// Hello Aussom!\npublic class Example {\n public main(Args) {}\n}");
app.setLayout(editor);
app.show(true);
fx.shutdown();
public highlight(Text) {
editor.clearStyles();
idx = 0;
while (idx < Text.length()) {
pos = Text.indexOf("//", idx);
if (pos < 0) { break; }
end = Text.indexOf("\n", pos);
if (end < 0) { end = Text.length(); }
editor.setStyleClass(pos, end, "comment");
idx = end + 1;
}
}
Where syntax.css defines:
.code-area .text { -fx-font-family: "Courier New"; -fx-font-size: 13px; }
.comment { -fx-fill: #808080; -fx-font-style: italic; }
.keyword { -fx-fill: #cc7832; -fx-font-weight: bold; }
.string { -fx-fill: #6a8759; }
.number { -fx-fill: #6897bb; }
include fx;
include fx.InlineCssTextArea;
app = fx.fxApp("Log Viewer", 800, 500);
log = new InlineCssTextArea();
log.setEditable(false);
log.setWrapText(false);
log.setPrefSize(780.0, 460.0);
app.setLayout(log);
app.show(false);
log.appendText("[INFO] Server started on port 8080\n");
log.setStyle(1, 5, "-fx-fill: green; -fx-font-weight: bold;");
log.appendText("[ERROR] Connection refused\n");
errStart = log.getLength() - "[ERROR] Connection refused\n".length();
log.setStyle(errStart + 1, errStart + 6, "-fx-fill: red; -fx-font-weight: bold;");
log.scrollToBottom();
app.show(true);
fx.shutdown();
| Method | Description |
|---|---|
getText() |
Returns the full plain text. |
getTextRange(int Start, int End) |
Returns the text in the range [Start, End). |
setText(string Text) |
Replaces all content. |
appendText(string Text) |
Appends to the end. |
insertText(int Pos, string Text) |
Inserts at the given position. |
deleteText(int Start, int End) |
Deletes the range [Start, End). |
replaceText(int Start, int End, string Text) |
Replaces the range with new text. |
getLength() |
Returns the total character count. |
getParagraphCount() |
Returns the number of paragraphs. |
getParagraph(int ParIndex) |
Returns the plain text of a paragraph by index. |
clear() |
Clears all text. |
| Method | Description |
|---|---|
getCaretPosition() |
Returns the current caret index. |
moveTo(int Pos) |
Moves the caret to a position. |
moveToStart() |
Moves the caret to position 0. |
moveToEnd() |
Moves the caret to the end. |
selectRange(int Start, int End) |
Selects the range and moves the caret to End. |
selectAll() |
Selects all text. |
deselect() |
Clears the selection. |
getSelectedText() |
Returns the selected text. |
getSelection() |
Returns an IndexRange Java object. Call .invoke("getStart") and .invoke("getEnd") on it. |
| Method | Description |
|---|---|
undo() |
Undoes the last edit. |
redo() |
Redoes the last undone edit. |
cut() |
Cuts the selection to the clipboard. |
copyToClipboard() |
Copies the selection to the clipboard. |
paste() |
Pastes from the clipboard. |
| Method | Description |
|---|---|
setPrefSize(double W, double H) |
Sets the preferred dimensions. |
setWrapText(bool Wrap) |
Enables or disables word wrap. |
setEditable(bool Editable) |
Makes the area read-only when false. |
setId(string Id) |
Sets the CSS ID. |
setNodeStyle(string Style) |
Applies a JavaFX node CSS string to the whole area (InlineCssTextArea only -- use setStyle on StyleClassedTextArea/CodeArea). |
setStyle(string Style) |
Applies a JavaFX node CSS string (StyleClassedTextArea and CodeArea). |
getStylesheets() |
Returns the stylesheet list. Call .invoke("add", "path.css") on it. |
setLineNumbers(bool Show) |
Shows or hides the line number gutter. |
setContextMenu(object Menu) |
Attaches a custom context menu. |
| Method | Description |
|---|---|
scrollToPixel(double X, double Y) |
Scrolls to an absolute pixel position. |
scrollYBy(double Delta) |
Scrolls vertically by a delta. |
scrollXBy(double Delta) |
Scrolls horizontally by a delta. |
scrollToBottom() |
Scrolls to the end of the content. |
| Method | Description |
|---|---|
setStyle(int From, int To, string Css) |
Applies a CSS string to the range [From, To). |
setStyleOfParagraph(int ParIndex, string Css) |
Applies a CSS string to a paragraph background. |
clearStyle(int From, int To) |
Removes inline style from the range. |
clearStyleOfParagraph(int ParIndex) |
Removes paragraph-level style. |
clearStyles() |
Removes all inline styles. |
| Method | Description |
|---|---|
setStyleClass(int From, int To, string Class) |
Assigns one CSS class to the range. |
setStyleClasses(int From, int To, list Classes) |
Assigns multiple CSS classes to the range. |
setStyleClassOfParagraph(int ParIndex, string Class) |
Assigns a CSS class to a whole paragraph. |
clearStyle(int From, int To) |
Removes all style classes from the range. |
clearStyleOfParagraph(int ParIndex) |
Removes style classes from a paragraph. |
clearStyles() |
Removes all style classes. |
| Method | Description |
|---|---|
setSyntaxHighlighter(callback Highlighter) |
Registers a callback invoked on every text change. The callback receives the full updated text as a string. |
| Method | Description |
|---|---|
onChange(callback OnChange) |
Fires on every plain text change. Callback receives a PlainTextChange Java object. |
onCaretChange(callback OnChange) |
Fires when the caret moves. Callback signature: (ObservableValue, OldPos, NewPos). |
onSelectionChange(callback OnChange) |
Fires when the selection changes. Callback signature: (ObservableValue, OldRange, NewRange). |
onMouseOverText(callback OnHover) |
Fires when the mouse hovers over text. Use with setMouseOverTextDelay(int Millis). |
getText() returns the full document. To get a substring, call getTextRange(Start, End).
Calling getText(Start, End) will fail with an argument count error because Aussom does not
support method overloading by argument count.
On InlineCssTextArea, the method setStyle(int, int, string) is the range styler.
To apply a CSS string to the control node itself (e.g., border, background), use
setNodeStyle(string) instead. On StyleClassedTextArea and CodeArea, which have no
range setStyle overload, use setStyle(string) directly.
The clipboard copy method is named copyToClipboard() because copy() conflicts with the
inherited FxObj.copy(Val) constructor helper used by every Aussom fx class.
All range methods (setStyle, setStyleClass, deleteText, etc.) take character indices,
not pixel offsets. Use getLength() as the upper bound, and validate that From < To and
To <= getLength() before calling to avoid index out of bounds exceptions.
After you call app.show(), all operations that modify area content or style should run
on the JavaFX Application Thread. Wrap them with fx.runLater():
fx.runLater(::updateStyles);
public updateStyles() {
area.clearStyles();
area.setStyle(0, 5, "-fx-fill: red;");
}
Constructing the area and calling methods before app.show() is safe off the FX thread.
When attaching an external CSS file to getStylesheets(), the area must already be part of
a live scene for the stylesheet to apply. Add the stylesheet after app.show(). The path
should be a valid URI string. For files in your project, convert the path to a file:// URI:
area.getStylesheets().invoke("add", "file:///path/to/syntax.css");
The highlighter callback runs on every plain text change, including each individual key
press. For large documents, keep the highlighting logic fast. If performance is a concern,
only re-highlight the affected paragraph rather than calling clearStyles() on the entire
document each time.
getSelection() returns an AussomJavaObject wrapping a Java IndexRange. Read the bounds
with .invoke("getStart") and .invoke("getEnd"). The result is 0 for both when nothing
is selected, so check start < end before applying styles:
sel = area.getSelection();
start = sel.invoke("getStart");
end = sel.invoke("getEnd");
if (start < end) {
area.setStyle(start, end, "-fx-fill: orange;");
}
setLineNumbers(true) calls LineNumberFactory.get(this.obj) which binds the factory to
that specific area instance. If you create a second area, call setLineNumbers on it
separately. Calling setLineNumbers(false) removes the gutter by setting the factory to
null, which is safe to call at any time.
Write out large numbers without exponent notation. 1.0E10 is a parse error; use
10000000000.0 or a suitably large integer value instead.