Search in sources :

Example 6 with Subscription

use of org.reactfx.Subscription in project RichTextFX by FXMisc.

the class JavaKeywords method start.

@Override
public void start(Stage primaryStage) {
    CodeArea codeArea = new CodeArea();
    // add line numbers to the left of area
    codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
    // recompute the syntax highlighting 500 ms after user stops editing area
    Subscription cleanupWhenNoLongerNeedIt = codeArea.multiPlainChanges().successionEnds(Duration.ofMillis(500)).subscribe(ignore -> codeArea.setStyleSpans(0, computeHighlighting(codeArea.getText())));
    // when no longer need syntax highlighting and wish to clean up memory leaks
    // run: `cleanupWhenNoLongerNeedIt.unsubscribe();`
    codeArea.replaceText(0, 0, sampleCode);
    Scene scene = new Scene(new StackPane(new VirtualizedScrollPane<>(codeArea)), 600, 400);
    scene.getStylesheets().add(JavaKeywordsAsync.class.getResource("java-keywords.css").toExternalForm());
    primaryStage.setScene(scene);
    primaryStage.setTitle("Java Keywords Demo");
    primaryStage.show();
}
Also used : Subscription(org.reactfx.Subscription) Scene(javafx.scene.Scene) StackPane(javafx.scene.layout.StackPane) VirtualizedScrollPane(org.fxmisc.flowless.VirtualizedScrollPane) CodeArea(org.fxmisc.richtext.CodeArea)

Example 7 with Subscription

use of org.reactfx.Subscription in project RichTextFX by FXMisc.

the class JavaKeywordsAsync method start.

@Override
public void start(Stage primaryStage) {
    executor = Executors.newSingleThreadExecutor();
    codeArea = new CodeArea();
    codeArea.setParagraphGraphicFactory(LineNumberFactory.get(codeArea));
    Subscription cleanupWhenDone = codeArea.multiPlainChanges().successionEnds(Duration.ofMillis(500)).supplyTask(this::computeHighlightingAsync).awaitLatest(codeArea.multiPlainChanges()).filterMap(t -> {
        if (t.isSuccess()) {
            return Optional.of(t.get());
        } else {
            t.getFailure().printStackTrace();
            return Optional.empty();
        }
    }).subscribe(this::applyHighlighting);
    // call when no longer need it: `cleanupWhenFinished.unsubscribe();`
    codeArea.replaceText(0, 0, sampleCode);
    Scene scene = new Scene(new StackPane(new VirtualizedScrollPane<>(codeArea)), 600, 400);
    scene.getStylesheets().add(JavaKeywordsAsync.class.getResource("java-keywords.css").toExternalForm());
    primaryStage.setScene(scene);
    primaryStage.setTitle("Java Keywords Async Demo");
    primaryStage.show();
}
Also used : Scene(javafx.scene.Scene) Collection(java.util.Collection) StyleSpans(org.fxmisc.richtext.model.StyleSpans) StackPane(javafx.scene.layout.StackPane) CodeArea(org.fxmisc.richtext.CodeArea) Executors(java.util.concurrent.Executors) LineNumberFactory(org.fxmisc.richtext.LineNumberFactory) StyleSpansBuilder(org.fxmisc.richtext.model.StyleSpansBuilder) Application(javafx.application.Application) Task(javafx.concurrent.Task) Matcher(java.util.regex.Matcher) Subscription(org.reactfx.Subscription) Stage(javafx.stage.Stage) VirtualizedScrollPane(org.fxmisc.flowless.VirtualizedScrollPane) Duration(java.time.Duration) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) Collections(java.util.Collections) ExecutorService(java.util.concurrent.ExecutorService) Subscription(org.reactfx.Subscription) Scene(javafx.scene.Scene) StackPane(javafx.scene.layout.StackPane) VirtualizedScrollPane(org.fxmisc.flowless.VirtualizedScrollPane) CodeArea(org.fxmisc.richtext.CodeArea)

Example 8 with Subscription

use of org.reactfx.Subscription in project RichTextFX by FXMisc.

the class SpellChecking method start.

@Override
public void start(Stage primaryStage) {
    StyleClassedTextArea textArea = new StyleClassedTextArea();
    textArea.setWrapText(true);
    Subscription cleanupWhenFinished = textArea.multiPlainChanges().successionEnds(Duration.ofMillis(500)).subscribe(change -> {
        textArea.setStyleSpans(0, computeHighlighting(textArea.getText()));
    });
    // load the dictionary
    try (InputStream input = getClass().getResourceAsStream("spellchecking.dict");
        BufferedReader br = new BufferedReader(new InputStreamReader(input))) {
        String line;
        while ((line = br.readLine()) != null) {
            dictionary.add(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    // load the sample document
    InputStream input2 = getClass().getResourceAsStream("spellchecking.txt");
    try (java.util.Scanner s = new java.util.Scanner(input2)) {
        String document = s.useDelimiter("\\A").hasNext() ? s.next() : "";
        textArea.replaceText(0, 0, document);
    }
    Scene scene = new Scene(new StackPane(new VirtualizedScrollPane<>(textArea)), 600, 400);
    scene.getStylesheets().add(getClass().getResource("spellchecking.css").toExternalForm());
    primaryStage.setScene(scene);
    primaryStage.setTitle("Spell Checking Demo");
    primaryStage.show();
}
Also used : InputStreamReader(java.io.InputStreamReader) InputStream(java.io.InputStream) IOException(java.io.IOException) Scene(javafx.scene.Scene) StyleClassedTextArea(org.fxmisc.richtext.StyleClassedTextArea) BufferedReader(java.io.BufferedReader) Subscription(org.reactfx.Subscription) StackPane(javafx.scene.layout.StackPane) VirtualizedScrollPane(org.fxmisc.flowless.VirtualizedScrollPane)

Example 9 with Subscription

use of org.reactfx.Subscription in project RichTextFX by FXMisc.

the class GenericStyledArea method createCell.

/* ********************************************************************** *
     *                                                                        *
     * Private methods                                                        *
     *                                                                        *
     * ********************************************************************** */
private Cell<Paragraph<PS, SEG, S>, ParagraphBox<PS, SEG, S>> createCell(Paragraph<PS, SEG, S> paragraph, BiConsumer<TextFlow, PS> applyParagraphStyle, Function<StyledSegment<SEG, S>, Node> nodeFactory) {
    ParagraphBox<PS, SEG, S> box = new ParagraphBox<>(paragraph, applyParagraphStyle, nodeFactory);
    box.highlightTextFillProperty().bind(highlightTextFill);
    box.wrapTextProperty().bind(wrapTextProperty());
    box.graphicFactoryProperty().bind(paragraphGraphicFactoryProperty());
    box.graphicOffset.bind(virtualFlow.breadthOffsetProperty());
    EventStream<Integer> boxIndexValues = box.indexProperty().values().filter(i -> i != -1);
    Subscription firstParPseudoClass = boxIndexValues.subscribe(idx -> box.pseudoClassStateChanged(FIRST_PAR, idx == 0));
    Subscription lastParPseudoClass = EventStreams.combine(boxIndexValues, getParagraphs().sizeProperty().values()).subscribe(in -> in.exec((i, n) -> box.pseudoClassStateChanged(LAST_PAR, i == n - 1)));
    // set up caret
    Function<CaretNode, Subscription> subscribeToCaret = caret -> {
        EventStream<Integer> caretIndexStream = EventStreams.nonNullValuesOf(caret.paragraphIndexProperty());
        // a new event stream needs to be created for each caret added, so that it will immediately
        // fire the box's current index value as an event, thereby running the code in the subscribe block
        // Reusing boxIndexValues will not fire its most recent event, leading to a caret not being added
        // Thus, we'll call the new event stream "fresh" box index values
        EventStream<Integer> freshBoxIndexValues = box.indexProperty().values().filter(i -> i != -1);
        return EventStreams.combine(caretIndexStream, freshBoxIndexValues).subscribe(t -> {
            int caretParagraphIndex = t.get1();
            int boxIndex = t.get2();
            if (caretParagraphIndex == boxIndex) {
                box.caretsProperty().add(caret);
            } else {
                box.caretsProperty().remove(caret);
            }
        });
    };
    Subscription caretSubscription = caretSet.addSubscriber(subscribeToCaret);
    // TODO: how should 'hasCaret' be handled now?
    Subscription hasCaretPseudoClass = EventStreams.combine(boxIndexValues, Val.wrap(currentParagraphProperty()).values()).map(t -> t.get1().equals(t.get2())).subscribe(value -> box.pseudoClassStateChanged(HAS_CARET, value));
    Function<Selection<PS, SEG, S>, Subscription> subscribeToSelection = selection -> {
        EventStream<Integer> startParagraphValues = EventStreams.nonNullValuesOf(selection.startParagraphIndexProperty());
        EventStream<Integer> endParagraphValues = EventStreams.nonNullValuesOf(selection.endParagraphIndexProperty());
        // see comment in caret section about why a new box index EventStream is needed
        EventStream<Integer> freshBoxIndexValues = box.indexProperty().values().filter(i -> i != -1);
        return EventStreams.combine(startParagraphValues, endParagraphValues, freshBoxIndexValues).subscribe(t -> {
            int startPar = t.get1();
            int endPar = t.get2();
            int boxIndex = t.get3();
            if (startPar <= boxIndex && boxIndex <= endPar) {
                // So that we don't add multiple paths for the same selection,
                // which leads to not removing the additional paths when selection is removed,
                // this is a `Map#putIfAbsent(Key, Value)` implementation that creates the path lazily
                SelectionPath p = box.selectionsProperty().get(selection);
                if (p == null) {
                    // create & configure path
                    Val<IndexRange> range = Val.create(() -> boxIndex != -1 ? getParagraphSelection(selection, boxIndex) : EMPTY_RANGE, selection.rangeProperty());
                    SelectionPath path = new SelectionPath(range);
                    selection.configureSelectionPath(path);
                    box.selectionsProperty().put(selection, path);
                }
            } else {
                box.selectionsProperty().remove(selection);
            }
        });
    };
    Subscription selectionSubscription = selectionSet.addSubscriber(subscribeToSelection);
    return new Cell<Paragraph<PS, SEG, S>, ParagraphBox<PS, SEG, S>>() {

        @Override
        public ParagraphBox<PS, SEG, S> getNode() {
            return box;
        }

        @Override
        public void updateIndex(int index) {
            box.setIndex(index);
        }

        @Override
        public void dispose() {
            box.highlightTextFillProperty().unbind();
            box.wrapTextProperty().unbind();
            box.graphicFactoryProperty().unbind();
            box.graphicOffset.unbind();
            firstParPseudoClass.unsubscribe();
            lastParPseudoClass.unsubscribe();
            caretSubscription.unsubscribe();
            hasCaretPseudoClass.unsubscribe();
            selectionSubscription.unsubscribe();
        }
    };
}
Also used : EventHandler(javafx.event.EventHandler) NamedArg(javafx.beans.NamedArg) SuspendableNo(org.reactfx.SuspendableNo) IntUnaryOperator(java.util.function.IntUnaryOperator) PseudoClass(javafx.css.PseudoClass) Cell(org.fxmisc.flowless.Cell) BiFunction(java.util.function.BiFunction) TextOps(org.fxmisc.richtext.model.TextOps) SuspendableEventStream(org.reactfx.SuspendableEventStream) PlainTextChange(org.fxmisc.richtext.model.PlainTextChange) StyleConverter(javafx.css.StyleConverter) ContextMenu(javafx.scene.control.ContextMenu) GenericEditableStyledDocument(org.fxmisc.richtext.model.GenericEditableStyledDocument) Duration(java.time.Duration) TwoDimensional(org.fxmisc.richtext.model.TwoDimensional) Point2D(javafx.geometry.Point2D) UndoManager(org.fxmisc.undo.UndoManager) VirtualFlowHit(org.fxmisc.flowless.VirtualFlowHit) SubscribeableContentsObsSet(org.fxmisc.richtext.util.SubscribeableContentsObsSet) Guard(org.reactfx.Guard) ObservableSet(javafx.collections.ObservableSet) UndoUtils(org.fxmisc.richtext.util.UndoUtils) LiveList(org.reactfx.collection.LiveList) CssMetaData(javafx.css.CssMetaData) Event(javafx.event.Event) Virtualized(org.fxmisc.flowless.Virtualized) List(java.util.List) BooleanProperty(javafx.beans.property.BooleanProperty) Region(javafx.scene.layout.Region) TwoLevelNavigator(org.fxmisc.richtext.model.TwoLevelNavigator) Subscription(org.reactfx.Subscription) Tuple2(org.reactfx.util.Tuple2) Paint(javafx.scene.paint.Paint) EventStreams(org.reactfx.EventStreams) Optional(java.util.Optional) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) Suspendable(org.reactfx.Suspendable) Styleable(javafx.css.Styleable) Bounds(javafx.geometry.Bounds) CornerRadii(javafx.scene.layout.CornerRadii) Val(org.reactfx.value.Val) BoundingBox(javafx.geometry.BoundingBox) MouseEvent(javafx.scene.input.MouseEvent) StyleSpans(org.fxmisc.richtext.model.StyleSpans) FXCollections(javafx.collections.FXCollections) Codec(org.fxmisc.richtext.model.Codec) DoubleProperty(javafx.beans.property.DoubleProperty) TextFlow(javafx.scene.text.TextFlow) Function(java.util.function.Function) MouseOverTextEvent(org.fxmisc.richtext.event.MouseOverTextEvent) ArrayList(java.util.ArrayList) IndexRange(javafx.scene.control.IndexRange) Paragraph(org.fxmisc.richtext.model.Paragraph) Insets(javafx.geometry.Insets) BackgroundFill(javafx.scene.layout.BackgroundFill) BiConsumer(java.util.function.BiConsumer) IntSupplier(java.util.function.IntSupplier) IntFunction(java.util.function.IntFunction) Color(javafx.scene.paint.Color) ObjectProperty(javafx.beans.property.ObjectProperty) ReadOnlyStyledDocument(org.fxmisc.richtext.model.ReadOnlyStyledDocument) Node(javafx.scene.Node) RichTextChange(org.fxmisc.richtext.model.RichTextChange) Replacement(org.fxmisc.richtext.model.Replacement) Tuples(org.reactfx.util.Tuples) Background(javafx.scene.layout.Background) Consumer(java.util.function.Consumer) StyledDocument(org.fxmisc.richtext.model.StyledDocument) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) StyleableObjectProperty(javafx.css.StyleableObjectProperty) VirtualizedScrollPane(org.fxmisc.flowless.VirtualizedScrollPane) StyledSegment(org.fxmisc.richtext.model.StyledSegment) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) SuspendableList(org.reactfx.collection.SuspendableList) ObservableValue(javafx.beans.value.ObservableValue) EditableStyledDocument(org.fxmisc.richtext.model.EditableStyledDocument) VirtualFlow(org.fxmisc.flowless.VirtualFlow) Var(org.reactfx.value.Var) EventStream(org.reactfx.EventStream) Collections(java.util.Collections) Val(org.reactfx.value.Val) SuspendableEventStream(org.reactfx.SuspendableEventStream) EventStream(org.reactfx.EventStream) Subscription(org.reactfx.Subscription) Cell(org.fxmisc.flowless.Cell)

Example 10 with Subscription

use of org.reactfx.Subscription in project RichTextFX by FXMisc.

the class SubscribeableContentsObsSetTest method adding_new_subscriber_when_list_has_contents_does_not_fire_invalidation_event.

@Test
public void adding_new_subscriber_when_list_has_contents_does_not_fire_invalidation_event() {
    SubscribeableContentsObsSet<Integer> contentSet = new SubscribeableContentsObsSet<>();
    contentSet.add(1);
    contentSet.add(2);
    contentSet.add(3);
    // when a change occurs add the additions/removals in another list
    SimpleBooleanProperty changeWasFired = new SimpleBooleanProperty(false);
    Subscription removeInvalidationListener = contentSet.addInvalidationListener(change -> changeWasFired.set(true));
    // when property is set to a new value, store the new value in storageList
    contentSet.addSubscriber(ignore -> Subscription.EMPTY);
    assertFalse(changeWasFired.get());
    // cleanup
    removeInvalidationListener.unsubscribe();
}
Also used : SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Subscription(org.reactfx.Subscription) Test(org.junit.Test)

Aggregations

Subscription (org.reactfx.Subscription)10 VirtualizedScrollPane (org.fxmisc.flowless.VirtualizedScrollPane)5 Scene (javafx.scene.Scene)4 Optional (java.util.Optional)3 SimpleBooleanProperty (javafx.beans.property.SimpleBooleanProperty)3 StackPane (javafx.scene.layout.StackPane)3 Test (org.junit.Test)3 Duration (java.time.Duration)2 ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2 CodeArea (org.fxmisc.richtext.CodeArea)2 StyleSpans (org.fxmisc.richtext.model.StyleSpans)2 BufferedReader (java.io.BufferedReader)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1 InputStreamReader (java.io.InputStreamReader)1 Collection (java.util.Collection)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 ExecutorService (java.util.concurrent.ExecutorService)1