-
Notifications
You must be signed in to change notification settings - Fork 9
Previews
NOTE! You may need a basic knowledge of JavaFX to fully understand this guide.
Creating custom previews from JavaScript is pretty easy. A preview menu can be simply instantiated by calling the constructor new PreviewMenu(title, image, controls, initFlow, flowsAmount)
-
title
is a string representing the title on the top of the menu -
image
represents the background of the preview. It can be either a relative string path or aFile
instance -
controls
is an array of JavaFX text controls, such as text fields, text areas, spinners, etc -
initFlow
is afunction(flow, index)
called every time the preview needs to be updated -
flowsAmount
defines the initial amount of text flows. If not specified, it will be equals to the amount of controls.
Example:
const textfield1 = new TextField(); // javafx.scene.control.TextField
const textfield2 = new TextField();
const previewMenu = new PreviewMenu('My preview', 'image.jpg', [textfield1, textfield2], (flow, index) => {
// ...
}, 2 /* in this case, this could be omitted */);
previewMenu.show();
Now we can work on the initFlow
function. The first parameter, flow
, is an instance of a JavaFX TextFlow
, which can be considered as a succession of Text
s.
(flow, index) => {
flow.setTextAlignment(TextAlignment.CENTER); // We center the flow
flow.setLayoutY(50 + index * 30); // We set the Y coordinate to 50 plus 30 for each index value
}
We are almost done but, if you type anything, the preview won't update. It's because we haven't set bindings.
PreviewMenu#bind
has two overload functions:
-
bind(property, index)
- Takes a JavaFX property (i.etextfield.textProperty()
) and flow index -
bind(control, index)
- Takes a JavaFX text control and flow index. Calls the previous method withcontrol.textProperty()
parameter
For more complex bindings, check the listen(property, action)
top-level function (see here).
const textfield1 = new TextField();
const textfield2 = new TextField();
const previewMenu = new PreviewMenu('My preview', 'image.jpg', [textfield1, textfield2], (flow, index) => {
flow.setTextAlignment(TextAlignment.CENTER);
flow.setLayoutY(50 + index * 30);
});
previewMenu.bind(textfield1, 0);
previewMenu.bind(textfield2, 1);
previewMenu.show();
Finally, let the user open the preview from a drop-menu button:
function onDropMenuOpen(type, menu) {
if (type == 'previews') {
menu.addButton('My preview', (area, x, y) => {
const textfield1 = new TextField();
const textfield2 = new TextField();
const previewMenu = new PreviewMenu('My preview', 'image.jpg', [textfield1, textfield2], (flow, index) => {
flow.setTextAlignment(TextAlignment.CENTER);
flow.setLayoutY(50 + index * 30);
}, 2);
previewMenu.bind(textfield1, 0);
previewMenu.bind(textfield2, 1)
previewMenu.setLayoutX(x);
previewMenu.setLayoutY(y);
previewMenu.show();
})
}
}
You may want to automatically insert selected text into one of the text fields.
Just set the value of the text field to getSelectedText()
inside of a runLater
block:
runLater(() => {
textfield1.setText(getSelectedText());
})
NOTE! getSelectedText()
is a built-in function that gets text inside selection (if there is one). Otherwhise, it will return the string value hovered by the caret. Otherwhise, an empty string.
Let's play with text flows:
(flow, index) => {
flow.setTextAlignment(TextAlignment.CENTER);
flow.setLayoutY(previewMenu.getImage().getBackground().getHeight() / 2 + 25 * (index - 1))
flow.getStyleClass().add('my-text-flow');
flow.getStyleClass().add('my-text-flow-' + index);
}
Remember to load stylesheets if needed:
.my-text-flow .label {
-fx-font-family: "Minecraft";
-fx-font-size: 25;
}
.my-text-flow-0 {
-fx-effect: dropshadow(gaussian, red, 10, 0, 0, 0);
}
.my-text-flow-1 {
-fx-effect: dropshadow(gaussian, green, 10, 0, 0, 0);
}
IMPORTANT! For text areas that generate a flow for each line, take a look at generateFlowList(textArea, menu)
which returns a list of TextFlow
s.