Skip to content

8356042: RichTextArea: tab stops attributes #1800

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 81 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
338a603
initial attempt
andy-goryachev-oracle Dec 20, 2024
6c3aed4
whitespace
andy-goryachev-oracle Dec 20, 2024
1bcb6bc
add line
andy-goryachev-oracle Dec 23, 2024
af24878
spacing
andy-goryachev-oracle Dec 23, 2024
d9fe0ba
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Jan 8, 2025
5cfcd48
font
andy-goryachev-oracle Jan 8, 2025
5102195
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Jan 21, 2025
8216208
truncated
andy-goryachev-oracle Jan 22, 2025
5222d1c
glyph run
andy-goryachev-oracle Jan 22, 2025
d43d51a
stub fonts
andy-goryachev-oracle Jan 23, 2025
8cd8ce3
add exports
andy-goryachev-oracle Jan 23, 2025
6d7682f
more
andy-goryachev-oracle Jan 23, 2025
c8b28bf
magic numbers
andy-goryachev-oracle Jan 24, 2025
0f98e4d
more magic
andy-goryachev-oracle Jan 24, 2025
f5c9118
cleanup
andy-goryachev-oracle Jan 24, 2025
ad5f514
better test
andy-goryachev-oracle Jan 24, 2025
a4a3ebb
cleanup
andy-goryachev-oracle Jan 24, 2025
a66e4d2
Merge branch 'master' into 8342565.stub.text.layout
andy-goryachev-oracle Jan 29, 2025
5010278
atomic boolean
andy-goryachev-oracle Jan 29, 2025
a082bbc
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Feb 4, 2025
b104282
review comments
andy-goryachev-oracle Feb 4, 2025
d212847
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Feb 20, 2025
d29bebd
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Feb 26, 2025
3650989
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Mar 5, 2025
bd6a6be
Merge remote-tracking branch 'origin/master' into 8342565.stub.text.l…
andy-goryachev-oracle Mar 6, 2025
1c4e5a8
review comments
andy-goryachev-oracle Mar 6, 2025
0e9e8ee
fixed bad merge
andy-goryachev-oracle Mar 6, 2025
e18e49a
Revert "fixed bad merge"
andy-goryachev-oracle Mar 6, 2025
980c98c
proof of concept
andy-goryachev-oracle Mar 7, 2025
fc038f9
after content
andy-goryachev-oracle Mar 7, 2025
9808ba4
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Mar 10, 2025
7516100
tab stop policy
andy-goryachev-oracle Mar 10, 2025
1bdc229
javadoc
andy-goryachev-oracle Mar 11, 2025
759e461
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Mar 19, 2025
149416c
tab stop policy is a class
andy-goryachev-oracle Mar 25, 2025
1151b2d
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Mar 25, 2025
190288a
jcheck
andy-goryachev-oracle Mar 25, 2025
4f15994
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Mar 26, 2025
d3adadf
whitespace
andy-goryachev-oracle Mar 26, 2025
2f4be8e
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 3, 2025
6e2cce9
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 4, 2025
9196280
compute offset
andy-goryachev-oracle Apr 8, 2025
32a48d5
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 8, 2025
c92f4e4
region
andy-goryachev-oracle Apr 9, 2025
7e4d3c4
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 14, 2025
9afc392
local to scene
andy-goryachev-oracle Apr 21, 2025
fe9d3ce
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 21, 2025
2755326
moved
andy-goryachev-oracle Apr 21, 2025
b38c8f2
wired
andy-goryachev-oracle Apr 22, 2025
8c54524
seems to work
andy-goryachev-oracle Apr 30, 2025
22afd85
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle Apr 30, 2025
b91bf7a
cleanup
andy-goryachev-oracle Apr 30, 2025
b0c0b5d
ruler
andy-goryachev-oracle May 1, 2025
408ac73
reference
andy-goryachev-oracle May 12, 2025
0d4319a
Merge remote-tracking branch 'origin/master' into 8356042.ruler
andy-goryachev-oracle May 12, 2025
7211743
tab stops attribute
andy-goryachev-oracle May 14, 2025
7fa74e4
Merge remote-tracking branch 'origin/master' into 8356042.ruler
andy-goryachev-oracle May 14, 2025
778c7e9
ws
andy-goryachev-oracle May 14, 2025
278f03c
removed reference
andy-goryachev-oracle May 16, 2025
6143d4c
space advance
andy-goryachev-oracle May 19, 2025
4bfe760
Merge remote-tracking branch 'origin/master' into 8356042.ruler
andy-goryachev-oracle May 19, 2025
35e9679
content padding setting
andy-goryachev-oracle May 19, 2025
8c776d1
Merge remote-tracking branch 'origin/master' into 8314482.tab.stops
andy-goryachev-oracle May 19, 2025
33c8968
api
andy-goryachev-oracle May 19, 2025
d624df5
cleanup
andy-goryachev-oracle May 19, 2025
ea9fa50
Merge branch '8314482.tab.stops' into 8356042.ruler
andy-goryachev-oracle May 19, 2025
a6532a4
fixed attribute serialization
andy-goryachev-oracle May 20, 2025
7669815
fixed attribute serialization
andy-goryachev-oracle May 20, 2025
0173357
tests
andy-goryachev-oracle May 20, 2025
c5b3e82
Merge branch '8357393.attr.ser' into 8356042.ruler
andy-goryachev-oracle May 20, 2025
d0551e4
test
andy-goryachev-oracle May 21, 2025
1d2625e
Merge remote-tracking branch 'origin/master' into 8357393.attr.ser
andy-goryachev-oracle May 21, 2025
3526d6d
Merge branch '8357393.attr.ser' into 8356042.ruler
andy-goryachev-oracle May 21, 2025
06b3181
javadoc
andy-goryachev-oracle May 21, 2025
0e1a5a7
Merge branch '8357393.attr.ser' into 8356042.ruler
andy-goryachev-oracle May 21, 2025
4b047dd
25
andy-goryachev-oracle May 29, 2025
147502b
Merge remote-tracking branch 'origin/master' into 8357393.attr.ser
andy-goryachev-oracle May 29, 2025
3cb33f9
Merge branch '8357393.attr.ser' into 8356042.ruler
andy-goryachev-oracle May 29, 2025
ce5c8d4
Merge remote-tracking branch 'origin/master' into 8356042.ruler
andy-goryachev-oracle Jun 3, 2025
7e930fb
popup
andy-goryachev-oracle Jun 4, 2025
d296c46
selected paragraphs
andy-goryachev-oracle Jun 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
import javafx.scene.control.Dialog;
import javafx.scene.input.DataFormat;
import javafx.scene.paint.Color;
import javafx.scene.text.TabStop;
import javafx.scene.text.TabStopPolicy;
import javafx.stage.FileChooser;
import javafx.stage.Window;
import com.oracle.demo.richtext.common.Styles;
Expand Down Expand Up @@ -103,13 +105,15 @@ public class Actions {
public final FxAction wrapText = new FxAction();

private final RichTextArea control;
private final Ruler ruler;
private final ReadOnlyBooleanWrapper modified = new ReadOnlyBooleanWrapper();
private final ReadOnlyObjectWrapper<File> file = new ReadOnlyObjectWrapper<>();
private final SimpleObjectProperty<StyleAttributeMap> styles = new SimpleObjectProperty<>();
private final SimpleObjectProperty<TextStyle> textStyle = new SimpleObjectProperty<>();

public Actions(RichTextArea control) {
public Actions(RichTextArea control, Ruler ruler) {
this.control = control;
this.ruler = ruler;

// undo/redo actions
redo.disabledProperty().bind(control.redoableProperty().not());
Expand Down Expand Up @@ -206,6 +210,18 @@ private void handleCaret() {
italic.setSelected(a.getBoolean(StyleAttributeMap.ITALIC), false);
underline.setSelected(a.getBoolean(StyleAttributeMap.UNDERLINE), false);
strikeThrough.setSelected(a.getBoolean(StyleAttributeMap.STRIKE_THROUGH), false);

if (ruler != null) {
TabStopPolicy tp = ruler.getTabStopPolicy();
if (tp != null) {
TabStop[] ts = a.get(StyleAttributeMap.TAB_STOPS);
if (ts == null) {
tp.tabStops().clear();
} else {
tp.tabStops().setAll(ts);
}
}
}
}

private void toggle(StyleAttribute<Boolean> attr) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
* Copyright (c) 2023, 2025, Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
Expand Down Expand Up @@ -39,13 +39,19 @@
import javafx.scene.control.ToolBar;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.TabStop;
import javafx.scene.text.TabStopPolicy;
import com.oracle.demo.richtext.common.TextStyle;
import com.oracle.demo.richtext.editor.settings.EndKey;
import com.oracle.demo.richtext.util.FX;
import com.oracle.demo.richtext.util.FxAction;
import jfx.incubator.scene.control.input.KeyBinding;
import jfx.incubator.scene.control.richtext.RichTextArea;
import jfx.incubator.scene.control.richtext.SelectionSegment;
import jfx.incubator.scene.control.richtext.TextPos;
import jfx.incubator.scene.control.richtext.model.StyleAttributeMap;

/**
* Main Panel.
Expand All @@ -55,10 +61,12 @@
public class RichEditorDemoPane extends BorderPane {
public final RichTextArea editor;
public final Actions actions;
private final Ruler ruler;
private final ComboBox<String> fontName;
private final ComboBox<Integer> fontSize;
private final ColorPicker textColor;
private final ComboBox<TextStyle> textStyle;
private TabStopPolicy tabPolicy;

public RichEditorDemoPane() {
FX.name(this, "RichEditorDemoPane");
Expand All @@ -69,7 +77,14 @@ public RichEditorDemoPane() {
System.out.println("Custom function: W key is pressed");
});

actions = new Actions(editor);
ruler = new Ruler(editor);
ruler.setOnChange(this::handleTabStopChange);
tabPolicy = new TabStopPolicy();
ruler.setTabStopPolicy(tabPolicy);

FX.setPopupMenu(ruler, this::createRulerPopupMenu);

actions = new Actions(editor, ruler);
editor.setContextMenu(createContextMenu());

fontName = new ComboBox<>();
Expand Down Expand Up @@ -108,9 +123,8 @@ public RichEditorDemoPane() {
textColor = new ColorPicker();
// TODO save/restore custom colors
FX.tooltip(textColor, "Text Color");
// FIX there is no API for this! why is this a property of a skin, not the control??
// https://stackoverflow.com/questions/21246137/remove-text-from-colour-picker
textColor.setStyle("-fx-color-label-visible: false ;");
textColor.setStyle("-fx-color-label-visible: false;");
textColor.setOnAction((ev) -> {
actions.setTextColor(textColor.getValue());
});
Expand All @@ -123,14 +137,15 @@ public RichEditorDemoPane() {
editor.requestFocus();
});

setTop(createToolBar());
setTop(new VBox(createToolBar(), ruler));
setCenter(editor);

actions.textStyleProperty().addListener((s,p,c) -> {
setTextStyle(c);
});

Settings.endKey.subscribe(this::setEndKey);
Settings.contentPadding.bindBidirectional(editor.contentPaddingProperty());
}

private ToolBar createToolBar() {
Expand Down Expand Up @@ -175,6 +190,12 @@ private ContextMenu createContextMenu() {
return m;
}

private ContextMenu createRulerPopupMenu() {
ContextMenu m = new ContextMenu();
FX.item(m, "Tab Options...", new FxAction(this::showTabOptions));
return m;
}

private static List<String> collectFonts() {
return Font.getFamilies();
}
Expand Down Expand Up @@ -228,4 +249,23 @@ private static int findLastText(String text, int start) {
}
return i;
}

private void showTabOptions() {
// TODO
}

private void handleTabStopChange() {
// TODO update default tabs if changed
SelectionSegment sel = editor.getSelection();
if (sel != null) {
TabStop[] ts = tabPolicy.tabStops().toArray(TabStop[]::new);
StyleAttributeMap a = StyleAttributeMap.builder().set(StyleAttributeMap.TAB_STOPS, ts).build();
int min = sel.getMin().index();
int max = sel.getMax().index();
for (int ix = min; ix <= max; ix++) {
TextPos p = TextPos.ofLeading(ix, 0);
editor.applyStyle(p, p, a);
}
}
}
}
Loading