4

actually i'm looking for something very similar to this thread:

How to hide the controls of HTMLEditor?

so basically i try to add a custom button to the javafx html editor but with the difference that it's implemented through FXML.

So my question is:

Is there a "work-around" to add custom buttons to the html-editor when it's implemented through FXML?

Community
  • 1
  • 1
fraggle
  • 51
  • 1
  • 4

3 Answers3

4

Sample solution is :

htmlEditor.setVisible(false);
    Platform.runLater(new Runnable() {

        @Override
        public void run() {
            Node[] nodes = htmlEditor.lookupAll(".tool-bar").toArray(new Node[0]);
            for (Node node : nodes) {
                node.setVisible(false);
                node.setManaged(false);
            }
            htmlEditor.setVisible(true);
        }

    });
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194
hkg
  • 41
  • 1
  • Felilpe, I cannot believe that your solution is not the top rated solution. I added your code to my Controllers initialize method, and it worked PERFECTLY (Java 8) - THANK YOU!!!! – Michael Sims Mar 12 '18 at 09:48
3

I have modified the @jewelsea answer for javaFX9.

I have also added some customization to move toolbars. The main idea is to get all the components by css selector, then modify or hide them. Read the class HTMLEditorSkin to get the CSS classes names, like ".html-editor-align-center" for the align button.

import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.RadioMenuItem;
import javafx.scene.control.ToolBar;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;

public class HTMLEditorCustomizationSample2 extends Application {
    // limits the fonts a user can select from in the html editor.
    private static final ObservableList<String> limitedFonts = FXCollections.observableArrayList("Arial",
            "Times New Roman", "Courier New", "Comic Sans MS");
    private HTMLEditor htmlEditor;

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

    @SuppressWarnings("unchecked")
    @Override
    public void start(Stage stage) {
        htmlEditor = new HTMLEditor();
        stage.setScene(new Scene(htmlEditor));
        stage.show();

        customizeEditor(htmlEditor);

    }

    private void customizeEditor(HTMLEditor htmlEditor) {
        // hide controls we don't need.
        Node seperator = htmlEditor.lookup(".separator");
        seperator.setVisible(false);
        seperator.setManaged(false);
        hideByClass(htmlEditor, ".separator");
        hideByClass(htmlEditor, ".html-editor-cut", ".html-editor-copy", ".html-editor-paste", ".html-editor-strike",
                ".html-editor-hr");
        hideByClass(htmlEditor, ".html-editor-align-left"
                , ".html-editor-align-center"
                , ".html-editor-align-right"
                , ".html-editor-align-justify", ".html-editor-outdent"
                , ".html-editor-indent", ".html-editor-bullets"
                , ".html-editor-numbers");
        // Move the toolbars
        Node top= htmlEditor.lookup(".top-toolbar");
        GridPane.setConstraints(top,1,0,1,1);
        Node bottom= htmlEditor.lookup(".bottom-toolbar");
        GridPane.setConstraints(bottom,0,0,1,1);
        Node web= htmlEditor.lookup("WebView");
        GridPane.setConstraints(web,0,1,2,1); 

        // modify font selections.
        int i = 0;
        Set<Node> fonts = htmlEditor.lookupAll(".font-menu-button");
        Iterator<Node> fontsIterator = fonts.iterator();
        fontsIterator.next();
        ComboBox<String> formatComboBox = (ComboBox<String>) fontsIterator.next();

        formatComboBox.itemsProperty().addListener((obs, old, value) -> {
            if (value.size() != limitedFonts.size()) {// should loop on array for equality
                Platform.runLater(() -> {
                    value.clear();
                    // stop.set(true);
                    value.addAll(limitedFonts);
                    formatComboBox.setValue(limitedFonts.get(0));
                });

            }
        });

        // add a custom button to the top toolbar.
        Node node = htmlEditor.lookup(".top-toolbar");
        if (node instanceof ToolBar) {
            ToolBar bar = (ToolBar) node;
            ImageView graphic = new ImageView(
                    new Image("http://bluebuddies.com/gallery/title/jpg/Smurf_Fun_100x100.jpg", 16  , 16, true, true));
            graphic.setEffect(new DropShadow());
            Button smurfButton = new Button("", graphic);
            bar.getItems().add(smurfButton);
            smurfButton.setOnAction(new EventHandler<ActionEvent>() {
                @Override
                public void handle(ActionEvent arg0) {
                    htmlEditor.setHtmlText("<font face='Comic Sans MS' color='blue'>Smurfs are having fun :-)</font>");
                }
            });
        }
    }

    private void hideByClass(HTMLEditor htmlEditor, String... selectors) {
        for (String selector : selectors) {
            Set<Node> nodes = htmlEditor.lookupAll(selector);
            for (Node node : nodes) {
                node.setVisible(false);
                node.setManaged(false);
            }
        }
    }



    @Override
    public void stop() throws Exception {

        super.stop();
        System.out.println(htmlEditor.getHtmlText());
    }

}
pdem
  • 3,880
  • 1
  • 24
  • 38
  • I have tried to get this working on java 8, but have had some issues with most of the code not working. Are there any aspects of this approach that are java 9 specific? – Tag Howard Jun 01 '20 at 22:29
  • @TagHoward Yes, there is a big gap between java8 and java9. Jewelsea solution will work in java 8, but I encourage you to use Java11, at least, as it is the current supported version. – pdem Jun 03 '20 at 10:17
  • yes, I have since switched I was waiting on a dependency to update, thanks! – Tag Howard Jun 03 '20 at 14:03
2

Here is some sample code which customizes the HTMLEditor and adds a custom button to it. The sample code does not use fxml but really it's very similar if fxml is used. You could define the HTMLEditor in fxml and inject it into your Controller using the standard @FXML annotation. Once you have a reference to the editor, customize it in Java code using an appropriate variation of the sample code. For the added button, just create it in Java rather than fxml and it will be simpler.

jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Thank you, now i got the clue! :) – fraggle Nov 22 '12 at 17:22
  • That brings me to another question in connection with that - is it possible to add another toolbar beneath the top-toolbar and bottom-toolbar? – fraggle Nov 22 '12 at 18:21
  • I've made it works for javaFX9, see my answer, if you want to update your gist. thank you for that idea that helps me much, especially for fonts. – pdem Jan 25 '18 at 09:13