From f40d80bd13b20219ae5d0c45c4988b7270fb54ba Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 9 Jan 2017 19:08:09 -0800 Subject: [PATCH 1/2] Add API to force lines to be shown at specific positions --- .../fxmisc/richtext/GenericStyledArea.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java b/richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java index 47a6ffdd2..ef72be99c 100644 --- a/richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java +++ b/richtextfx/src/main/java/org/fxmisc/richtext/GenericStyledArea.java @@ -962,6 +962,38 @@ void show(double y) { virtualFlow.show(y); } + /** + * Shows the paragraph somewhere in the viewport. If the line is already visible, no noticeable change occurs. + * If line is above the current view, it appears at the top of the viewport. If the line is below the current + * view, it appears at the bottom of the viewport. + */ + public void showParagraphInViewport(int paragraphIndex) { + virtualFlow.show(paragraphIndex); + } + + /** + * Lays out the viewport so that the paragraph is the first line (top) displayed in the viewport. Note: if + * the given area does not have enough lines that follow the given line to span its entire height, the paragraph + * may not appear at the very top of the viewport. Instead, it may simply be shown in the viewport. For example, + * given an unwrapped area whose height could show 10 lines but whose content only has 3 lines, calling + * {@code showParagraphAtTop(3)} would be no different than {@code showParagraphAtTop(1)}. + */ + public void showParagraphAtTop(int paragraphIndex) { + virtualFlow.showAsFirst(paragraphIndex); + } + + /** + * Lays out the viewport so that the paragraph is the last line (bottom) displayed in the viewport. Note: if + * the given area does not have enough lines preceding the given line to span its entire height, the paragraph + * may not appear at the very bottom of the viewport. Instead, it may appear towards the bottom of the viewport + * with some extra space following it. For example, given an unwrapped area whose height could show 10 lines but + * whose content only has 7 lines, calling {@code showParagraphAtBottom(1)} would be no different than calling + * {@code showParagraphAtBottom(7)}. + */ + public void showParagraphAtBottom(int paragraphIndex) { + virtualFlow.showAsLast(paragraphIndex); + } + void showCaretAtBottom() { int parIdx = getCurrentParagraph(); Cell, ParagraphBox> cell = virtualFlow.getCell(parIdx); From c223a2d6f04579c148e3a4b9013bd80120172c8a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Mon, 9 Jan 2017 19:09:01 -0800 Subject: [PATCH 2/2] Add demo for`show()` related methods --- .../fxmisc/richtext/demo/ShowLineDemo.java | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java new file mode 100644 index 000000000..f22480a89 --- /dev/null +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java @@ -0,0 +1,100 @@ +package org.fxmisc.richtext.demo; + +import javafx.application.Application; +import javafx.event.ActionEvent; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; +import org.fxmisc.flowless.VirtualizedScrollPane; +import org.fxmisc.richtext.InlineCssTextArea; + +import java.util.function.Consumer; +import java.util.function.Function; + +public class ShowLineDemo extends Application { + + public static final int MIN_LINE_INDEX = 0; + + private class NumbersOnlyField extends TextField { + + NumbersOnlyField() { + super(); + setOnKeyTyped(ke -> { + String keyEventText = ke.getCharacter(); + if (Character.isDigit(keyEventText.charAt(0))) { + if (getSelectedText().isEmpty()) { + appendText(keyEventText); + } else { + replaceText(getSelection(), keyEventText); + } + } + ke.consume(); + }); + } + + public int getTextAsInt() { + String text = getText(); + if (text.isEmpty()) { + setText(String.valueOf(MIN_LINE_INDEX)); + return MIN_LINE_INDEX; + } else { + return Integer.parseInt(text); + } + } + + } + + private final NumbersOnlyField field = new NumbersOnlyField(); + { + field.setPromptText("Input a number to indicate which line you want to show"); + } + + @Override + public void start(Stage primaryStage) throws Exception { + StringBuilder sb = new StringBuilder(); + int max = 100; + for (int i = 0; i < max; i++) { + sb.append("Line Index: ").append(i).append("\n"); + } + sb.append("Line Index: ").append(max); + InlineCssTextArea area = new InlineCssTextArea(sb.toString()); + VirtualizedScrollPane vsPane = new VirtualizedScrollPane<>(area); + + Function clamp = i -> Math.max(0, Math.min(i, area.getLength() - 1)); + Button showInViewportButton = createButton("Show line somewhere in Viewport", ae -> { + area.showParagraphInViewport(clamp.apply(field.getTextAsInt())); + }); + Button showAtViewportTopButton = createButton("Show line at top of viewport", ae -> { + area.showParagraphAtTop(clamp.apply(field.getTextAsInt())); + }); + Button showAtViewportBottomButton = createButton("Show line at bottom of viewport", ae -> { + area.showParagraphAtBottom(clamp.apply(field.getTextAsInt())); + }); + + VBox vbox = new VBox(field, showInViewportButton, showAtViewportTopButton, showAtViewportBottomButton); + vbox.setAlignment(Pos.CENTER); + + BorderPane root = new BorderPane(); + root.setCenter(vsPane); + root.setBottom(vbox); + + Scene scene = new Scene(root, 700, 500); + primaryStage.setScene(scene); + primaryStage.show(); + + } + + private Button createButton(String text, Consumer handler) { + Button b = new Button(text); + b.setOnAction(ae -> { + handler.accept(ae); + field.requestFocus(); + }); + return b; + } + +}