Skip to content

Instantly share code, notes, and snippets.

@jewelsea
Created April 28, 2012 00:43
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save jewelsea/2514709 to your computer and use it in GitHub Desktop.
Save jewelsea/2514709 to your computer and use it in GitHub Desktop.
Customize the JavaFX HTMLEditor
import java.util.List;
import java.util.regex.Pattern;
import javafx.application.*;
import javafx.collections.FXCollections;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.web.HTMLEditor;
import javafx.stage.Stage;
public class HTMLEditorCustomizationSample extends Application {
// limits the fonts a user can select from in the html editor.
private static final List<String> limitedFonts = FXCollections.observableArrayList("Arial", "Times New Roman", "Courier New", "Comic Sans MS");
public static void main(String[] args) { launch(args); }
@Override public void start(Stage stage) {
// create a new html editor and show it before we start modifying it.
final HTMLEditor htmlEditor = new HTMLEditor();
stage.setScene(new Scene(htmlEditor));
stage.show();
// hide controls we don't need.
hideImageNodesMatching(htmlEditor, Pattern.compile(".*(Cut|Copy|Paste).*"), 0);
Node seperator = htmlEditor.lookup(".separator");
seperator.setVisible(false); seperator.setManaged(false);
// modify font selections.
int i = 0;
for (Node candidate: (htmlEditor.lookupAll("MenuButton"))) {
// fonts are selected by the second menu in the htmlEditor.
if (candidate instanceof MenuButton && i == 1) {
// limit the font selections to our predefined list.
MenuButton menuButton = (MenuButton) candidate;
List<MenuItem> removalList = FXCollections.observableArrayList();
final List<MenuItem> fontSelections = menuButton.getItems();
for (MenuItem item: fontSelections) {
if (!limitedFonts.contains(item.getText())) {
removalList.add(item);
}
}
fontSelections.removeAll(removalList);
// Select a font from out limited font selection.
// Selection done in Platform.runLater because if you try to do
// the selection immediately, it won't take place.
Platform.runLater(new Runnable() {
@Override public void run() {
boolean fontSelected = false;
for (final MenuItem item: fontSelections) {
if ("Comic Sans MS".equals(item.getText())) {
if (item instanceof RadioMenuItem) {
((RadioMenuItem) item).setSelected(true);
fontSelected = true;
}
}
}
if (!fontSelected && fontSelections.size() > 0 && fontSelections.get(0) instanceof RadioMenuItem) {
((RadioMenuItem) fontSelections.get(0)).setSelected(true);
}
}
});
}
i++;
}
// 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", 32, 32, 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>");
}
});
}
}
// hide buttons containing nodes whose image url matches a given name pattern.
public void hideImageNodesMatching(Node node, Pattern imageNamePattern, int depth) {
if (node instanceof ImageView) {
ImageView imageView = (ImageView) node;
String url = imageView.getImage().impl_getUrl();
if (url != null && imageNamePattern.matcher(url).matches()) {
Node button = imageView.getParent().getParent();
button.setVisible(false); button.setManaged(false);
}
}
if (node instanceof Parent)
for (Node child : ((Parent) node).getChildrenUnmodifiable())
hideImageNodesMatching(child, imageNamePattern, depth + 1);
}
}
@jewelsea
Copy link
Author

@jewelsea
Copy link
Author

https://forums.oracle.com/thread/2562169 "How to insert image into HTMLEditor content pane?"

@jewelsea
Copy link
Author

README The example makes use of internal introspection on the structure of the HTMLEditor which doesn't really form part of the JavaFX public API and may change between different JavaFX versions. For example, the hideImageNodesMatching method will not work out of the box in Java 8.

Copy link

ghost commented Jan 1, 2014

Hello Jewelsea, Thank you for all your efforts in answering questions on StockOverflow. May I request you to please address this:

http://stackoverflow.com/questions/20810995/how-to-get-the-ids-of-nodes-inside-htmleditor-javafx

From which reference did you get ".separator", "MenuButton", and ".top-toolbar" which you used in the lookup() method in your above code?

@jewelsea
Copy link
Author

jewelsea commented Jan 9, 2015

I determined the ids by running a recursive dump of all the nodes in the scene graph and printing out the style classes and ids of the nodes to System.out as part of the dump (see the dump(node) function in this DebugUtil class). Alternately SceneBuilder has a CSS analyzer, or ScenicView will show the CSS style classes and ids for nodes.

@alamenai
Copy link

Hi @jewelsea ,thank you for your gist ,it helped me for my project ,but i have a question we have two tool bars ,i need the name of class (css) of second bar ?

@TurekBot
Copy link

TurekBot commented Oct 11, 2017

@jewelsea, I'm so sad that this well-thought out example is broken!

I tried it and none of the Copy, Cut, Paste buttons disappear now.

Do we need to hide them by style class? Like "html-editor-copy"?

How can I help?

@purringpigeon
Copy link

Hello - I was hoping to use this example as well, and it does't seem to work with the Java8 version - any thoughts or updates to this code?

@jewelsea
Copy link
Author

This example was written a long time ago. From the comments it would seem that it no longer works with more recent JavaFX versions. If somebody would like to spend the effort to get it working or provide a similar example, they can fork the gist and add their modifications and place a link to the modified gist, noting what they did, in a comment here.

@segreeeen
Copy link

Did you by any chance encounter a rich text javafx component?

@jewelsea
Copy link
Author

jewelsea commented Nov 4, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment