在 RichTextFx CodeArea 的行号处显示断点

Show breakpoint at line number in RichTextFx CodeArea

我正在使用 RichTextFx 的 CodeArea 来突出显示自定义迷你语言代码。

现在,在执行这段代码时,我想在当前执行的行前面显示一个小箭头。我知道具体的行号,但无法使用行号标签进行任何操作。

由于 github 项目声称将显示行号或断点切换作为一项功能,因此这不会很困难。但是什么都做不了...

提前致谢

要在行前显示任何图形,您需要设置代码区的"paragraph graphic factory"。这个图形工厂只是一个函数 int -> Node: 给定行号,它 returns 一个 Node 将显示在该行的前面。

这是一个图形工厂,它生成一个指向直线的绿色三角形。只有当行等于给定的整数时才会显示 属性 shownLine.

class ArrowFactory implements IntFunction<Node> {
    private final ObservableValue<Integer> shownLine;

    ArrowFactory(ObservableValue<Integer> shownLine) {
        this.shownLine = shownLine;
    }

    @Override
    public Node apply(int lineNumber) {
        Polygon triangle = new Polygon(0.0, 0.0, 10.0, 5.0, 0.0, 10.0);
        triangle.setFill(Color.GREEN);

        ObservableValue<Boolean> visible = Val.map(
                shownLine,
                sl -> sl == lineNumber);

        triangle.visibleProperty().bind(visible.conditionOnShowing(t‌​riangle));

        return triangle;
    }
}

您创建的每个图形(即绿色小三角形)都将观察给定的 shownLine 属性 来决定它是否应该可见。由于线条和线条图形来来去去,因此当图形不再使用时删除 shownLine 的侦听器很重要。 visible.conditionOnShowing(t‌​riangle) 是一个新的 属性,它将停止观察 visible 属性(并且自动地也停止观察 shownLine 属性,这要归功于 ReactFX 的惰性绑定语义) 并在三角形不属于显示 window 时重置为常量 false。所以我们不会由于未清理的侦听器而导致内存或 CPU 泄漏。

这是一个完整的可运行演示,它使用此 ArrowFactory 结合 RichTextFX 提供的 LineNumberFactory 来显示行号和一个小三角形。此演示使用 CodeArea 的当前行作为 shownLine 属性。您需要将其替换为包含当前执行行的 属性。

import java.util.function.IntFunction;

import javafx.application.Application;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;
import org.reactfx.value.Val;

public class CodeAreaWithLineIndicator extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        CodeArea codeArea = new CodeArea();

        IntFunction<Node> numberFactory = LineNumberFactory.get(codeArea);
        IntFunction<Node> arrowFactory = new ArrowFactory(codeArea.currentParagraphProperty());
        IntFunction<Node> graphicFactory = line -> {
            HBox hbox = new HBox(
                numberFactory.apply(line),
                arrowFactory.apply(line));
            hbox.setAlignment(Pos.CENTER_LEFT);
            return hbox;
        };
        codeArea.setParagraphGraphicFactory(graphicFactory);

        primaryStage.setScene(new Scene(new StackPane(codeArea), 600, 400));
        primaryStage.show();
    }
}

class ArrowFactory implements IntFunction<Node> {
    private final ObservableValue<Integer> shownLine;

    ArrowFactory(ObservableValue<Integer> shownLine) {
        this.shownLine = shownLine;
    }

    @Override
    public Node apply(int lineNumber) {
        Polygon triangle = new Polygon(0.0, 0.0, 10.0, 5.0, 0.0, 10.0);
        triangle.setFill(Color.GREEN);

        ObservableValue<Boolean> visible = Val.map(
                shownLine,
                sl -> sl == lineNumber);

        triangle.visibleProperty().bind(visible.conditionOnShowing(t‌​riangle));

        return triangle;
    }
}

这是结果: