# WorkbenchFX
**Repository Path**: mirrors_dlsc-software-consulting-gmbh/WorkbenchFX
## Basic Information
- **Project Name**: WorkbenchFX
- **Description**: A lightweight RCP framework for JavaFX applications.
- **Primary Language**: Unknown
- **License**: Apache-2.0
- **Default Branch**: master-11
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-01-06
- **Last Updated**: 2025-09-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[](https://www.jfx-central.com/libraries/workbenchfx)
# WorkbenchFX
[](https://codecov.io/gh/dlsc-software-consulting-gmbh/WorkbenchFX)
[](https://search.maven.org/search?q=g:%22com.dlsc.workbenchfx%22%20AND%20a:%22workbenchfx-core%22)
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fdlsc-software-consulting-gmbh%2FWorkbenchFX?ref=badge_shield)
**The one and only framework to build large JavaFX Applications!**

## Maven
To use this framework as part of your Maven build simply add the following dependency to your pom.xml file:
### Java 8
```XML
com.dlsc.workbenchfxworkbenchfx-core8.1.0
```
### Java 11
```XML
com.dlsc.workbenchfxworkbenchfx-core11.1.0
```
## Gradle
To use this framework as part of your gradle build simply add the following to your build.gradle file and use the following dependency definition:
### Java 8
```groovy
dependencies {
compile group: 'com.dlsc.workbenchfx', name: 'workbenchfx-core', version: '8.1.0'
}
```
### Java 11
```groovy
dependencies {
compile group: 'com.dlsc.workbenchfx', name: 'workbenchfx-core', version: '11.1.0'
}
```
# Table of Contents
- [What is WorkbenchFX?](#what-is-workbenchfx)
- [Advantages](#advantages)
- [Main Components](#main-components)
- [Documentation](#documentation)
- [Basic Structure](#basic-structure)
- [Workbench Concept](#workbench-concept)
- [Module Lifecycle](#module-lifecycle)
- [Demos](#demos)
- [Getting Started](#getting-started)
- [Extending the WorkbenchModule](#extending-the-workbenchmodule)
- [Creating the Workbench](#creating-the-workbench)
- [Optional Methods](#optional-methods)
- [WorkbenchBuilder](#workbenchbuilder)
- [Workbench](#workbench)
- [WorkbenchModule](#workbenchmodule)
- [Using the Components](#using-the-components)
- [ToolbarItem](#toolbaritem)
- [Dialog](#dialog)
- [Predefined Dialog Types](#predefined-dialog-types)
- [Custom Dialog](#custom-dialog)
- [Prevent module from closing](#prevent-module-from-closing)
- [Drawer](#drawer)
- [Custom Overlay](#custom-overlay)
- [Restyling](#restyling)
- [Basic Styling](#basic-styling)
- [Changing Colors](#changing-colors)
- [Setting a Logo](#setting-a-logo)
- [Advanced Styling](#advanced-styling)
- [Team](#team)
# What is WorkbenchFX?
WorkbenchFX is an out of the box solution to build large applications from multiple views, called modules.
It offers you good user experience and a beautiful design.
As a developer, you often start with the views, so you can quickly show your progress to your customer.
After that, some question may arise such as:
- "How do I bring all those views together?"
- "How do I build the navigation between those views?"
- "How do I establish a good user experience?"
Exactly when those questions appear, *WorkbenchFX* comes into play:
With *WorkbenchFX* you can focus on designing your views and meanwhile we're building the application around them.
*WorkbenchFX* also scales with growing requirements.
In the beginning you just want to navigate through the views, but later on you probably would want to use a menu or a toolbar.
Even that is supported by *WorkbenchFX* and you don't have to build anything by yourself.
If you still manage to start outgrowing the workbench, you can even replace whole parts of it with your own implementations, without having to rewrite the whole workbench.
# Advantages
- Less error-prone
- Less code needed
- Easy to learn
- Easy to understand
- Easy to use, especially for developers which have not much experience in working with JavaFX
- A well designed, adaptable UI, inspired by the material design standards
- Multiple, independent *workbench modules*, displayed in Tabs combine into one great application
- The `jdk8` branch works well with [JPRO](https://www.jpro.one/)
- FXML & [Scene Builder](https://gluonhq.com/products/scene-builder/) support
# Main Components
The most important components are noted in the picture and the corresponding table below:

Nr. | Component | Description
--- | ------------------- | -----------
_ | `WorkbenchModule` | A `Workbench` consists of multiple modules. It contains a title, an icon and the content to be displayed in it. It represents the *views* mentioned in chapter [What is WorkbenchFX?](#what-is-workbenchfx)
2 | `Tile` | For each `WorkbenchModule` a `Tile` will be created. Clicking on the `Tile` opens the corresponding module
3 | `Tab` | A `Tab` will be displayed for each open module. Clicking on a `Tab` opens and shows the view of the corresponding module. Pressing the *'x'* button closes the module
4 | Tab bar | The upper section of the window, where the `Tab`s of the current open modules are displayed
5 | Add button | The button used to open a new module. It opens an overview of all available modules
6 | `AddModulePage` | Stores all the `Page`s on which the `Tile`s are displayed
7 | `Page` | When more modules are loaded than defined in the `modulesPerPage()` attribute, the `Workbench` creates multiple `Page`s on which the `Tile`s are displayed
8 | Pagination dots | Are only displayed when having multiple `Page`s and can be used for navigating through them
9 | Toolbar | It contains `ToolbarItem`s. If the bar does not contain any items, the *toolbar* will be hidden automatically
10 | `ToolbarItem` | Depending on the defined attributes, the item behaves like a JavaFX `Label`, `Button` or `MenuButton` (more about `ToolbarItem`s: [ToolbarItem](#toolbaritem))
11 | Menu button | It opens the `NavigationDrawer`. The position of the button varies depending on the amount of items to be displayed in the *toolbar* and the `NavigationDrawer`. If the `NavigationDrawer` does not contain any items, the button will not be displayed at all. If any items are in the *toolbar*, it will be displayed on the left side of the *toolbar*, otherwise on the left side of the *tab bar*

Nr. | Component | Description
--- | ------------------- | -----------
12 | `NavigationDrawer` | It displays a *logo* which can be set in the stylesheet (described in chapter [Setting a Logo](#setting-a-logo)) and the defined `MenuItem`s. The default hover behavior over its items can be changed using the method call `navigationDrawer.setMenuHoverBehavior()`. It can be closed by clicking on the `GlassPane` or by pressing the back arrow button
13 | `GlassPane` | The `GlassPane` prevents click events on the components below and adds a scrim to the background. Unless a blocking (modal) overlay is being displayed, clicking on the `GlassPane` closes the overlay (more about the *blocking* attribute: [Custom Overlay](#custom-overlay), [Custom Dialog](#custom-dialog))

Nr. | Component | Description
--- | ------------------- | -----------
14 | `Drawer` | It is possible to use `workbench.showDrawer()` to show drawers with custom content. All four sides of the window are supported (more about `Drawer`s: [Drawer](#drawer))

Nr. | Component | Description
--- | ------------------- | -----------
15 | `DialogControl` | Dialogs can be shown using a variety of predefined dialog types like `showInformationDialog()`, `showErrorDialog`, etc. Calling `workbench.showDialog(WorkbenchDialog)` shows a custom dialog (more about dialogs: [Dialog](#dialog))

Nr. | Component | Description
--- | ------------------- | -----------
16 | `Module toolbar` | Displays the module's toolbar items ([Workbench Module](#workbenchmodule)). The toolbar will automatically be shown as soon as there are items to be displayed and it will be hidden when there are none
For further information about the components, refer to the *Javadoc*
# Documentation
The detailed documentation can be found in: `workbenchfx-demo/src/main/resources/com/dlsc/workbenchfx/modules/webview/index.html`
It can also be read by opening the **Documentation** module in `ExtendedDemo` or the `CustomDemo`.
# Basic Structure
## Workbench Concept
*WorkbenchFX* uses the builder pattern to create the `Workbench` object, since it allows to use optional features in a flexible way.
The minimal usage requires only to specify the `WorkbenchModule` objects to be used in the `Workbench`.
Afterwards, optional features can be defined using their respective method call before calling `build()`.
For better illustration, the basic concept of creating a `Workbench` object is shown below:
```Java
Workbench workbench =
Workbench.builder( // Using the static method call
new CustomWorkbenchModule() // class CustomWorkbenchModule extends WorkbenchModule
...
)
// .toolbarRight(...) // optional usage of additional features like navigationDrawer(), modulesPerPage(), etc.
.build(); // The build call creates, initializes and returns the Workbench object
```
Note:
- The result of the `build()` call is a `Control` which can be set in a scene
- For use with FXML & [Scene Builder](https://gluonhq.com/products/scene-builder/), there is also a default constructor `new Workbench()`. However, in this case, modules and other optional features need to be defined separately afterwards
## Module Lifecycle
The lifecycle methods are implicitly being called by the workbench.
You **must not** call any of the lifecycle methods by yourself.
To close and open modules use only `workbench.openModule()` and `workbench.closeModule()`.
The abstract class `WorkbenchModule` contains four different lifecycle methods which can be overridden:
Method | Description
-------------- | -----------
`init()` | Gets called when the module is being opened from the overview for the first time
`activate()` | Gets called whenever the currently displayed content is being switched to this module
`deactivate()` | Gets called whenever this module's currently displayed content is being switched to the content of another module
`destroy()` | Gets called when this module is explicitly being closed by the user by clicking on the *'x'* symbol in the `Tab`
**When extending `WorkbenchModule`, it is only required to implement the `activate()` method.**
([Extending the WorkbenchModule](#extending-the-workbenchmodule))
Overriding all other lifecycle methods is optional and only needs to be done to perform additional actions in the lifecycle.
Besides a call to `super()`, no further workbench-related code is required when overriding a lifecycle method.
Note:
- For further information, refer to our documentation or the *Javadoc*
- The full documentation about the module lifecycle can be found in the documentation file `workbenchfx-demo/src/main/resources/com/dlsc/workbenchfx/modules/webview/index.html`, in the section *WorkbenchModule Lifecycle*
# Demos
We created several demos to visualize the capabilities of *WorkbenchFX* in the `workbenchfx-demo` folder:
File | Description
------------------- | -----------
`SimpleDemo.java` | Shows the simplest usage of *WorkbenchFX* with only three modules and no optional features used
`ExtendedDemo.java` | Shows a simple workbench application with most of the features used in a simple way.
`CustomDemo.java` | A workbench application which uses all features, to demonstrate the full capability of *WorkbenchFX*
`FXMLDemo.java` | A minimal example of how to use *WorkbenchFX* with FXML & [Scene Builder](https://gluonhq.com/products/scene-builder/)
# Getting started
## Extending the WorkbenchModule
It is required to create a new class and extend `WorkbenchModule`, in order to create a custom module:
```Java
public class CustomModule extends WorkbenchModule {
}
```
It is then required to call the `super()` constructor and pass in a `String` as the name and either an `Image`, `FontAwesomeIcon` or `MaterialDesignIcon` as an icon for the module
(icon cheatsheets: [materialdesignicons.com](https://materialdesignicons.com/), [fontawesome.com](https://fontawesome.com/v4.7.0/)):
```Java
public CustomModule() {
super("My first Workbench module", MaterialDesign.MDI_THUMB_UP); // a name and an icon is required
}
```
Furthermore, overriding the `activate()` method is also required.
This lifecycle method will be called when clicking on the `Tile` to open the module (see [Module Lifecycle](#module-lifecycle)):
```Java
@Override
public Node activate() {
return new Label("Hello World"); // return here the actual content to display
}
```
The minimal implementation of a custom `WorkbenchModule` finally looks like the code snippet below.
Returning a *Hello World Label* represents the view which will be displayed in the final application.
For further information, refer to the *Javadoc*.
```Java
public class CustomModule extends WorkbenchModule {
public CustomModule() {
super("My first Workbench module", MaterialDesign.MDI_THUMB_UP); // A name and an icon is required
}
@Override
public Node activate() {
return new Label("Hello World"); // return here the actual content to display
}
}
```
## Creating the Workbench
After extending the `WorkbenchModule`, the `Workbench` can be created.
To do this, access the `WorkbenchBuilder` by calling `Workbench.builder()`, passing in the previously created module as an object and build the `Workbench` by calling `workbench.build()`:
```Java
// Creating the Workbench
Workbench customWorkbench = Workbench.builder( // Getting a WorkbenchBuilder
new CustomModule() // Adding the CustomModule
).build(); // Building the Workbench
```
For the *final application*, it can then be used in a `Scene` as follows:
```Java
public class CustomDemo extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Workbench customWorkbench = Workbench.builder(
new CustomModule()
).build();
Scene myScene = new Scene(customWorkbench);
primaryStage.setScene(myScene);
primaryStage.setWidth(700);
primaryStage.setHeight(450);
primaryStage.show();
}
}
```
This code snippet results in the following application:

The default implementation comes with a clickable `Tile` to open the module.
Opening the module, creates a `Tab` with the defined icon and text.
The content returned in the `activate()` method is displayed in the center.
By clicking on the *add button*, you can get back to the `AddModulePage`.
Closing the opened module is achieved through clicking on the close button in the `Tab`.
### Single Module Layout
If the workbench consists of only one module, a single module layout is used to display the module.
In the single module layout, the tab bar and the add module button are not visible and the module is
automatically opened on startup.
This results in a very basic application as can be seen below

## Optional Methods
### WorkbenchBuilder
These optional method calls are called after adding the custom modules to the builder:
```Java
Workbench workbench = Workbench.builder(...)
.modulesPerPage(6) // call the optional methods
.build();
```
The following methods are optionally available to further configure the `Workbench`:
Method in WorkbenchBuilder | Description
-------------------------- | -----------
`modulesPerPage()` | Defines the amount of `Tile`s that should be shown per `Page` in `AddModulePage`. The default value is set to 6
`navigationDrawerItems()` | Allows to add `MenuItem`s which are then displayed in the `NavigationDrawer`.
`toolbarLeft()` | Allows to add `ToolbarItem`s on the left side of the toolbar on top of the `Tab`s
`toolbarRight()` | Allows to add `ToolbarItem`s on the right side of the toolbar on top of the `Tab`s
When the default layout of `Page`, `Tab`, `Tile` or `NavigationDrawer` don't fulfill the desired requirements, it is possible to replace them:
Method in WorkbenchBuilder | Description
-------------------------- | -----------
`navigationDrawer()` | Allows setting a custom implementation of the `NavigationDrawer` control, which will then be used
`pageFactory()` | Requires a `Callback` function which takes a `Workbench` and then returns a custom implementation of a `Page` control
`tabFactory()` | Requires a `Callback` function which takes a `Workbench` and then returns a custom implementation of a `Tab` control
`tileFactory()` | Requires a `Callback` function which takes a `Workbench` and then returns a custom implementation of a `Tile` control
### Workbench
After the `build()` call on `WorkbenchBuilder`, the `Workbench` is created.
The following selective calls might be of interest:
Method in Workbench | Description
---------------------------- | -----------
`showNavigationDrawer()` | Shows the `NavigationDrawer`
`getNavigationDrawer()` | Returns the `NavigationDrawer`
`getNavigationDrawerItems()` | Returns the `ObservableList` of the drawer's `ToolbarItem`s
`openModule()` | Opens the specified module
`getModules()` | Returns a list of all modules stored in the workbench
`show...Dialog()` | Shows a [predefined dialog](#predefined-dialogs)
`showDialog()` | Shows a [custom dialog](#custom-dialog)
`showDrawer()` | Shows a [custom drawer](#drawer)
`getToolbarControlsLeft()` | Returns the list of items on the left of the `Toolbar`
`getToolbarControlsRight()` | Returns the list of items on the right of the `Toolbar`
`showOverlay()` | Shows a [custom overlay](#custom-overlay)
`hideOverlay()` | Hides a [custom overlay](#custom-overlay)
### WorkbenchModule
The `WorkbenchModule` also provides useful functionality.
It is possible to add `ToolbarItem`s to the toolbar of the module (just like in the workbench):
Method (WorkbenchModule) | Description
--------------------------- | -----------
`getWorkbench()` | In the `init()` call, the `Workbench` is stored in the module. Calling this enables to call methods on the `Workbench` within the `WorkbenchModule`.
`getToolbarControlsLeft()` | Returns a list of `ToolbarItem`s. Adding items to the list will automatically create a toolbar between the tab bar and the module content and show the items on the left side
`getToolbarControlsRight()` | Returns a list of `ToolbarItem`s. Adding items to the list will automatically create a toolbar between the tab bar and the module content and show the items on the right side
`close()` | Will immediately close the module, without calling `destroy()` first (see [Module Lifecycle](#module-lifecycle))
# Using the Components
## ToolbarItem
The `ToolbarItem`s which can be set in the toolbars of either the workbench or the module are styled and behave differently based on their content.
If for example the item contains a `String` as text and a `MenuItem` it is automatically assumed that the styling and behavior of a `MenuButton` is needed.
If on the other hand only an `IconView` is defined, it is assumed, the behavior of a `Label` is desired.
Adding different attributes to the `ToolbarItem` results in different representations:
They can also be seen in the *toolbar* of the `CustomDemo`
Syntax
Representation
// Label with text
ToolbarItem toolbarItem = new ToolbarItem("Hello World");
// Label with graphic
ToolbarItem toolbarItem = new ToolbarItem(
new FontIcon(MaterialDesign.MDI_THUMB_UP)
);
// Label with text and graphic
ToolbarItem toolbarItem = new ToolbarItem(
"Hello World",
new FontIcon(MaterialDesign.MDI_THUMB_UP)
);
// Button with text
ToolbarItem toolbarItem = new ToolbarItem(
"Hello World", event -> System.out.println("Hello World")
);
// Button with graphic
ToolbarItem toolbarItem = new ToolbarItem(
new FontIcon(MaterialDesign.MDI_THUMB_UP),
event -> System.out.println("Hello World")
);
// Button with text and graphic
ToolbarItem toolbarItem = new ToolbarItem(
"Hello World",
new FontIcon(MaterialDesign.MDI_THUMB_UP),
event -> System.out.println("Hello World")
);
// MenuButton with text
ToolbarItem toolbarItem = new ToolbarItem(
"Hello World",
new MenuItem("Content 1"), new MenuItem("Content 2")
);
// MenuButton with graphic
ToolbarItem toolbarItem = new ToolbarItem(
new FontIcon(MaterialDesign.MDI_THUMB_UP),
new MenuItem("Content 1"), new MenuItem("Content 2")
);
// MenuButton with text and graphic
ToolbarItem toolbarItem = new ToolbarItem(
"Hello World",
new FontIcon(MaterialDesign.MDI_THUMB_UP),
new MenuItem("Content 1"), new MenuItem("Content 2")
);
// MenuButton with a MenuItem containing custom content
ToolbarItem toolbarItem = new ToolbarItem(
"Account",
new FontIcon(MaterialDesign.MDI_ACCOUNT),
new MenuItem("",
new HBox(
new Label("Login: "),
new TextField(),
new Button("", new FontIcon(
MaterialDesign.MDI_PLUS))
)
)
);
## Dialog
A demo of the dialogs can be found in the `DialogTestModule` of the [Custom Demo](#demos)
### Predefined Dialog Types
*WorkbenchFX* comes with a lot of predefined dialog types.
Using them is as simple as calling `workbench.show...Dialog()` with the desired dialog type.
After clicking on one of the `Button`s of a dialog, the corresponding `ButtonType` is returned as the result of the dialog.
Therefore it is required to define a `Consumer` for every dialog to validate the answer.
A few examples on how to use them are listed below:
```Java
// Precondition
Workbench workbench = Workbench.builder(...).build; // Creating the workbench
Button dialogBtn = new Button("Show Dialog"); // Assuming the button is used in a module
```
Syntax
Outcome
// Confirmation Dialog
dialogBtn.setOnAction(event ->
workbench.showConfirmationDialog(
"Continue without saving?",
"Are you sure you want to continue without saving"
+ "your document?",
buttonType -> { // Proceed and validate the result }
)
);
// Error Dialog
dialogBtn.setOnAction(event ->
workbench.showErrorDialog(
"Button click failed!",
"During the click of this button, something went"
+ "horribly wrong.",
buttonType -> { // Proceed and validate the result }
)
);
// Error Dialog with exception
dialogBtn = null; // Provokes an exception
try {
dialogBtn.setOnAction(
event -> System.out.println("Throws NPE!"));
} catch (NullPointerException exception) {
workbench.showErrorDialog(
"Button click failed!",
"During the click of this button, something went "
+ "horribly wrong. Please forward the content "
+ "below to anyone but the WorkbenchFX "
+ "developers to track down the issue:",
exception
buttonType -> { // Proceed and validate the result }
);
}
// Error Dialog with details
dialogBtn.setOnAction(event ->
workbench.showErrorDialog(
"Button click failed!",
"During the click of this button, something went"
+ "horribly wrong.",
"Details about this exception are not present.",
buttonType -> { // Proceed and validate the result }
)
);
// Warning Dialog
dialogBtn.setOnAction(event ->
workbench.showWarningDialog(
"Reset settings?",
"This will reset your device to its default"
+ "factory settings.",
buttonType -> { // Proceed and validate the result }
)
);
// Information Dialog
dialogBtn.setOnAction(event ->
workbench.showInformationDialog(
"Just to let you know",
"(This is an information dialog)",
buttonType -> { // Proceed and validate the result }
)
);
### Custom Dialog
Sometimes just using the default dialog types are not enough.
For such special cases, the `workbench.showDialog()` method can be used.
With `WorkbenchDialog.builder()` a custom dialog can be created.
The builder provides some useful methods which can be used:
WorkbenchDialog.builder(*Parameters*) | Description
------------------------------------- | -----------
`String title` | Required and defines the `title` of the dialog
`String message` | Optionally either `message` or `content` can be defined. The `message` is located below the `title`
`Node content` | A `Node` with custom content
`Type type` | Defines one of the default dialog types like `Type.ERROR`, `Type.INFORMATION`, etc. The corresponding buttons and style class will automatically be set
`ButtonType... buttonTypes` | All the specified button types will be set (eg. `OK`, `CANCEL` and `APPLY` for a preferences dialog)
Note:
- Defining `content` will override further definitions of `message`, `details` or `exception`
WorkbenchDialog.builder().*Parameters* | Description
-------------------------------------- | -----------
`blocking(boolean)` | Defines whether clicking on the `GlassPane` closes the dialog or not (i.e. forcing a decision when blocking)
`onResult(Consumer)` | After clicking on a dialog button, the clicked `ButtonType` is returned. Enables to define an action to be performed when a dialog button was pressed
`details(String)` | The dialog will display the specified error message ([Error Dialog With Details](#details-dialog)). Will not be displayed when defining a content
`exception(Exception)` | The dialog will display the stacktrace of a specified `Exception` ([Error Dialog With Exception](#exception-dialog)). Will not be displayed when defining a content
`maximized(boolean)` | Defines whether the dialog's size should take up the whole window or only as much as needed by the content
`showButtonsBar(boolean)` | Defines whether the dialog's buttons should be shown or not
`onShown(EventHandler)` | The `EventHandler` which is called when the dialog is showing
`onHidden(EventHandler)` | The `EventHandler` which is called when the dialog is hidden
`dialogControl(DialogControl)` | Makes it possible to define a custom `DialogControl`
`build()` | Builds the `WorkbenchDialog`
WorkbenchDialog | Description
---------------------------------- | -----------
`getButton(ButtonType buttonType)` | Returns an `Optional