This documentation pages give you detailed information about all parts of JacpFX, how to bootstrap a new JacpFX application and the general usage. You may want to read the quick-start tutorial to start with a JacpFX project.
JacpFX is an UI application framework based on JavaFX, supporting developers to structure an application with loosely coupled, reusable components. It frees you from the pitfalls of traditional multi-threaded programming helping you to separate the task execution from UI changes in your client application. JacpFX focusing on following goals to deliver best developer and user experience:
Like any other UI application framework JacpFX has a hierarchic component-structure to create client applications.
The following components make up a JacpFX application:
JacpFX projects have a typical maven project structure.
root | src | | | main | | | java | | | resources | | | bundles (Resource bundles) | | | fxml (FXML files) | | | styles (CSS files) | pom.xml
An ApplicationLauncher contains the main method, the component-scanning configuration, the managed container configuration and a reference to the workbench class.
JacpFX defines a Launcher interface which can be implemented to work with different managed containers like Spring or Weld. Currently Spring is used as the main container implementation, but you can use a minimal Launcher without any dependencies. For the Spring implementation two abstract Launcher implementations are available:
The "getXMLConfig()" methods returns the name of your spring configuration xml, which is located in the resources folder.
The "getConfigClasses()" returns an array with all valid spring configuration classes (annotated with @Configuration)
This is an example for the usage of the „minimal launcher“ without any other dependencies.
Returns the defined Workbench class.
Define all packages to scan for Components and Perspectives. JacpFX uses component scanning to resolve all Components and Perspectives by ID.
This method gives you access to the JavaFX stage. You may define a stylesheet for your application.
The Workbench is the root node of your client project. It provides a simple interface to configure the basic behavior of your client. Besides the application launcher, it is the only component where you can get direct access to the JavaFX "stage". Furthermore a Workbench logically groups all Perspectives defined by @Workbench annotations.
The Workbench interface defines two method:
This method is the first one called on application startup. It allows you to do a basic configuration of your application. The method signature defines three parameter:
Message
WorkbenchLayout
Stage: the JavaFX "Stage" object
The postHandle method will be executed after the configuration in the "handleInitialLayout" method. Depending on the configured toolbars and menus you can add global toolbar/menu entries to your application here. The FXComponentLayout interface defines the following methods:
For detailed information about toolbars, see Toolbars
To declare references to Perspectives, simply add the Perspective ID's to the "perspectives" attribute of "@Workbench" annotations. The component-scanning tries to find the corresponding Perspective implementation in the classpath. The Implementations do not need to be located in the same project as the workbench as long they are in the classpath.
A FXPerspective defines the basic UI structure for your view and provides a container for Components.
While a FXPerspective is more like a template with placeholders (or a portal page), Components are the detail views of your application (or the portlets).
A typical UI application has a root node and a large tree of Nodes/Controls which represent the application UI. The leaf nodes of such a component tree are your user defined controls like Buttons, TextFields and so on. A Perspective allows you to register JavaFX Nodes of your FXPerspective view, where Component views are rendered. Child Components in your FXPerspective can now registers themselves to be rendered in one of those targets.
A FXPerspective defines five lifecycle hooks:
FXPerspective can be implemented either programmatically in plain JavaFX or declarative with an FXML view.
Programmatic FXPerspectives declare their view in plain JavaFX. You can create any complex UI tree but you have to register the root Node of your UI tree which will then be added to the workbench.
Declarative FXPerspectives provides their view by defining a FXML file representing the view. The root Node is always the root of your FXML and is automatically registered.
Component references are defined inside the @Perspective annotation. Once the application is started you can move Components from one Perspective to another. Components are subjected to one simple rule: They are ALWAYS unique per Perspective. You can't add the same Component twice in one FXPerspective, but you can use one Component in many FXPerspectives. The same Component will be created in its own instance per FXPerspective.
Render targets are areas in your FXPerspective where Component views are rendered. You may register any Node of your FXPerspective view to be a render target. A child Component of your FXPerspective can now register itself to be rendered in this node.
The @Perspective annotation provides necessary metadata for all classes implementing the FXPerspective interface. The following attributes describe a JacpFX FXPerspective:
While FXPerspectives help you to structure your application, Components are more like "micro" applications or portlets. You can simply create master-detail views and reuse Components in different FXPerspectives. Basically JacpFX Components are distinguished in UI and NonUI Components; UI Components may contain your complex UI (e.g Form) and Controls like "TextField" or "Button". NonUI Components are meant to be services for long running tasks or a connector to an external system. Common to all Componentsis that they have a “handle” method. That method will be run outside the FX application thread so the execution does not block the rest of your UI.
UI Components must implement the "FXComponent" interface. They act as controller class and return a view either in plain JavaFX or FXML. While JavaFX Components must return a (JavaFX) Node, FXML-Components pass the root node of their FXML view directly to the parent FXPerspective.
The FXComponent interface defines the following two methods:
FXComponent may be written either programmatically in plain JavaFX or declarative, with an FXML view.
The @View annotation contains all metadata related to a JacpFX-Component implementing the FXComponent interface.
The "postHandle" method of a FXComponent must always return a JavaFX Node representing the view of the JacpFX-Component.
The @DeclarativeView annotation contains all metadata related to the FXML-Component implementing the FXComponent interface.
The "postHandle" method of a FXML FXComponent must return NULL, as the root node of the FXML-file will be passed to the FXPerspective.
Callback Components are service like Components which react on messages and returns an Object to the caller Component or any other target (Request/Response). By default the caller Component will be notified unless no return value is specified.
The CallbackComponent interface defines the following two methods to implement:
The @Component annotation contains all metadata related to the Callback-Component implementing the CallbackComponent interface.
CallbackComponents can be stateful or stateless
A stateful CallbackComponent must implement the CallbackComponent interface and define the @Component annotation. In terms of JEE it is a "singleton per Perspective" Component. While JEE singletons must be synchronized (Container or Bean managed concurrency), JacpFX Components are never accessed directly (only trough messages) and must not be synchronized. The container puts all messages to a FIFO queue and is aware of correct message delivering (similar to a Message Driven Bean running on one thread). Like all JacpFX Components it has a handle method that is executed in a separate Thread (Worker Thread). Use this type of Component to handle long running tasks or service calls and when you need a conversational state. The result of your task will be sent to the message caller by default. This type of Component has one method you have to implement:
A stateless CallbackComponent must implement the CallbackComponent interface and define the annotations @Component and @Stateless. Stateless Components are using instance-pooling for scaling, a CallbackComponent pool will be created for every Component per Perspective.
JacpFX Fragments are small managed Components, that exist in the context of a FXPerspective or a FXComponent. The purpose of a Fragment is to create a reusable custom control or a group of controls that has access to the parent context. This allows the Fragment to send messages, access resources and to interact with the parent FXComponent or FXPerspective.
A Fragment can either extent a JavaFX "Node" or declare a FXML view. The Fragment itself cannot be a message target, but his parent FXComponent can access his Controller class and the view.
The @Fragment annotation contains all metadata related to the JacpFX Fragment.
Fragments can either extend a JavaFX Node, or be a POJO defining a FXML view.
Fragments never instantiated directly, they can only be created inside a FXPerspective or an FXComponent. To create a Fragment, the Context interface provides the method: getManagedFragmentHandler(FragmentOne.class); and returns a ManagedFragmentHandler. The Handler provides access to the controller (FragmentOne) and to the view (VBox).
Depending on the Fragment scope, the method call returns always the same instance or in case of "prototype" scope, different one.
The ManagedFragmentHandler holds the reference to the Fragment instance and their view. To create a Fragment, the JacpFX Context interface provides the method: getManagedFragmentHandler(FragmentOne.class); and returns a ManagedFragmentHandler. The Handler provides access to the controller (FragmentOne) and to the view (VBox).
Messaging is an essential part of JacpFX that allows to communicate with all FXPerspectives/JacpFX Components, and to change their state. You can send an object to any components and start their specific lifecycle.
The Message interface provides access to the message payload itself and contains methods for easy message checks. The interface contains following methods:
The JacpFX Context provides methods to send messages to other Components and to the caller itself.
JacpFX has a hierarchical Component schema where a Workbench is the root node and Components are the leaf nodes. The Workbench can never be a message target itself but you may send messages from a FXWorkbench to any Perspective/Component. JacpFX has a simple "." (dot) separator to specify the exact target of your message.
The JacpFX Context provides methods to access to the metadata of any Perspective/Component and to several JacpFX functionality. To get a org.jacpfx.rcp.context.Context reference you must annotate a class member with this type. Following methods and metadata are provided by the Context interface:
@Component, @DeclarativeView, @View and @Perspective annotation allow the declaration of a resource bundle and a default localeID. If no localeID is declared the system default is assumed. Set the relative resourceBundleLocation in URL (in resource) like "bundles.languageBundle" and create in resources/bundles a file languageBundle_en.properties for further informations on resource bundles see: http://docs.oracle.com/javase/7/docs/api/java/util/ResourceBundle.html.
To get access to the ResourceBundle use a @PostConstruct annotated method with a ResourceBundle parameter or annotate a class member of type ResourceBundle with @Resource.
The default project layout provides following structure for resources:
src/main/resources:
Assuming you put your stylesheet to src/main/resources/styles/mystyle.css, you may assign the stylesheet in the application launcher. The postInit method gives you access to the JavaFX stage objects where you may ad the stylesheet like this:
Dependency injection is provided by the Launcher implementation which is currently is Spring. All Perspectives and Components are Spring managed beans and supports all injection capabilities of a Spring bean.
An error handler catches all Exceptions occur in an JacpFX application and forwards it to an error dialog. JacpFX comes with a default implementation, but you may want to overwrite it with your own implementation. To do so you need to extend the AErrorDialogHandler and to implement an error dialog.
The ErrorDialog must extend an JavaFX Node and should handle/display the StackTrace or an appropriate error message.
To register the dialogHandler overwrite the getErrorHandler() method in the application launcher.
JacpFX provides a default optionpane, which can be displayed as a modal dialog.
The optionpane holds a title a message four buttons (Ok, Cancel, Yes, No) closeButton
To create an optionpane, you can use the createOptionPane method of the JACPDialogUtil.
While the title and the message will be taken as parameter of the create method, you can set the Eventhandlers for all four buttons individually. Every button has its own “setOnAction” method.
By calling one of those four, the corresponding button will be added to the pane. There is no other way to add buttons to the default optionpane. One of your buttons can be chosen as default button. The default-button will have the focus, after the optionpane shows up. If the same “setOnAction” method will be called several times, only the last Eventhandler will be used. After clicking a button, the optionpane will hide automatically. Beside of the four buttons, there is also an option to show a close-button on the optionpane. That button will simply close the optionpane without triggering any other event or Eventhandler. The options for the close-button are:
Showing and hiding the optionpane is managed by the JACPModalDialog.
To show a dialog you have to provide a Node, that should be displayed (e.g. JACPOptionPane or a Custom Node). Call hideModalMessage() will hide the dialog, which is currently shown.
The JACPOptionPane comes with a default theme, which can be overridden using a custom stylesheet. Every part of the pane has a corresponding css-class.
Attention: The message part uses the JavaFX Text class. So ensure to use -fx-fill to apply a color to the message text. All other parts will use -fx-text-fill. With a custom stylesheet, using the mentioned classes, you’re able to style the option pane to your specific needs.
The JACPToolbar will help you to organize the buttons you’ll need for your application. Toolbars can be registered on any orientation of the application (NORTH, WEST, SOUTH, EAST)
All Buttons will be added within a given context, which means, the toolbar knows which button belongs to which perspective, component or workbench. This allows the toolbar to show and hide your buttons as needed (eg. switching to another perspective).
To manage the buttons by yourself, you can add buttons by providing an id. If you do so, the toolbar will not handle those buttons, which means, they will not disappear if you switch perspectives.
JacpFX uses an extended Toolbar, which allows to add Buttons to either end or to the center. You can apply Regions (e.g. Buttons) to the JACPToolbar by using the methods:
To manage the context by yourself, all methods are also available with a second parameter (String id).
The end portion of a toolbar will be the right hand side, if the toolbar has a horizontal orientation, or the bottom end, if the toolbar is oriented vertically.
Added nodes on the toolbar, can be removed by using the remove method. For self-managed buttons, you can also remove buttons for a given id.
To self-manage your buttons, use the methods hideButtons(String id) and showButtons(String id)
Due to the fact that the JACPToolbar only uses two style classes, where one of them is only for very special styling needs, the styling is pretty easy. The two classes for styling are: .jacp-tool-bar .jacp-button-bars (defines the container for the added nodes on either end)
Every Node, you will add, has to be styled separately. After styling the JACPToolbar and the added nodes (buttons in this case) the Toolbar could look like this:
The JACPMenuBar is registered to the Workbench. It is an extended MenuBar, which will take custom nodes, windowbuttons, and (of course) MenuItems.
Just setup your menu within the postHandle-method of your workspace. Basically the menubar will work, as known from the JavaFXmenuBar, for adding MenuItems. Windowbuttons (minimize, resize, close) have to be registered if needed. The Buttons will only show up, if the Stage is set to UNDECORATED.
For MAC OS X users: Hence to the option of using the system-menu on the very top of the screen, the stage will always be DECORATED, thus the buttons will never show up.
Since the JACPMenuBar uses a JavaFX MenuBar , for holding MenuItems , you can use the std. MenuBar classes for styling. The windowbuttons, are styled by using a set of classes and ids.
Styles Windowbuttons can look like this.
The JACPHovermenu is a extended button, which provides some a kind of dropdown portion to add more content (e.g. buttons, checkboxes etc.)
The additional part (ContentPane) will hover above the UI. If you click on the button, the ContentPane shows up and disappears if a click outside the Hovermenu is detected.
For the Hovermenu the ContentPane is a plain JavaFX - Pane, which allows you to add about anything to it.
The JACPOptionButton is based on a Hovermenu. It will take a single or a series of buttons, which are added to the ContentPane.
The behavior is the same as known from the hovermenu. If the main button is clicked, the ContentPane and the Buttons are shown. The ContentPane will be hidden, if a click outside the ContentPane is detected.
For a OptionButton, you can decide if the ContentPane will also disappear if a Button of the ContentPane is clicked. If you want that to happen, just set the hideOnAction parameter of the constructor to true.
@View
The @View annotation is used for components implementing the FXComponent interface and declaring a JavaFX based view. The return value of a components postHandle method will be placed in the defined render target of the parent FXPerspective. The annotation contains following attributes:
@DeclarativeView
The @DeclarativeView annotation is used for components implementing the FXComponent interface and declaring a FXML based view. The return value of a components postHandle must be null as the FXML root node will be placed in the defined render target of the parent FXPerspective. The annotation contains following attributes:
@Component
The @Component annotation contains all metadata related to the Callback-Component implementing the CallbackComponent interface.
@Perspective
The @Perspective annotation provides necessary metadata for all classes implementing the FXPerspective interface. The following attributes describe a JacpFX FXPerspective:
@Workbench
The @Workbench annotation provides necessary metadata for all classes implementing the FXWorkbench interface. The following attributes describe a JacpFX FXWorkbench:
@Fragment
The @Fragment annotation contains all metadata related to the JacpFX Fragment.
@PostConstruct
Lifecycle annotation, a method annotated with @PostConstruct is executed on component startup (also when component is reactivated). It is applicable for all component types and FXPerspective(s). Annotated methods must not throw a checked exception. Following method signature is applicable:
@PreDestroy
Lifecycle annotation, a method annotated with @PreDestroy is executed on component shutdown. It is applicable for all component types and FXPerspective(s). Annotated methods must not throw a checked exception. Following method signature is applicable:
@OnShow
Lifecycle annotation, a method annotated with @OnShow is executed when a FXPerspective gets the focus. Usually this happens on perspective switch when a FXPerspective receives a message. Annotated methods must not throw a checked exception. Following method signature is applicable:
@OnHide
Lifecycle annotation, a method annotated with @OnHide is executed when a FXPerspective looses the focus. Usually this happens on perspective switch when an other FXPerspective receives a message. Annotated methods must not throw a checked exception. Following method signature is applicable:
@Resource
The @Resource annotation can be applied to a member to get the reference to the JacpFX Context or the resource bundle.