public void createNodes(Graph graph, double[][] coordinates) { nodeArray = new ArrayList<>(); double radius = graph.getNumberOfNodes() < 25 ? 100 / graph.getNumberOfNodes() : 4; for (int i = 0; i < coordinates.length; i++) { Circle nodeI = new Circle(radius); nodeI.setTranslateX(coordinates[i][0]); nodeI.setTranslateY(coordinates[i][1]); Tooltip tip = new Tooltip("node number " + (i + 1) + ", \"" + root.sequence.getText().charAt(i) + "\""); Tooltip.install(nodeI, tip); nodeI.setId(root.sequence.getText().substring(i, i + 1)); Timeline timeline = new Timeline(); nodeI.setOnMouseDragged( event -> { nodeI.setTranslateX(event.getSceneX() - root.nodes.getLayoutX()); nodeI.setTranslateY(event.getSceneY() - root.nodes.getLayoutY()); }); final int finalI = i; nodeI.setOnMouseReleased( event -> { double[][] newCoordinates = SpringEmbedder.computeSpringEmbedding( 100, graph.getNumberOfNodes(), graph.getEdges(), null); SpringEmbedder.centerCoordinates( newCoordinates, 0, (int) root.getWidth(), 20, (int) (root.getHeight() - root.vbox.getHeight() * 1.5)); timeline .getKeyFrames() .add( new KeyFrame( Duration.millis(200), new KeyValue(nodeI.translateXProperty(), coordinates[finalI][0]))); timeline .getKeyFrames() .add( new KeyFrame( Duration.millis(200), new KeyValue(nodeI.translateYProperty(), coordinates[finalI][1]))); timeline.play(); }); nodeI.disableProperty().bind(Bindings.not(root.animate.selectedProperty())); root.nodes.getChildren().add(nodeI); nodeArray.add(nodeI); } }
@Override public void start(Stage primaryStage) { CheckBox wrapToggle = new CheckBox("Wrap"); wrapToggle.setSelected(true); area.wrapTextProperty().bind(wrapToggle.selectedProperty()); Button undoBtn = createButton("undo", () -> area.undo()); Button redoBtn = createButton("redo", () -> area.redo()); Button cutBtn = createButton("cut", () -> area.cut()); Button copyBtn = createButton("copy", () -> area.copy()); Button pasteBtn = createButton("paste", () -> area.paste()); Button boldBtn = createButton("bold", () -> toggleBold()); Button italicBtn = createButton("italic", () -> toggleItalic()); Button underlineBtn = createButton("underline", () -> toggleUnderline()); Button strikeBtn = createButton("strikethrough", () -> toggleStrikethrough()); ComboBox<Integer> sizeCombo = new ComboBox<>( FXCollections.observableArrayList( 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 28, 32, 36, 40, 48, 56, 64, 72)); sizeCombo.getSelectionModel().select(Integer.valueOf(12)); ComboBox<String> familyCombo = new ComboBox<>(FXCollections.observableList(Font.getFamilies())); familyCombo.getSelectionModel().select("Serif"); ColorPicker textColorPicker = new ColorPicker(Color.BLACK); ColorPicker backgroundColorPicker = new ColorPicker(); sizeCombo.setOnAction(evt -> updateFontSize(sizeCombo.getValue())); familyCombo.setOnAction(evt -> updateFontFamily(familyCombo.getValue())); textColorPicker.valueProperty().addListener((o, old, color) -> updateTextColor(color)); backgroundColorPicker .valueProperty() .addListener((o, old, color) -> updateBackgroundColor(color)); undoBtn.disableProperty().bind(Bindings.not(area.undoAvailableProperty())); redoBtn.disableProperty().bind(Bindings.not(area.redoAvailableProperty())); BooleanBinding selectionEmpty = new BooleanBinding() { { bind(area.selectionProperty()); } @Override protected boolean computeValue() { return area.getSelection().getLength() == 0; } }; cutBtn.disableProperty().bind(selectionEmpty); copyBtn.disableProperty().bind(selectionEmpty); area.beingUpdatedProperty() .addListener( (o, old, beingUpdated) -> { if (!beingUpdated) { boolean bold, italic, underline, strike; Integer fontSize; String fontFamily; Color textColor; Color backgroundColor; IndexRange selection = area.getSelection(); if (selection.getLength() != 0) { StyleSpans<StyleInfo> styles = area.getStyleSpans(selection); bold = styles.styleStream().anyMatch(s -> s.bold.orElse(false)); italic = styles.styleStream().anyMatch(s -> s.italic.orElse(false)); underline = styles.styleStream().anyMatch(s -> s.underline.orElse(false)); strike = styles.styleStream().anyMatch(s -> s.strikethrough.orElse(false)); int[] sizes = styles .styleStream() .mapToInt(s -> s.fontSize.orElse(-1)) .distinct() .toArray(); fontSize = sizes.length == 1 ? sizes[0] : -1; String[] families = styles .styleStream() .map(s -> s.fontFamily.orElse(null)) .distinct() .toArray(i -> new String[i]); fontFamily = families.length == 1 ? families[0] : null; Color[] colors = styles .styleStream() .map(s -> s.textColor.orElse(null)) .distinct() .toArray(i -> new Color[i]); textColor = colors.length == 1 ? colors[0] : null; Color[] backgrounds = styles .styleStream() .map(s -> s.backgroundColor.orElse(null)) .distinct() .toArray(i -> new Color[i]); backgroundColor = backgrounds.length == 1 ? backgrounds[0] : null; } else { int p = area.getCurrentParagraph(); int col = area.getCaretColumn(); StyleInfo style = area.getStyleAtPosition(p, col); bold = style.bold.orElse(false); italic = style.italic.orElse(false); underline = style.underline.orElse(false); strike = style.strikethrough.orElse(false); fontSize = style.fontSize.orElse(-1); fontFamily = style.fontFamily.orElse(null); textColor = style.textColor.orElse(null); backgroundColor = style.backgroundColor.orElse(null); } updatingToolbar.suspendWhile( () -> { if (bold) { if (!boldBtn.getStyleClass().contains("pressed")) { boldBtn.getStyleClass().add("pressed"); } } else { boldBtn.getStyleClass().remove("pressed"); } if (italic) { if (!italicBtn.getStyleClass().contains("pressed")) { italicBtn.getStyleClass().add("pressed"); } } else { italicBtn.getStyleClass().remove("pressed"); } if (underline) { if (!underlineBtn.getStyleClass().contains("pressed")) { underlineBtn.getStyleClass().add("pressed"); } } else { underlineBtn.getStyleClass().remove("pressed"); } if (strike) { if (!strikeBtn.getStyleClass().contains("pressed")) { strikeBtn.getStyleClass().add("pressed"); } } else { strikeBtn.getStyleClass().remove("pressed"); } if (fontSize != -1) { sizeCombo.getSelectionModel().select(fontSize); } else { sizeCombo.getSelectionModel().clearSelection(); } if (fontFamily != null) { familyCombo.getSelectionModel().select(fontFamily); } else { familyCombo.getSelectionModel().clearSelection(); } if (textColor != null) { textColorPicker.setValue(textColor); } backgroundColorPicker.setValue(backgroundColor); }); } }); HBox panel1 = new HBox(3.0); HBox panel2 = new HBox(3.0); panel1 .getChildren() .addAll( wrapToggle, undoBtn, redoBtn, cutBtn, copyBtn, pasteBtn, boldBtn, italicBtn, underlineBtn, strikeBtn); panel2.getChildren().addAll(sizeCombo, familyCombo, textColorPicker, backgroundColorPicker); VBox vbox = new VBox(); VBox.setVgrow(area, Priority.ALWAYS); vbox.getChildren().addAll(panel1, panel2, area); Scene scene = new Scene(vbox, 600, 400); scene.getStylesheets().add(RichText.class.getResource("rich-text.css").toExternalForm()); primaryStage.setScene(scene); area.requestFocus(); primaryStage.setTitle("Rich Text Demo"); primaryStage.show(); }