How to Use ‘CardLayout’ like Panel with JRebirth StackModel

JRebirth Application Framework provides a custom ‘CardLayout’ as a JRebirth component by using its dedicated pattern wB-CSMvc.

The StackModel class will do the job (provided by artifact), you can find 2 usages here and here.

Each ‘card’ model can be called using a enum|modelKey identifier, and each stack has an unique name.

The first sample is used for the JRebirth Demo Application, it’s a pretty simple application that will allow to display other JRebirth showcase applications dynamically loaded as JRebirth module (from a separate and independent jar).

public final class JRebirthDemo extends DefaultApplication<StackPane> {

    public static void main(final String... args) {
        Application.launch(JRebirthDemo.class, args);

    public Class<? extends Model> firstModelClass() {
        return MainModel.class;

    protected String applicationTitle() {
        return "JRebirth Demo Application";

    protected void customizeScene(final Scene scene) {

        addCSS(scene, DemoStyles.DEFAULT);
        addCSS(scene, WorkbenchStyles.DEFAULT);

    protected void customizeStage(final Stage stage) {
        // Center the stage

    protected List<? extends ResourceItem<?, ?, ?>> getResourceToPreload() {
        return Collections.emptyList();

This application will load its first model (MainModel) and put its root node into the scene root node (StackPane, automatically built).The MainModel will list all application’s sub modules to add a button entries into its left menu, and a StackModel that will display each module content. The StackModel is loaded using special annotation using its unique String key.

public final class MainModel extends DefaultModel<MainModel, MainView> {

    private final List<ModuleModel> modules = new ArrayList<>();

    private StackModel stackModel;

    protected void initModel() {
        for (final ModuleModel mm : getModels(ModuleModel.class)) {

    protected void showView() {

    protected void hideView() {
        // Nothing to do yet

    List<ModuleModel> getModules() {
        return this.modules;

The MainView will be in charge to create the module menu:

public final class MainView extends DefaultView<MainModel, BorderPane, MainController> {

    private final List<Button> buttonList = new ArrayList<>();

    public MainView(final MainModel model) throws CoreException {

    protected void initView() {

        node().setPrefSize(800, 600);



    public void start() { ->;

    private Node createMenu() {
        final VBox box = new VBox();

        for (final ModuleModel mm : model().getModules()) {
            final Node n = createModuleButton(mm);
            VBox.setMargin(n, new Insets(4, 4, 4, 4));
        return box;

    private Node createModuleButton(final ModuleModel mm) {
        final Button b = new Button(mm.moduleName());
        b.setPrefSize(100, 50);
        return b;

And the MainController will load the Module content when any menu button is triggered:

public final class MainController extends DefaultController<MainModel, MainView> implements ActionAdapter {

    public MainController(final MainView view) throws CoreException {

    public void onButtonFired(final ActionEvent event) {
        final Button b = (Button) event.getSource();
        final UniqueKey<? extends Model> data = (UniqueKey<? extends Model>) b.getUserData();

                         WBuilder.waveData(StackWaves.PAGE_MODEL_KEY, data),
                         WBuilder.waveData(StackWaves.STACK_NAME, "DemoStack"));

The second example will load the StackModel as an innerComponent and each card will be identified by an enum entry (stored into FXMLPage), let’s see FXMLShowCaseModel :

final InnerComponent<StackModel> stack = CBuilder.innerComponent(StackModel.class, FXMLPage.class);
    this.stackModel = findInnerComponent(stack);

The enumeration that link enum entry with Model:

public enum FXMLPage implements PageEnum {


    public UniqueKey<? extends Model> getModelKey() {
        switch (this) {
            case ViewEmbeddedFxml:
                return Key.create(EmbeddedModel.class);
            case StandaloneFxml:
                return Key.create(StandaloneModel.class);
            case HybridFxml:
                return Key.create(HybridModel.class, FXMLModel.KEYPART_FXML_PREFIX + "");
            case IncludedFxml:
                return Key.create(IncludedModel.class, new LoremIpsum());


As the card list is known, toolbar item are statically created into FXMLShowCaseView and event handling is also staically defined into FXMLShowCaseController using another technique:

public final class FXMLShowCaseController extends DefaultController<FXMLShowCaseModel, FXMLShowCaseView> {

    private static final Logger LOGGER = LoggerFactory.getLogger(FXMLShowCaseController.class);

    public FXMLShowCaseController(final FXMLShowCaseView view) throws CoreException {

    protected void initEventAdapters() throws CoreException {

        // WaveData<Class<? extends PageEnum>> stackName = Builders.waveData(StackWaves.STACK_PAGES, FXMLShowCaseModel.STACK_PAGES);

        // Manage Ui Command Button
        linkWave(view().getShowIncluded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
                 WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.IncludedFxml));

        linkWave(view().getShowEmbedded(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
                 WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.ViewEmbeddedFxml));

        linkWave(view().getShowStandalone(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
                 WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.StandaloneFxml));

        linkWave(view().getShowHybrid(), ActionEvent.ACTION, StackWaves.SHOW_PAGE_ENUM,
                 WBuilder.waveData(StackWaves.PAGE_ENUM, FXMLPage.HybridFxml));


Here you have the final application that allows to open each module dependency into the Stack using a Toggle button


Leave a Reply