Skip to content

Commit

Permalink
Merge pull request #232 from JordanMartinez/splitView-Cleaned
Browse files Browse the repository at this point in the history
2+ Views (areas) share the same Model (document)
  • Loading branch information
TomasMikula committed Dec 28, 2015
2 parents ac4a0d4 + 7bb340e commit 87c2b30
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package org.fxmisc.richtext.demo;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.fxmisc.richtext.AreaFactory;
import org.fxmisc.richtext.InlineCssTextArea;

public class CloneDemo extends Application {

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) {
String selectedText = "selection";
String text = "Edit the top area (original)\nand watch the (clone) bottom area's displayed text change and its " +
"selected text [" + selectedText + "] update itself accordingly.";
InlineCssTextArea area = AreaFactory.inlineCssTextArea(text);
InlineCssTextArea clone = AreaFactory.cloneInlineCssTextArea(area);

VBox vbox = new VBox(area, clone);
vbox.setSpacing(10);

// set up labels displaying caret position
String caret = "Caret: ";
Label areaCaret = new Label(caret);
area.caretPositionProperty().addListener((observable, oldValue, newValue) -> areaCaret.setText(caret + String.valueOf(newValue)));
Label cloneCaret = new Label(caret);
clone.caretPositionProperty().addListener((observable, oldValue, newValue) -> cloneCaret.setText(caret + String.valueOf(newValue)));

// set up label's displaying selection position
String selection = "Selected Text: ";
Label areaSelection = new Label(selection);
area.selectedTextProperty().addListener(((observable, oldValue, newValue) -> areaSelection.setText(selection + newValue)));
Label cloneSelection = new Label(selection);
clone.selectedTextProperty().addListener(((observable, oldValue, newValue) -> cloneSelection.setText(selection + newValue)));

// now that listeners are set up update the selection for clone
int selectionStart = text.indexOf(selectedText);
int selectionEnd = selectionStart + selectedText.length();
clone.selectRange(selectionStart, selectionEnd);

// set up Label's distinguishing which labels belong to which area.
Label areaLabel = new Label("Original Area: ");
Label cloneLabel = new Label("Cloned Area: ");

// set up Buttons that programmatically change area but not clone
Button deleteLastThreeChars = new Button("Click to Delete the previous 3 chars.");
deleteLastThreeChars.setOnAction((ae) -> {
for (int i = 0; i <= 2; i++) {
area.deletePreviousChar();
}
});

// finish GUI
GridPane grid = new GridPane();
// add area content to first row
grid.add(areaLabel, 0, 0);
grid.add(areaCaret, 1, 0);
grid.add(areaSelection, 2, 0);

// add clone content to second row
grid.add(cloneLabel, 0, 1);
grid.add(cloneCaret, 1, 1);
grid.add(cloneSelection, 2, 1);

grid.setHgap(10);
grid.setVgap(4);

BorderPane pane = new BorderPane();
pane.setCenter(vbox);
pane.setTop(grid);
pane.setBottom(deleteLastThreeChars);

Scene scene = new Scene(pane, 800, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@

import org.fxmisc.flowless.VirtualizedScrollPane;
import org.fxmisc.richtext.AreaFactory;
import org.fxmisc.richtext.InlineStyleTextArea;
import org.fxmisc.richtext.Paragraph;
import org.fxmisc.richtext.StyleSpans;
import org.fxmisc.richtext.StyledTextArea;
Expand All @@ -48,11 +47,11 @@ public static void main(String[] args) {
}

private final StyledTextArea<TextStyle, ParStyle> area =
AreaFactory.inlineStyleTextArea(
AreaFactory.<TextStyle, ParStyle>styledTextArea(
TextStyle.EMPTY.updateFontSize(12).updateFontFamily("Serif").updateTextColor(Color.BLACK),
TextStyle::toCss,
( text, style) -> text.setStyle(style.toCss()),
ParStyle.EMPTY,
ParStyle::toCss);
( paragraph, style) -> paragraph.setStyle(style.toCss()));
{
area.setWrapText(true);
area.setStyleCodecs(TextStyle.CODEC, ParStyle.CODEC);
Expand Down
176 changes: 132 additions & 44 deletions richtextfx/src/main/java/org/fxmisc/richtext/AreaFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import org.fxmisc.flowless.VirtualizedScrollPane;

import java.util.function.BiConsumer;
import java.util.function.Function;

/**
* AreaFactory is a convenience class used to create StyledTextArea
Expand All @@ -13,106 +12,195 @@
*
*/
public class AreaFactory {

/* ********************************************************************** *
* *
* StyledTextArea *
* *
* ********************************************************************** */

// StyledTextArea 1
public static <S, PS> StyledTextArea<S, PS> styledTextArea(
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle, boolean preserveStyle
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
) {
return new StyledTextArea<S, PS>(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, preserveStyle);
return new StyledTextArea<S, PS>(
initialStyle, applyStyle,
initialParagraphStyle, applyParagraphStyle,
true);
}

public static <S, PS> StyledTextArea<S, PS> styledTextArea(
// Embeds StyledTextArea 1
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
) {
return new StyledTextArea<S, PS>(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, true);
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle));
}

// StyledTextArea 2
public static <S, PS> StyledTextArea<S, PS> styledTextArea(
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle,
boolean preserveStyle
) {
return new StyledTextArea<S, PS>(
initialStyle, applyStyle,
initialParagraphStyle, applyParagraphStyle,
preserveStyle);
}

// Embeds StyledTextArea 2
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle, boolean preserveStyle
) {
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle, preserveStyle));
}

public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedStyledTextArea(
S initialStyle, BiConsumer<? super TextExt, S> applyStyle,
PS initialParagraphStyle, BiConsumer<TextFlow, PS> applyParagraphStyle
// Clones StyledTextArea
public static <S, PS> StyledTextArea<S, PS> cloneStyleTextArea(StyledTextArea<S, PS> area) {
return new StyledTextArea<S, PS>(area.getInitialStyle(), area.getApplyStyle(),
area.getInitialParagraphStyle(), area.getApplyParagraphStyle(),
area.getContent(), area.isPreserveStyle());
}

// Embeds cloned StyledTextArea
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedClonedStyledTextArea(StyledTextArea<S, PS> area) {
return new VirtualizedScrollPane<>(cloneStyleTextArea(area));
}

// Embeds a cloned StyledTextArea from an embedded StyledTextArea
public static <S, PS>VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedClonedStyledTextArea(
VirtualizedScrollPane<StyledTextArea<S, PS>> virtualizedScrollPaneWithArea
) {
return new VirtualizedScrollPane<>(styledTextArea(initialStyle, applyStyle, initialParagraphStyle, applyParagraphStyle));
return embeddedClonedStyledTextArea(virtualizedScrollPaneWithArea.getContent());
}

/* ********************************************************************** *
* *
* StyleClassedTextArea *
* *
* ********************************************************************** */

// StyleClassedTextArea 1
public static StyleClassedTextArea styleClassedTextArea(boolean preserveStyle) {
return new StyleClassedTextArea(preserveStyle);
}

public static StyleClassedTextArea styleClassedTextArea() {
return styleClassedTextArea(true);
}

// Embeds StyleClassedTextArea 1
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedStyleClassedTextArea(boolean preserveStyle) {
return new VirtualizedScrollPane<>(styleClassedTextArea(preserveStyle));
}

// StyleClassedTextArea 2
public static StyleClassedTextArea styleClassedTextArea() {
return styleClassedTextArea(true);
}

// Embeds StyleClassedTextArea 2
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedStyleClassedTextArea() {
return new VirtualizedScrollPane<>(styleClassedTextArea());
}

public static CodeArea codeArea() {
return new CodeArea();
// Clones StyleClassedTextArea
public static StyleClassedTextArea cloneStyleClassedTextArea(StyleClassedTextArea area) {
return new StyleClassedTextArea(area.getContent(), area.isPreserveStyle());
}

public static CodeArea codeArea(String text) {
return new CodeArea(text);
// Embeds cloned StyleClassedTextArea
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedClonedStyleClassedTextArea(StyleClassedTextArea area) {
return new VirtualizedScrollPane<>(cloneStyleClassedTextArea(area));
}

// Embeds a cloned StyleClassedTextArea from an embedded StyleClassedTextArea
public static VirtualizedScrollPane<StyleClassedTextArea> embeddedClonedStyleClassedTextArea(
VirtualizedScrollPane<StyleClassedTextArea> virtualizedScrollPaneWithArea
) {
return embeddedClonedStyleClassedTextArea(virtualizedScrollPaneWithArea.getContent());
}

/* ********************************************************************** *
* *
* CodeArea *
* *
* ********************************************************************** */

// CodeArea 1
public static CodeArea codeArea() {
return new CodeArea();
}

// Embeds CodeArea 1
public static VirtualizedScrollPane<CodeArea> embeddedCodeArea() {
return new VirtualizedScrollPane<>(codeArea());
}

// CodeArea 2
public static CodeArea codeArea(String text) {
return new CodeArea(text);
}

// Embeds CodeArea 2
public static VirtualizedScrollPane<CodeArea> embeddedCodeArea(String text) {
return new VirtualizedScrollPane<>(codeArea(text));
}

/**
* Creates a text area that uses inline css derived from the style info to define
* style of text segments.
*
* @param <S> type of text style information.
* @param <PS> type of paragraph style information.
* @param initialStyle style to use for text ranges where no other
* style is set via {@code setStyle(...)} methods.
* @param styleToCss function that converts an instance of {@code S}
* to a CSS string.
*/
public static <S, PS> StyledTextArea<S, PS> inlineStyleTextArea(
S initialStyle, Function<S, String> styleToCss, PS initialParagraphStyle, Function<PS, String> paragraphStyleToCss
) {
return styledTextArea(
initialStyle,
(text, style) -> text.setStyle(styleToCss.apply(style)),
initialParagraphStyle,
(paragraph, style) -> paragraph.setStyle(paragraphStyleToCss.apply(style)));
// Clones CodeArea
public static CodeArea cloneCodeArea(CodeArea area) {
return new CodeArea(area.getContent());
}

public static <S, PS> VirtualizedScrollPane<StyledTextArea<S, PS>> embeddedInlineStyleTextArea(
S initialStyle, Function<S, String> styleToCss, PS initialParagraphStyle, Function<PS, String> paragraphStyleToCss
) {
return new VirtualizedScrollPane<>(inlineStyleTextArea(initialStyle, styleToCss, initialParagraphStyle, paragraphStyleToCss));
// Embeds a cloned CodeArea
public static VirtualizedScrollPane<CodeArea> embeddedClonedCodeArea(CodeArea area) {
return new VirtualizedScrollPane<>(cloneCodeArea(area));
}

public static InlineCssTextArea inlineCssTextArea() {
return new InlineCssTextArea();
// Embeds a cloned CodeArea from an embedded CodeArea
public static VirtualizedScrollPane<CodeArea> embeddedClonedCodeArea(VirtualizedScrollPane<CodeArea> virtualizedScrollPaneWithArea) {
return new VirtualizedScrollPane<>(cloneCodeArea(virtualizedScrollPaneWithArea.getContent()));
}

public static InlineCssTextArea inlineCssTextArea(String text) {
return new InlineCssTextArea(text);
/* ********************************************************************** *
* *
* InlineCssTextArea *
* *
* ********************************************************************** */

// InlineCssTextArea 1
public static InlineCssTextArea inlineCssTextArea() {
return new InlineCssTextArea();
}

// Embeds InlineCssTextArea 1
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInlineCssTextArea() {
return new VirtualizedScrollPane<>(inlineCssTextArea());
}

// InlineCssTextArea 2
public static InlineCssTextArea inlineCssTextArea(String text) {
return new InlineCssTextArea(text);
}

// Embeds InlineCssTextArea 2
public static VirtualizedScrollPane<InlineCssTextArea> embeddedInlineCssTextArea(String text) {
return new VirtualizedScrollPane<>(inlineCssTextArea(text));
}

// Clones InlineCssTextArea
public static InlineCssTextArea cloneInlineCssTextArea(InlineCssTextArea area) {
return new InlineCssTextArea(area.getContent());
}

// Embeds a cloned InlineCssTextArea
public static VirtualizedScrollPane<InlineCssTextArea> embeddedClonedInlineCssTextArea(InlineCssTextArea area) {
return new VirtualizedScrollPane<>(cloneInlineCssTextArea(area));
}

// Embeds a cloned InlineCssTextArea from an embedded InlineCssTextArea
public static VirtualizedScrollPane<InlineCssTextArea> embeddedClonedInlineCssTextArea(
VirtualizedScrollPane<InlineCssTextArea> virtualizedScrollPaneWithArea
) {
return new VirtualizedScrollPane<>(cloneInlineCssTextArea(virtualizedScrollPaneWithArea.getContent()));
}
}
6 changes: 6 additions & 0 deletions richtextfx/src/main/java/org/fxmisc/richtext/CodeArea.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.fxmisc.richtext;


import java.util.Collection;

/**
* A convenience subclass of {@link StyleClassedTextArea}
* with fixed-width font and an undo manager that observes
Expand All @@ -18,6 +20,10 @@ public class CodeArea extends StyleClassedTextArea {
setUseInitialStyleForInsertion(true);
}

public CodeArea(EditableStyledDocument<Collection<String>, Collection<String>> document) {
super(document, false);
}

public CodeArea() {
super(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.reactfx.EventStream;
import org.reactfx.EventStreams;
import org.reactfx.Guard;
import org.reactfx.SuspendableNo;
import org.reactfx.util.Lists;
import org.reactfx.value.SuspendableVar;
import org.reactfx.value.Val;
Expand Down Expand Up @@ -381,6 +382,10 @@ public void setParagraphStyle(int parIdx, PS style) {
* *
* ********************************************************************** */

private final SuspendableNo beingUpdated = new SuspendableNo();
SuspendableNo beingUpdatedProperty() { return beingUpdated; }
final boolean isBeingUpdated() { return beingUpdated.get(); }

private void ensureValidParagraphIndex(int parIdx) {
Lists.checkIndex(parIdx, paragraphs.size());
}
Expand Down
Loading

0 comments on commit 87c2b30

Please sign in to comment.