2015-02-22 19 views
7

Ich arbeite mit CodeArea RichTextFx, um benutzerdefinierte Mini-Sprachcode hervorzuheben.Zeige Breakpoint bei Zeilennummer in RichTextFx CodeArea

Jetzt, während ich diesen Code ausführe, möchte ich einen kleinen Pfeil vor der aktuell ausgeführten Zeile zeigen. Ich kenne die spezifische Zeilennummer, kann aber mit dem Zeilennummern-Label nichts erreichen.

Da github Projektansprüche Zeilennummern oder Breakpoint-Toggel als Feature anzeigen, kann dies nicht sehr schwierig sein. Aber kann nichts an der Arbeit ...

Vielen Dank im Voraus

Antwort

12

jede Grafik Um zu zeigen, vor der Linie, müssen Sie die „Absatz grafische Fabrik“, um des CodeArea. Diese Grafik-Factory ist nur eine Funktion int -> Node: angesichts der Zeilennummer, gibt es eine Node, die vor der Zeile angezeigt wird.

Hier ist eine grafische Fabrik, die ein grünes Dreieck zeigt, das auf die Linie zeigt. Es wird nur angezeigt, wenn die Zeile gleich der angegebenen Ganzzahleigenschaft shownLine ist.

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; 
    } 
} 

Jede Grafik (das heißt kleine grüne Dreieck) Sie erstellen, wird die gegebene shownLine Eigenschaft werden zu beobachten, um zu entscheiden, ob sie sichtbar sein sollen. Da Linien und somit Liniengrafiken kommen und gehen, ist es wichtig, den Listener von shownLine zu entfernen, wenn die Grafik nicht mehr verwendet wird. visible.conditionOnShowing(t‌​riangle) ist eine neue Eigenschaft, die die visible-Eigenschaft (und automatisch auch die shownLine -Eigenschaft, dank ReactFX Lazy Binding Semantik) zu beobachten und auf false immer dann zurückgesetzt wird, wenn das Dreieck nicht Teil eines angezeigten Fensters ist. Wir verursachen also keine Speicher- oder CPU-Lecks aufgrund unsauberer Zuhörer.

Hier ist eine vollständige runnable Demo, die diese ArrowFactory kombiniert mit der LineNumberFactory von RichTextFX verwendet, um beide Zeilennummern und ein kleines Dreieck anzuzeigen. In dieser Demo wird die aktuelle Zeile der CodeArea als shownLine-Eigenschaft verwendet. Sie möchten es durch eine Eigenschaft ersetzen, die die aktuelle Ausführungszeile enthält.

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; 
    } 
} 

Und das ist das Ergebnis:

CodeArea with current line indicator

+0

Ich denke, es wäre einfacher, Val.conditionOnShowing (Knoten) zu verstehen, mit: 'triangle.visibleProperty() binden (visible.conditionOnShowing (. Dreieck)); 'oder habe ich etwas Wichtiges vermisst? – Adrodoc55

+0

Sie haben absolut Recht. Der einzige Grund ist, dass diese Antwort der Existenz von "conditionOnShowing" vorausgeht. Ich werde die Antwort aktualisieren. Vielen Dank! –