Here is how I solved my problem using Pebble. The following example served me as a proof of concept before using Pebble in my real project. I kept it very simple but it did the job of proving what I wanted to achieve was possible.
Layout.pebble.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<BorderPane id="page" prefWidth="1280.0" prefHeight="900.0" xmlns:fx="http://javafx.com/fxml">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#exitAction" text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
{% block body %}{% endblock %}
</center>
</BorderPane>
Index.pebble.fxml:
{% extends "templates/Layout.pebble.fxml" %}
{% block body %}
<VBox xmlns:fx="http://javafx.com/fxml/1">
<Text text="Test" />
</VBox>
{% endblock %}
App.java:
package be.dupirefr.pebblefx;
import java.io.File;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
import be.dupirefr.pebblefx.controllers.DumbController;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class App extends Application {
public static void main(String args[]) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
PebbleEngine engine = new PebbleEngine.Builder().build();
PebbleTemplate compiledTemplate = engine.getTemplate("templates/Index.pebble.fxml");
Map<String, Object> context = new HashMap<>();
File file = File.createTempFile("views/Index", "fxml");
file.deleteOnExit();
PrintWriter writer = new PrintWriter(file);
compiledTemplate.evaluate(writer, context);
writer.close();
primaryStage.setTitle("Pebble test");
FXMLLoader loader = new FXMLLoader();
loader.setController(new DumbController());
loader.setLocation(file.toURI().toURL());
BorderPane pane = loader.load();
Scene scene = new Scene(pane);
primaryStage.setScene(scene);
primaryStage.show();
}
}
The process generated this file :
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<BorderPane id="page" prefWidth="1280.0" prefHeight="900.0"
xmlns:fx="http://javafx.com/fxml">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" onAction="#exitAction"
text="Exit" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<VBox xmlns:fx="http://javafx.com/fxml/1">
<Text text="Test" />
</VBox>
</center>
</BorderPane>
And it is successfully used by the FXMLLoader.
Of course you can use other features of Pebble, but what I wanted to see was if it was going to work with any kind of file and if the FXMLLoader will take the temporary file as input.