Skip to content

Commit 87c2b30

Browse files
committed
Merge pull request #232 from JordanMartinez/splitView-Cleaned
2+ Views (areas) share the same Model (document)
2 parents ac4a0d4 + 7bb340e commit 87c2b30

9 files changed

Lines changed: 394 additions & 69 deletions

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package org.fxmisc.richtext.demo;
2+
3+
import javafx.application.Application;
4+
import javafx.scene.Scene;
5+
import javafx.scene.control.Button;
6+
import javafx.scene.control.Label;
7+
import javafx.scene.layout.BorderPane;
8+
import javafx.scene.layout.GridPane;
9+
import javafx.scene.layout.VBox;
10+
import javafx.stage.Stage;
11+
import org.fxmisc.richtext.AreaFactory;
12+
import org.fxmisc.richtext.InlineCssTextArea;
13+
14+
public class CloneDemo extends Application {
15+
16+
public static void main(String[] args) {
17+
launch(args);
18+
}
19+
20+
@Override
21+
public void start(Stage primaryStage) {
22+
String selectedText = "selection";
23+
String text = "Edit the top area (original)\nand watch the (clone) bottom area's displayed text change and its " +
24+
"selected text [" + selectedText + "] update itself accordingly.";
25+
InlineCssTextArea area = AreaFactory.inlineCssTextArea(text);
26+
InlineCssTextArea clone = AreaFactory.cloneInlineCssTextArea(area);
27+
28+
VBox vbox = new VBox(area, clone);
29+
vbox.setSpacing(10);
30+
31+
// set up labels displaying caret position
32+
String caret = "Caret: ";
33+
Label areaCaret = new Label(caret);
34+
area.caretPositionProperty().addListener((observable, oldValue, newValue) -> areaCaret.setText(caret + String.valueOf(newValue)));
35+
Label cloneCaret = new Label(caret);
36+
clone.caretPositionProperty().addListener((observable, oldValue, newValue) -> cloneCaret.setText(caret + String.valueOf(newValue)));
37+
38+
// set up label's displaying selection position
39+
String selection = "Selected Text: ";
40+
Label areaSelection = new Label(selection);
41+
area.selectedTextProperty().addListener(((observable, oldValue, newValue) -> areaSelection.setText(selection + newValue)));
42+
Label cloneSelection = new Label(selection);
43+
clone.selectedTextProperty().addListener(((observable, oldValue, newValue) -> cloneSelection.setText(selection + newValue)));
44+
45+
// now that listeners are set up update the selection for clone
46+
int selectionStart = text.indexOf(selectedText);
47+
int selectionEnd = selectionStart + selectedText.length();
48+
clone.selectRange(selectionStart, selectionEnd);
49+
50+
// set up Label's distinguishing which labels belong to which area.
51+
Label areaLabel = new Label("Original Area: ");
52+
Label cloneLabel = new Label("Cloned Area: ");
53+
54+
// set up Buttons that programmatically change area but not clone
55+
Button deleteLastThreeChars = new Button("Click to Delete the previous 3 chars.");
56+
deleteLastThreeChars.setOnAction((ae) -> {
57+
for (int i = 0; i <= 2; i++) {
58+
area.deletePreviousChar();
59+
}
60+
});
61+
62+
// finish GUI
63+
GridPane grid = new GridPane();
64+
// add area content to first row
65+
grid.add(areaLabel, 0, 0);
66+
grid.add(areaCaret, 1, 0);
67+
grid.add(areaSelection, 2, 0);
68+
69+
// add clone content to second row
70+
grid.add(cloneLabel, 0, 1);
71+
grid.add(cloneCaret, 1, 1);
72+
grid.add(cloneSelection, 2, 1);
73+
74+
grid.setHgap(10);
75+
grid.setVgap(4);
76+
77+
BorderPane pane = new BorderPane();
78+
pane.setCenter(vbox);
79+
pane.setTop(grid);
80+
pane.setBottom(deleteLastThreeChars);
81+
82+
Scene scene = new Scene(pane, 800, 500);
83+
primaryStage.setScene(scene);
84+
primaryStage.show();
85+
}
86+
}

richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/richtext/RichText.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
import org.fxmisc.flowless.VirtualizedScrollPane;
3737
import org.fxmisc.richtext.AreaFactory;
38-
import org.fxmisc.richtext.InlineStyleTextArea;
3938
import org.fxmisc.richtext.Paragraph;
4039
import org.fxmisc.richtext.StyleSpans;
4140
import org.fxmisc.richtext.StyledTextArea;
@@ -48,11 +47,11 @@ public static void main(String[] args) {
4847
}
4948

5049
private final StyledTextArea<TextStyle, ParStyle> area =
51-
AreaFactory.inlineStyleTextArea(
50+
AreaFactory.<TextStyle, ParStyle>styledTextArea(
5251
TextStyle.EMPTY.updateFontSize(12).updateFontFamily("Serif").updateTextColor(Color.BLACK),
53-
TextStyle::toCss,
52+
( text, style) -> text.setStyle(style.toCss()),
5453
ParStyle.EMPTY,
55-
ParStyle::toCss);
54+
( paragraph, style) -> paragraph.setStyle(style.toCss()));
5655
{
5756
area.setWrapText(true);
5857
area.setStyleCodecs(TextStyle.CODEC, ParStyle.CODEC);

richtextfx/src/main/java/org/fxmisc/richtext/AreaFactory.java

Lines changed: 132 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import org.fxmisc.flowless.VirtualizedScrollPane;
55

66
import java.util.function.BiConsumer;
7-
import java.util.function.Function;
87

98
/**
109
* AreaFactory is a convenience class used to create StyledTextArea
@@ -13,106 +12,195 @@
1312
*
1413
*/
1514
public class AreaFactory {
15+
16+
/* ********************************************************************** *
17+
* *
18+
* StyledTextArea *
19+
* *
20+
* ********************************************************************** */
21+
22+
// StyledTextArea 1
1623
public static <S, PS> StyledTextArea<S, PS> styledTextArea(
1724
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
18-
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle, boolean preserveStyle
25+
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
1926
) {
20-
return new StyledTextArea<S, PS>(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, preserveStyle);
27+
return new StyledTextArea<S, PS>(
28+
initialStyle, applyStyle,
29+
initialParagraphStyle, applyParagraphStyle,
30+
true);
2131
}
2232

23-
public static <S, PS> StyledTextArea<S, PS> styledTextArea(
33+
// Embeds StyledTextArea 1
34+
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
2435
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
2536
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
2637
) {
27-
return new StyledTextArea<S, PS>(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, true);
38+
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle));
2839
}
2940

41+
// StyledTextArea 2
42+
public static <S, PS> StyledTextArea<S, PS> styledTextArea(
43+
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
44+
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle,
45+
boolean preserveStyle
46+
) {
47+
return new StyledTextArea<S, PS>(
48+
initialStyle, applyStyle,
49+
initialParagraphStyle, applyParagraphStyle,
50+
preserveStyle);
51+
}
52+
53+
// Embeds StyledTextArea 2
3054
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
3155
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
3256
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle, boolean preserveStyle
3357
) {
3458
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, preserveStyle));
3559
}
3660

37-
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
38-
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
39-
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
61+
// Clones StyledTextArea
62+
public static <S, PS> StyledTextArea<S, PS> cloneStyleTextArea(StyledTextArea<S, PS> area) {
63+
return new StyledTextArea<S, PS>(area.getInitialStyle(), area.getApplyStyle(),
64+
area.getInitialParagraphStyle(), area.getApplyParagraphStyle(),
65+
area.getContent(), area.isPreserveStyle());
66+
}
67+
68+
// Embeds cloned StyledTextArea
69+
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedClonedStyledTextArea(StyledTextArea<S, PS> area) {
70+
return new VirtualizedScrollPane<>(cloneStyleTextArea(area));
71+
}
72+
73+
// Embeds a cloned StyledTextArea from an embedded StyledTextArea
74+
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedClonedStyledTextArea(
75+
VirtualizedScrollPane<StyledTextArea<S, PS>> virtualizedScrollPaneWithArea
4076
) {
41-
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle));
77+
return embeddedClonedStyledTextArea(virtualizedScrollPaneWithArea.getContent());
4278
}
4379

80+
/* ********************************************************************** *
81+
* *
82+
* StyleClassedTextArea *
83+
* *
84+
* ********************************************************************** */
85+
86+
// StyleClassedTextArea 1
4487
public static StyleClassedTextArea styleClassedTextArea(boolean preserveStyle) {
4588
return new StyleClassedTextArea(preserveStyle);
4689
}
4790

48-
public static StyleClassedTextArea styleClassedTextArea() {
49-
return styleClassedTextArea(true);
50-
}
51-
91+
// Embeds StyleClassedTextArea 1
5292
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedStyleClassedTextArea(boolean preserveStyle) {
5393
return new VirtualizedScrollPane<>(styleClassedTextArea(preserveStyle));
5494
}
5595

96+
// StyleClassedTextArea 2
97+
public static StyleClassedTextArea styleClassedTextArea() {
98+
return styleClassedTextArea(true);
99+
}
100+
101+
// Embeds StyleClassedTextArea 2
56102
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedStyleClassedTextArea() {
57103
return new VirtualizedScrollPane<>(styleClassedTextArea());
58104
}
59105

60-
public static CodeArea codeArea() {
61-
return new CodeArea();
106+
// Clones StyleClassedTextArea
107+
public static StyleClassedTextArea cloneStyleClassedTextArea(StyleClassedTextArea area) {
108+
return new StyleClassedTextArea(area.getContent(), area.isPreserveStyle());
62109
}
63110

64-
public static CodeArea codeArea(String text) {
65-
return new CodeArea(text);
111+
// Embeds cloned StyleClassedTextArea
112+
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedClonedStyleClassedTextArea(StyleClassedTextArea area) {
113+
return new VirtualizedScrollPane<>(cloneStyleClassedTextArea(area));
66114
}
67115

116+
// Embeds a cloned StyleClassedTextArea from an embedded StyleClassedTextArea
117+
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedClonedStyleClassedTextArea(
118+
VirtualizedScrollPane<StyleClassedTextArea> virtualizedScrollPaneWithArea
119+
) {
120+
return embeddedClonedStyleClassedTextArea(virtualizedScrollPaneWithArea.getContent());
121+
}
122+
123+
/* ********************************************************************** *
124+
* *
125+
* CodeArea *
126+
* *
127+
* ********************************************************************** */
128+
129+
// CodeArea 1
130+
public static CodeArea codeArea() {
131+
return new CodeArea();
132+
}
133+
134+
// Embeds CodeArea 1
68135
public static VirtualizedScrollPane<CodeArea> embeddedCodeArea() {
69136
return new VirtualizedScrollPane<>(codeArea());
70137
}
71138

139+
// CodeArea 2
140+
public static CodeArea codeArea(String text) {
141+
return new CodeArea(text);
142+
}
143+
144+
// Embeds CodeArea 2
72145
public static VirtualizedScrollPane<CodeArea> embeddedCodeArea(String text) {
73146
return new VirtualizedScrollPane<>(codeArea(text));
74147
}
75148

76-
/**
77-
* Creates a text area that uses inline css derived from the style info to define
78-
* style of text segments.
79-
*
80-
* @param <S> type of text style information.
81-
* @param <PS> type of paragraph style information.
82-
* @param initialStyle style to use for text ranges where no other
83-
* style is set via {@code setStyle(...)} methods.
84-
* @param styleToCss function that converts an instance of {@code S}
85-
* to a CSS string.
86-
*/
87-
public static <S, PS> StyledTextArea<S, PS> inlineStyleTextArea(
88-
S initialStyle, Function<S, String> styleToCss, PS initialParagraphStyle, Function<PS, String> paragraphStyleToCss
89-
) {
90-
return styledTextArea(
91-
initialStyle,
92-
(text, style) -> text.setStyle(styleToCss.apply(style)),
93-
initialParagraphStyle,
94-
(paragraph, style) -> paragraph.setStyle(paragraphStyleToCss.apply(style)));
149+
// Clones CodeArea
150+
public static CodeArea cloneCodeArea(CodeArea area) {
151+
return new CodeArea(area.getContent());
95152
}
96153

97-
public static <S, PS> VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedInlineStyleTextArea(
98-
S initialStyle, Function<S, String> styleToCss, PS initialParagraphStyle, Function<PS, String> paragraphStyleToCss
99-
) {
100-
return new VirtualizedScrollPane<>(inlineStyleTextArea(initialStyle, styleToCss, initialParagraphStyle, paragraphStyleToCss));
154+
// Embeds a cloned CodeArea
155+
public static VirtualizedScrollPane<CodeArea> embeddedClonedCodeArea(CodeArea area) {
156+
return new VirtualizedScrollPane<>(cloneCodeArea(area));
101157
}
102158

103-
public static InlineCssTextArea inlineCssTextArea() {
104-
return new InlineCssTextArea();
159+
// Embeds a cloned CodeArea from an embedded CodeArea
160+
public static VirtualizedScrollPane<CodeArea> embeddedClonedCodeArea(VirtualizedScrollPane<CodeArea> virtualizedScrollPaneWithArea) {
161+
return new VirtualizedScrollPane<>(cloneCodeArea(virtualizedScrollPaneWithArea.getContent()));
105162
}
106163

107-
public static InlineCssTextArea inlineCssTextArea(String text) {
108-
return new InlineCssTextArea(text);
164+
/* ********************************************************************** *
165+
* *
166+
* InlineCssTextArea *
167+
* *
168+
* ********************************************************************** */
169+
170+
// InlineCssTextArea 1
171+
public static InlineCssTextArea inlineCssTextArea() {
172+
return new InlineCssTextArea();
109173
}
110174

175+
// Embeds InlineCssTextArea 1
111176
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInlineCssTextArea() {
112177
return new VirtualizedScrollPane<>(inlineCssTextArea());
113178
}
114179

180+
// InlineCssTextArea 2
181+
public static InlineCssTextArea inlineCssTextArea(String text) {
182+
return new InlineCssTextArea(text);
183+
}
184+
185+
// Embeds InlineCssTextArea 2
115186
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInlineCssTextArea(String text) {
116187
return new VirtualizedScrollPane<>(inlineCssTextArea(text));
117188
}
189+
190+
// Clones InlineCssTextArea
191+
public static InlineCssTextArea cloneInlineCssTextArea(InlineCssTextArea area) {
192+
return new InlineCssTextArea(area.getContent());
193+
}
194+
195+
// Embeds a cloned InlineCssTextArea
196+
public static VirtualizedScrollPane<InlineCssTextArea> embeddedClonedInlineCssTextArea(InlineCssTextArea area) {
197+
return new VirtualizedScrollPane<>(cloneInlineCssTextArea(area));
198+
}
199+
200+
// Embeds a cloned InlineCssTextArea from an embedded InlineCssTextArea
201+
public static VirtualizedScrollPane<InlineCssTextArea> embeddedClonedInlineCssTextArea(
202+
VirtualizedScrollPane<InlineCssTextArea> virtualizedScrollPaneWithArea
203+
) {
204+
return new VirtualizedScrollPane<>(cloneInlineCssTextArea(virtualizedScrollPaneWithArea.getContent()));
205+
}
118206
}

richtextfx/src/main/java/org/fxmisc/richtext/CodeArea.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package org.fxmisc.richtext;
22

33

4+
import java.util.Collection;
5+
46
/**
57
* A convenience subclass of {@link StyleClassedTextArea}
68
* with fixed-width font and an undo manager that observes
@@ -18,6 +20,10 @@ public class CodeArea extends StyleClassedTextArea {
1820
setUseInitialStyleForInsertion(true);
1921
}
2022

23+
public CodeArea(EditableStyledDocument<Collection<String>, Collection<String>> document) {
24+
super(document, false);
25+
}
26+
2127
public CodeArea() {
2228
super(false);
2329
}

richtextfx/src/main/java/org/fxmisc/richtext/EditableStyledDocument.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.reactfx.EventStream;
2222
import org.reactfx.EventStreams;
2323
import org.reactfx.Guard;
24+
import org.reactfx.SuspendableNo;
2425
import org.reactfx.util.Lists;
2526
import org.reactfx.value.SuspendableVar;
2627
import org.reactfx.value.Val;
@@ -381,6 +382,10 @@ public void setParagraphStyle(int parIdx, PS style) {
381382
* *
382383
* ********************************************************************** */
383384

385+
private final SuspendableNo beingUpdated = new SuspendableNo();
386+
SuspendableNo beingUpdatedProperty() { return beingUpdated; }
387+
final boolean isBeingUpdated() { return beingUpdated.get(); }
388+
384389
private void ensureValidParagraphIndex(int parIdx) {
385390
Lists.checkIndex(parIdx, paragraphs.size());
386391
}

0 commit comments

Comments
 (0)