2015-02-22 8 views
7

Sto lavorando con CodeArea RichTextFx per evidenziare codice mini lingua personalizzato.Mostra breakpoint al numero di riga in RichTextFx CodeArea

Ora mentre eseguo questo codice voglio mostrare una piccola freccia davanti alla linea attualmente in esecuzione. Conosco il numero di linea specifico ma non riesco a ottenere nulla con l'etichetta del numero di riga.

Poiché il progetto github afferma che i numeri di riga o i punti di interruzione del punto di interruzione come funzione non possono essere molto difficili. Ma non si può ottenere nulla per il lavoro ...

Grazie in anticipo

risposta

12

Per mostrare qualsiasi immagine davanti alla linea, è necessario impostare il "paragrafo grafica factory" del CodeArea. Questa fabbrica grafica è solo una funzione int -> Node: dato il numero di riga, restituisce un Node che verrà visualizzato davanti alla linea.

Ecco una fabbrica grafica che produce un triangolo verde che punta sulla linea. Verrà visualizzato solo quando la riga è uguale alla proprietà intera specificata 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; 
    } 
} 

Ogni grafica (ossia piccolo triangolo verde) si crea verrà osservando la data shownLine proprietà per decidere se deve essere visibile. Poiché le linee, e quindi la grafica di linea, vanno e vengono, è importante rimuovere l'ascoltatore di shownLine quando l'immagine non viene più utilizzata. visible.conditionOnShowing(t‌​riangle) è una nuova proprietà che smetterà di osservare la proprietà visible (e automaticamente anche la proprietà shownLine, grazie alla semantica lazy binding di ReactFX) e di ripristinare la costante false ogni volta che il triangolo non fa parte di una finestra di visualizzazione. Quindi non causiamo perdite di memoria o CPU a causa di ascoltatori non ripuliti.

Ecco una demo eseguibile completa che utilizza questo ArrowFactory combinato con lo LineNumberFactory fornito da RichTextFX per mostrare sia i numeri di riga che un piccolo triangolo. Questa demo utilizza la riga corrente CodeArea come proprietà shownLine. Dovresti sostituirlo con una proprietà che contiene la linea di esecuzione corrente.

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

E questo è il risultato:

CodeArea with current line indicator

+0

Credo che sarebbe più facile da capire usando Val.conditionOnShowing (Node): 'triangle.visibleProperty() bind (visible.conditionOnShowing (. triangolo)); 'o mi sono perso qualcosa di importante? – Adrodoc55

+0

Hai assolutamente ragione. L'unica ragione è che questa risposta precede l'esistenza di 'conditionOnShowing'. Aggiornerò la risposta Grazie! –