Sorry about not posting links last week – I was on vacation, and the internet in my hotel was terrible. Because I didn’t get a post out last week, this week I have a heap of links to share. Enjoy! :-)

  • Geertjan Wielenga has posted about his modular JavaFX Application Framework project, which looks promising.
  • Danno Ferrin has put out updated versions of the Gradle and Maven plugins for JavaFX 8u20.
  • Tomas Mikula has created a simplified VirtualFlow implementation for use in his RichTextFX project. VirtualFlow is used to efficiently handle ListView, TableView, etc. Tomas’ implementation is a more performant implementation, at the cost of reduced functionality. As the owner of the JavaFX VirtualFlow implementation, I would love to see the official code getting faster, but it is very, very hard to achieve without functional regressions. It is always one of those tasks I try to undertake once per release, but I think most of the low-hanging fruit has well and truly been picked. Quick update: I just spent an hour trying to improve the performance of the JavaFX VirtualFlow based on Tomas’ benchmark, and managed to take the results from 25/25/5/75 to 1/0/5/0 (refer to the flowless wiki document to understand what these numbers mean). You can see more detail in my last two comments over at RT-35395.
  • Dirk Lemmermann continues to post JavaFX-related tips, including ‘Have the Final Word‘, ‘Be Observable‘, ‘Use Transparent Colors‘, and ‘Use CSS Color Constants / Derive Colors‘.
  • Jens Deters has three posts. Firstly, he has a post talking about how to get rid of focus highlighting in JavaFX. David Grieves’ comment gives good insight into how borders are handled in JavaFX. Secondly, Jens has announced that MQTT.fx 0.0.4 has been released. Finally, Jens has a post about UI logic with JavaFX Bindings.
  • Andres Almiray has two posts on ‘getting started with Griffon and JavaFX’. The first post talks about “the new capabilities of the framework, specifically targeting JavaFX as the main UI toolkit and Java as the main programming language.” The second post talks about the same application as in part one, but using Groovy instead of Java.
  • Pedro Duque Vieira has blogged about the addition of a ToggleSwitch control to JFXtras, which also includes a JMetro style.
  • John Sirach has posted a review of the recently released JavaFX 8: Introduction by Example book.
  • Alexander Casall has a post about how to get the controller of an included FXML when using FXML composition.
  • William Antônio has a blog post about the Gainda project, which appears to be a DSL for creating JavaFX applications in JavaScript (using Nashorn).
  • Manuel Mauky has been working on an ‘Advanced Bindings‘ project for JavaFX, which, not surprisingly, is “a collection of useful helpers and custom binding implementations to simplify the development of applications that are heavily based on JavaFX’s Properties and Bindings. “
  • David Gilbert let me know that JFreeChart 1.0.18 has been released. He went on to say that “it features JavaFX support with a new ChartViewer control that renders charts to a Canvas node and handles tooltips, a context menu, zooming via mouse drag and wheel events, panning and mouse event notifications (more or less equivalent to the existing ChartPanel class used in Swing). This will ease the path for our users that are migrating Swing applications to JavaFX, as their charting code will require very minimal changes.”
  • Mark Stephens from IDR solutions (makers of the PDF viewing software for Swing and JavaFX) let me know that they “offer an Open source version (with less bells and whistles) under an LGPL license at http://www.idrsolutions.com/open-fx/“. He went on to say that “we wanted a generic free version which lots of people could use (including us in our NetBeans plugin) and we think there are lots of uses for this in embedded. Then a high end supported version with support and lots of extras (like a slick pageflow which could work really nicely on a Pi with touchscreen) which funds the development.”
  • Johannes Rupprecht has a post about custom transitions in JavaFX.

That’s a lot of links! Keep up the hard work folks, it’s fascinating reading what you’re all doing, and it makes me jealous that there aren’t more hours in the day to hack on all the stuff you’re doing.

Another quiet week this week. This is a very common pattern in the lead up to JavaOne – people tend to start working on their JavaOne projects and have less time for blogging. Anyway, enjoy the links! :-)

Catch you all next week!

A relatively quiet week this week, which is good for me as I have a tonne of work to get into! :-)

  • I did a very long blog post this week about bringing dialogs to JavaFX. In short, JavaFX 8u40 will be getting a dialog API, but it isn’t yet decided what the API will look like, so now is your chance to influence the API. You should definitely read the linked blog post first, and then you should go to RT-12643, read all of the comments there, and then post your feedback if you have anything to add! :-)
  • Hendrik Ebbers has posted another sneak peak of the AeroFX project, a Windows 7 ‘native’ skin for JavaFX 8.
  • Andres Almiray has posted on boosting JavaFX application development, where he talks about afterburner.fx, afterburner.gfx, and lazybones.
  • Stephen Chin has posted a video from Stuart Marks’ recent presentation at the Silicon Valley JavaFX Users Group, where he spoke on the topic of Java 8 and JavaFX.
  • Thomas Bolz has posted version 1.4 of his BaufiFX application, a mortgage calculator and financial analysis tool written in JavaFX.
  • Rene Jahn has posted on how he built a live ticker for the football world cup using headless JavaFX and the new ‘Monocle’ Glass windowing component of JavaFX. For those unfamiliar with Monocle, you can read more at the JavaFX wiki.

That’s all folks – short and sweet! Catch you all next week! :-)

JavaFX has never had a dialogs API, which has always seemed to be a glaring omission – but no more! It has (finally!!!) been decided that JavaFX 8u40 will be the first release that will include a dialogs API. You can follow along at home with the RT-12643 Jira issue. If you have comments as a result of this blog post, you are also encouraged to send them in to RT-12643. Dialogs can mean different things to different people, and with this comes different expectations over how an API should be formed. In this document I hope to outline what dialogs can mean in an attempt to get everyone on the same page, and from there decide on how best to advance JavaFX into the dialogs era! I should note that I am basing this document on my own perspective and understanding, and I am maybe forgetting or misunderstanding concepts. If this is the case, please email me at jonathan.giles@oracle.com and I’ll be sure to update this document.

What is a Dialog?

A dialog is a popup that appears when the user needs to provide some input. Normally they block input to its owner, and normally they are modal, stopping the execution of the calling code until they return. This is beneficial as it means you can show a dialog, wait for the users response, and react accordingly. The alternative approach is to require callbacks to be called once the dialog is closed, but rarely is this the kind of interaction that a developer wants.

Dialogs can either be in their own top-level window (i.e. a JavaFX Stage), or they may be ‘internal’ (i.e. not in a separate window but embedded within the scene of their owner). I’ve always referred to these concepts (incorrectly) as heavyweight and lightweight dialogs, and I will continue to use this as my way of classifying the two types of dialog in this document. My personal preference has been to always use heavyweight dialogs, but in my experience in developing dialogs for ControlsFX (more details below), I have been surprised by how popular and how commonly used the lightweight dialog has been. Some benefits of lightweight dialogs is that they do not need a windowing system and are therefore more friendly on some touch devices.

Dialogs consist of a number of areas, and what the JavaFX dialogs consist of is still up for discussion. However, some common areas include the title area, the masthead area (which is an area beneath the title and above the content for showing bold text and / or graphics), the content area (where the message or other nodes can be placed), and the button area.

There are typically two common use cases for a dialogs API, and they only differ in how much time the developer needs to spend to bring the dialog up. In other words, the most common use case is to simply show a common dialog type (i.e. warning, confirmation, information, etc) with a pre-specified set of buttons, and to just specify the message (and related attributes), before returning the selected button to the developer so that they may react accordingly. The other common use case is only ever considered by developers when the simpler use case fails them: they find the simplest API that allows for them to customise the dialog to suit their needs. I typically refer to these two approaches as ‘high-level dialogs’ and ‘low-level dialogs’. JavaFX should support both approaches.

There are a number of ways a dialog can be customised – but typically it falls down to a desire to change one or more of the the title, masthead, content or buttons areas. From my experience, the most complex aspect to customising dialogs (from an API perspective) is how to specify and configure the buttons to show to the user. In addition to simply specifying the button text, there needs to be consideration over whether to allow for customising the button graphic, or modifying the default action of the button (the alternative is that the button always hides the dialog without question), and finally being able to specify which button is the ‘default’ or ‘cancel’ buttons (i.e. those that are pressed when the Enter or Escape are pressed). I will give extra attention to this area later in this document.

What is the goal for JavaFX dialogs?

At this stage that question does not have a clearly defined answer. JavaFX dialogs could even be a misnomer – I’m calling the feature ‘dialogs’, but in actual fact they are referred to interchangeably as ‘alerts’ as well.

At the most basic end of the spectrum, JavaFX API could consist of little more than API akin to the JavaScript Alert API (where the only parameter is a String of the text to show the user).

A more advanced API might be simply a low-level Dialog class that allows for setting title, masthead, graphic, content and buttons. What the buttons do and how the dialog looks will be largely left to the user.

Stepping further forward, we could include high-level API to make it easier to show common dialogs, and to have more of the implementation details hidden from the user (e.g. default buttons, default graphics, default text, default actions when buttons are pressed, etc).

The next possible step is to include additional pre-built dialogs, for example font choosers, progress dialogs (bound to a worker), ‘command link’ dialogs, login dialogs, etc.

Finally, a dialogs API could conceivable go so far as to include a wizard API, allowing for easy stepping between multiple pages, including branching, reading user input, and generally having more of a lifecycle.

My personal opinion is that if we are to have dialogs in JavaFX, we should go at least to having high-level API. A future release could include pre-built dialogs like those listed in the final step as users demand them. I have developed a prototype Wizard API in ControlsFX (look under the ‘wizard’ branch) to better understand its requirements, and I think it is safe to work on this after an initial release of dialogs – whilst a Wizard API depends a lot on dialogs, it does not require additional API at that level (rather, it is more concerned with pages, and moving between them, which is unrelated to the topic of this document).

What is ControlsFX Dialogs?

ControlsFX is an open source project consisting of a number of UI controls and other useful classes for JavaFX. One of the areas it covers is dialogs, where it has quite a complete implementation. The ControlsFX Dialogs implementation could quite easily form the basis of a JavaFX dialogs implementation. What is more important, and the purpose of this document, is how we see a JavaFX dialogs API taking shape.

The ControlsFX API documentation can be found at http://docs.controlsfx.org. Specific attention should be paid to the org.controlsfx.control.action and org.controlsfx.dialog packages, as well as the org.controlsfx.control.ButtonBar class, which is responsible for platform-specific button placement. Particularly useful documentation can be found on the Dialog and Dialogs classes, although I should note that this documentation is based on ControlsFX 8.0.6 and it has in fact changed (for the better, I hope) quite significantly in the upcoming 8.0.7 release. In other words, take note of the concepts, but not necessarily the specific API.

What are Actions?

As mentioned above, perhaps the most difficult aspect to a dialog API is determining how to specify and configure the buttons that can be displayed to the user in the dialog.

The Swing JOptionPane approach had two separate ways to specify buttons. Firstly, the common case is available via public static final ints (for example, JOptionPane.YES_NO_CANCEL_OPTION would mean that separate buttons for ‘Yes’, ‘No’, and ‘Cancel’ would be shown to the user). When the dialog was dismissed using this approach, the returned value would be a constant that mapped to another int in JOptionPane, for example, JOptionPane.YES_OPTION. Therefore, code would be written as such:

int response = JOptionPane.showConfirmDialog(
                    frame,                              // owner
                    "Hello world",                      // message
                    "Dialog title",                     // title
                    JOptionPane.YES_NO_OPTION);         // optionType

if (response == JOptionPane.YES_OPTION) {
    …
}

In the situation where custom buttons needed to be specified, the developer, if they wanted to use the high-level API, was forced to call the ‘showOptionDialog’ API, as such:

int response = JOptionPane.showOptionDialog(
        frame,                                   // owner
        "Hello world",                           // message
        "Dialog title",                          // title
        JOptionPane.YES_NO_OPTION,               // optionType
        JOptionPane.INFORMATION_MESSAGE,         // messageType
        null,                                    // icon
        new String[] { "Maybe", "Definitely" },  // options
        "Definitely");                           // default option

In this approach, the optionType argument of YES_NO_OPTION appears to be totally ignored – instead the two strings “Maybe” and “Definitely” are the only buttons presented to the user. Because neither “Maybe” or “Definitely” is a pre-specified option in JOptionPane, there is no way to return an int constant to represent this, so instead the response returned to the user will simply be an integer representing the location of the button in the dialog, counting from left to right.

The problem with this approach, in my opinion, is the disconnect between the provided Strings, and the integer return type. I’m left with two concerns:

  1. There is no way to specify the button type. The button type is important as different operating systems order and position buttons differently, based on their type. The ControlsFX approach below has a way of supporting this, but I would imagine that in JOptionPane OS-specific placement is left up to the developer (and that there is no way to left-align certain buttons – e.g. the ‘Help’ button).
  2. What happens in the RTL case? Do “Maybe” and “Definitely” force their orientation such that they are always in the given order, do we reverse the layout but return the original integer, or do we return different integers?

On top of this, there is no way for the buttons to do anything other than hide the dialog. This is unfortunate, as there are often times where a button press should do something whilst retaining the dialog in its current state. Examples include expanding / collapsing a dialog to show more information (common with ‘exception’ dialog types – the user only wants to see the exception after clicking a ‘show exception’ button), showing a new window with help text, or performing some validation on the dialog before dismissing it. Hopefully I am wrong, but I don’t think there is a high-level way of doing this in Swing JOptionPane.

How can we do this better? One option is to introduce the concept of Action. An Action is essentially an encapsulation of relevant properties, as well as an event handler, for zero or more user interface components to depend on (typically used with controls such as Buttons and MenuItems, for example). Properties an Action might include are text, description (for a tooltip, for example), a graphic, disabled (to specify whether the control is disabled or interactive). On top of this, any control with an Action backing it will defer to the Action when it’s ‘onAction’ event is fired.

The nice thing about considering an Action API for dialogs (and for now lets consider it in isolation of the rest of the JavaFX API framework) is that Actions may be passed into a Dialog, and may also be returned from a Dialog once it has been closed (i.e. if the ‘OK’ button has been clicked, the Action that created that button will be returned).

Introducing an Action API into JavaFX does not come without consequences, so it is not possible to say that an Dialog+Action API combination is the best option available. I will try to outline the possible approaches below, including the scenario where JavaFX does not include an Action API.

Possible Approaches for JavaFX

Now that we’ve covered a lot of the background, theory, and a little of how dialogs are handled in Swing, we can start to look forward and work out what we want to do with dialogs in JavaFX. Fortunately, as mentioned, we already have a great playground to experiment with dialogs API – ControlsFX. We can work on API experiments, and test that the API works as expected with the underlying implementation remaining relatively intact. As of now, I have three different high-level API approaches, and one low-level API which I will outline below.

High-Level Approach 1: Using overloaded static methods

The first implementation takes its API inspiration from Swing, with its JOptionPane API. In short, we provide a Dialog class that provides both high-level and low-level API, depending on how the class is instantiated.

The high-level API can be a series of overloaded public static methods, with names such as:

Dialogs.showConfirmDialog(...)
Dialogs.showInformationDialog(...)
Dialogs.showErrorDialog(...)

The permutations for each dialog type will include versions for various combinations, such as:

message,
message, title
message, title, masthead
message, title, masthead, graphic
message, title, masthead, graphic, actions

Note that the actual final set of methods is still to be defined, so this is just a representation and no means final! Also, the last parameter in the last permutation, ‘actions’, could be either an Array (or varargs) of String or Action, depending on whether Action is part of the JavaFX API or not. I discuss this further later.

The benefit of this approach is that it doesn’t bring in any additional API (such as Actions), but it comes at the cost of being either less configurable or more difficult to configure (as the Action API is able to encapsulate the details about each button in the dialog).

High-Level Approach 2: Use constructor + setter methods

Rather than (or in addition to) having static methods as shown in approach 1 above, we could introduce setters (and probably related getter / property methods). This approach would result in code such as the following:

Dialogs dialog = new Dialogs();
dialog.setTitle("Hello world!");
dialog.setMasthead("I can have an optional masthead too");
dialog.setMessage("This is a dialog message");
Action response = dialog.showConfirm();

Of course, the class name is unlikely to be Dialogs, and there is certain to be convenience constructors that would reduce this down somewhat. My concern with this approach is that people will just end up doing the following:

Action response = new Dialogs("Hello world!", 
                              "I can have an optional masthead too", 
                              "This is a dialog message").showConfirm();

The end result is that the static overloaded methods and the setter approach (given the availability of convenience methods on the constructor) are largely the same, and people are essentially ending up with a poor-mans fluent API (i.e. force everything into the constructor and then call show*()).

High-Level Approach 3: Using a fluent API

The third approach is derived from the ControlsFX API, although quite what is and is not included is up for debate. I will firstly present the entire API (in particular, the ControlsFX dialogs API, as well as the Actions API and the ButtonBar control), and then later I will discuss how this could be stripped back.

Here is the first example, using the ControlsFX Dialogs fluent API. It uses the default buttons (as specified for a ‘confirm’ dialog:

Action response = Dialogs.create()
                       .title("Hello world!")
                       .masthead("I can have an optional masthead too")
                       .message("This is a dialog message")
                       .showConfirm();
            
if (Dialog.ACTION_YES == response) {
    System.out.println("Success!");
}

But what about the case where we want custom buttons in our dialog? Here’s another example using the fluent API:

Action response = Dialogs.create()
                       .title("Hello world!")
                       .masthead("I can have an optional masthead too")
                       .message("This is a dialog message")
                       .actions(Dialog.ACTION_CANCEL, 
                                Dialog.ACTION_YES, 
                                Dialog.ACTION_OK, 
                                Dialog.ACTION_NO, 
                                Dialog.ACTION_CLOSE)
                       .showConfirm();
            
System.out.println("Response: " + response);

This approach is a little….odd…..but it shows a dialog with five actions specified: cancel, yes, ok, no, and close. Each of these actions is converted to a Button and shown within the dialog (with their OS-specific placement taken care of automatically). Whichever button is clicked on is returned as the response, which the user may then check and perform the necessary actions.

What about the case where custom actions are needed (i.e. buttons that perform custom functionality)? This can be handled using the following approach:

Action jumpAction = new DialogAction("Jump!", ButtonType.OTHER);
Action dontJumpAction = new DialogAction("Don't Jump!", ButtonType.OTHER);
            
Action response = Dialogs.create()
                       .title("Hello world!")
                       .masthead("I can have an optional masthead too")
                       .message("This is a dialog message")
                       .actions(jumpAction, dontJumpAction)
                       .showConfirm();
            
if (response == jumpAction) {
    System.out.println("You fool!");
} else if (response == dontJumpAction) {
    System.out.println("Phew, that was close!");
}

Of course, rather than just having custom actions being returned, the action could do anything – it will be called as soon as the button is clicked – and that means functionality can be fired before (or even instead of) closing the dialog.

The code examples above have shown the ControlsFX high-level API, and in particular the fluent API. The main benefit of a fluent interface is readability. The Dialogs class is intended for the 95% of cases where you want to show a confirmation dialog, or a warning dialog, or a information dialog, etc, and you want the majority of the dialog preconfigured (e.g. images, default buttons, etc). Using the Dialogs class is significantly more readable than a couple of dozen overloaded public static methods, because the parameter name is directly beside the argument, rather than simply having a long list of arguments. Once you start enumerating all the possible permutations, you can appreciate that we could end up with a lot of overridden methods, multiplied by how many dialog types we offer (error, information, warning, confirmation, input, font, progress, login, etc):

  • Owner
  • Title text
  • Masthead text
  • Graphic
  • Message text
  • Buttons / Actions
  • Style classes

Then, for certain dialog types, you need to provide default values, lists of possible choices, exception text, etc. Pretty much as soon as you write out the full argument list as a user of JOptionPane-esque API you’ve forgotten what each of the arguments is for (and I’ve seen so many times in Swing people putting things in the wrong order to ….interesting…. results).

However, as I note below, there are alternatives to having a fluent API, which we may consider as an alternative approach if a fluent API proves undesirable.

Low-Level Approach

The ControlsFX low-level API is based around the Dialog class (note the naming distinction – Dialogs vs Dialog). The Dialog class has API for allowing the specification of title, masthead, content, actions, and other applicable properties. From this class it is possible to almost entirely customise a dialog, although in reality this class does force certain layout expectations (if the user wants total customisation, they would want to start with Stage and roll their own from there). In other words, masthead will always be at the top, content will always be in the middle, and the buttons will always be at the bottom.

The main difference between the Dialogs and Dialog class is that Dialog does not have any pre-conceived notion of a default dialog. In other words, whereas Dialogs allows a user to show a confirm, information, error, or other type of dialog (with a default graphic and button configuration), Dialog has no such API. In other words, Dialog is great in the use cases where a user wants to show custom content, without the hassle of needing to handle the general layout of a dialog (i.e. button placement, padding, resize support, node positioning, etc).

Here is a custom login dialog created using the low-level API:

final TextField txUserName = new TextField();
final PasswordField txPassword = new PasswordField();
final Action actionLogin = new DialogAction("Login", ButtonType.OK_DONE){
    @Override public void handle(ActionEvent ae) {
        Dialog dlg = (Dialog) ae.getSource();
        // real login code here
        dlg.setResult(this);
    }
};

Dialog dlg = new Dialog(owner, "Login Dialog");
dlg.setMasthead("Login to ControlsFX");

InvalidationListener changeListener = o -> validate();
txUserName.textProperty().addListener(changeListener);
txPassword.textProperty().addListener(changeListener);

final GridPane content = new GridPane();
content.setHgap(10);
content.setVgap(10);

content.add(new Label("User name"), 0, 0);
content.add(txUserName, 1, 0);
GridPane.setHgrow(txUserName, Priority.ALWAYS);
content.add(new Label("Password"), 0, 1);
content.add(txPassword, 1, 1);
GridPane.setHgrow(txPassword, Priority.ALWAYS);

dlg.setResizable(false);
dlg.setIconifiable(false);
dlg.setGraphic(new ImageView(HelloDialog.class.getResource(
        "login.png").toString()));
dlg.setContent(content);
dlg.getActions().addAll(actionLogin, ACTION_CANCEL);
validate();

Action response = dlg.show();
System.out.println("response: " + response);

Reflections on the APIs Presented

Whilst my experience with ControlsFX is that people are happy with the dialogs API, I have never sought feedback from users of the API directly. I would be very interested to hear what people think about it.

However, having discussed the ControlsFX API very, very briefly with my team at Oracle, it is apparent that the ControlsFX API may not immediately be desirable for inclusion in JavaFX (after having been tidied up and repackaged, of course). This is particularly due to its inclusion of the high-level fluent API outlined above, and also due to its reliance on an Action API for specifying which buttons to show.

There are ways to strip back and change the ControlsFX API, with various implications (both positive and negative). In general, what will happen is that approach two will slowly trend towards approach one (i.e. it’ll move closer to having a JOptionPane-esque API). Below I attempt to discuss the most obvious ways I can change the API in two areas: fluentness and actions.

Fluentness

Obviously, if having a fluent API is not palatable (as it is non-standard API from the JavaFX point of view), we could remove the Dialogs class. From the top of my head, the only other fluent API in JavaFX is the Bindings class, and that class benefits from the fluent API due to the order of calls being important, whereas they do not matter for the Dialogs API. If we remove the Dialogs class, we lose the high-level API, and would need to introduce an alternative. There are at least three options:

Option 1: Add static overloaded methods to the Dialog (or another) class (as shown in approach 1 earlier).

Option 2: Add setter (and getter / property) methods to a class other than Dialog (as shown in approach 2 earlier).

Option 3: Replace the Dialogs class with a DialogBuilder class that has a public static create method, but after that it uses setters to modify the DialogBuilder instance. I think this is a non-starter, given the JavaFX move away from builder classes.

Actions

The other (and arguably the more important) area where the ControlsFX API might be pushing the limits of what is acceptable for JavaFX (at least in the 8u40 timeframe) is the actions API.

Based on my own prototyping of this scenario it is still possible to have both high-level and low-level API as discussed above. The change to the API of removing actions essentially results in an API where all Action arguments are changed to String arguments, and all Action return types are changed to integer return types. All other aspects of this document still remain true – we need to choose a high-level API structure, and if we don’t go with actions we need to be comfortable with the implications of this (as noted in the actions section earlier).

Summary

All this document leads us to one big question: what kind of dialogs API do we want in JavaFX? As with any API discussion we need to be careful to ground ourselves in reality – which I hope this document has achieved. Do we want a simple API to just show alerts, or do we want more configurability to customise what we show in dialogs? Do we want to have pre-built dialogs, or would we rather have just the low-level dialog (which, come on, isn’t all that low-level anyway!) :-) Do we want to break the JavaFX pattern and introduce a fluent API? Is it actually any better, or is it just confusing for people trying to wrap their heads around JavaFX? Do people really like long lists of overloaded methods (it makes your dialog instantiations one (long) line), or do they prefer making use of setters and splitting the instantiation and showing of their dialog over multiple lines?

I am not advocating for any particular approach, although I’m aware I’ve not been completely unbiased either. I should state that my primary goal is to define the best dialogs feature set and API we can, which isn’t necessarily to use the ControlsFX API as-is. I know some people who don’t think an Action API should be part of a UI toolkit, and it is not my goal to force API onto people when the feedback is that it isn’t desired. My inclusion of Action in this discussion is more to highlight my perceived shortfalls if we don’t have some Action API. I’m hopeful others may propose alternate solutions that haven’t even been outlined here.

JavaFX dialogs are targeted to 8u40, and we’re right on the verge of making all these calls, so your input in really important now. Not in a months time – now! As noted on the JavaFX 8u40 page, dialogs should be finished by September 15th, so time is definitely of the essence. Please leave comments on this blog post (or even better, at RT-12643), and I’ll do my best to moderate as quickly as possible.

Thanks for reading this far, you’re a champ!

 

 

Another week rolls around, and with it another weeks worth of links. Enjoy! :-)

JavaFX

  • Tomas Mikula has two posts this week. Firstly, a post titled ‘detecting when the mouse stays still over a node‘. Secondly, he has a post on ‘separation of View and Controller in JavaFX Controls’, which is an interesting read, especially for me as JavaFX needs to have more public API around third party controls. The JavaFX Jira issue (RT-21598) is the best place to discuss this further.
  • Hendrik Ebbers has posted a sneak peak of some work currently being undertaken, to create a Windows 7-esque JavaFX style that is being called AeroFX. Already it looks very promising! This is a follow-on from the very successful AquaFX look developed previously.
  • Tom Eugelink has posted on his circle popup menu progress, which is available for download as part of JFXtras-8.0-SNAPSHOT-r2.
  • Jens Deters has released MQTT.FX 0.0.3. This is an application for publishing and subscribing to MQTT topics, which is commonly used in IOT projects.
  • Sébastien Bordes has announced the release of JRebirth Application Framework 7.7.2. This new version “fixes some troubles experienced with demo applications like bad image loading (by presentation engine) or animation failure that lead to an empty slide.”
  • The ReportMill blog has two posts this week. Firstly, they have announced that SnapCode, their IDE, is the ‘first and only pure JavaFX IDE‘. Secondly, they have posted some sample code for getting the visual bounds of a node. There is a Jira issue (RT-37509) for this functionality, and as I posted in there, I really wish someone would develop the code to make it possible to have a general-purpose glasspane in JavaFX (especially one that supports knowing the visual bounds of a node after scrolling, clipping, effects, etc).
  • Arnaud Nouard has posted that he has updated his Undecorator library for JavaFX 8.0, and that he has used this library in the development (and now release) of his aLive application, intended to “help music bands to organize rehearsals”.

That’s all folks. Catch you next week!

Another week, another round of interesting links. Enjoy! :-)

That’s all for this week – catch you all in a weeks time.

Another week, another round of links. Enjoy! :-)

That’s all folks. Now I can get outside and enjoy the public holiday here in New Zealand! :-)

Wow – this release of ControlsFX is a big one in all respects! It took just shy of three months, consists of nearly 500 changesets, has been translated into 17 languages, and includes a huge number of bug fixes and new features. This is going to be a long post, so strap yourselves in and please read to the very end – this release has some important changes!

This release also continues in the long tradition of being a real team effort. ControlsFX wouldn’t be where it is today without the hard work of the following contributors: Eugene Ryzhikov, Samir Hadzic, Gabriel Féron, Carolina Veiga, Anirvan Sarkar, IsNull, Artur Biesiadowski, Yair Oren, Davide Nabais, Tom Eugelink, Michał Skowroński, Uwe Sander, Laurent Gebus, Geoffrey Capper, Romain Moreau, Mario Voigt, Ruben Paz, Jonathan Millman, Chen Gaofeng, Ladislav Török, Tiziano Lattisi, Victor Alfonso Pineda Orozco, Daniel Rodrigues, Avramucz István, Sriram Raghuraman, Dirk Lemmermann, Florian Brunner, and Christian Michelsen. Apologies if I missed anyone! As always, if you see these people walking down the street, give them a high-five or a knowing wink, as in to say “You’re a cool person – I appreciate your hard work”.

With that out of the way, lets dive in.

Important Release Note Regarding JavaFX 8u20

Everyone should upgrade to ControlsFX 8.0.6, but especially so if you are running JavaFX 8u20 on your machine. This is because ControlsFX 8.0.6 is the first release to support 8u20. You may be asking yourself why this is necessary – the answer is that ControlsFX uses internal JavaFX API, and this changed between JavaFX 8 and JavaFX 8u20. This is entirely our doing, so is no reflection on JavaFX itself. To support 8u20, we therefore are forced to release two separate releases: ControlsFX 8.0.6 for JavaFX 8.0, and ControlsFX 8.0.6_20 for JavaFX 8u20. I apologise for the extra hassle, but hey, at least ControlsFX works on both, right? :-)

New Features

I should start by saying that this release was largely about consolidating what we had, so most of our focus has been on improving the quality of the release, and slowing down the introduction of new features. This approach will continue in future releases, as I don’t want to let the quality of any release fall below a (very high) threshold. This release was largely focused on decoration and validation. We already have plans for future releases – if you want to know more, it is a good idea to join our google group.

Decoration framework
ControlsFX 8.0.6 introduces a brand new (and at this stage relatively simplistic) decoration framework, to allow for developers to apply decorations to nodes on screen. For example, you may want to show graphics in the corner of your nodes, or add a styleclass in certain circumstances. The decoration framework makes this kind of action trivial. However, to be fair, the decoration framework was primarily developed to be the visual feedback mechanism for a validation framework, and we have one of those in ControlsFX 8.0.6 too (read down a bit further to see screenshots of it in action!).

SnapshotView
The SnapshotView is a control that allows for users to draw a bounding box inside a scenegraph (or typically in an ImageView). This bounding box represents the dimensions of their selection, and from which an image can be created of the selected area. This is another of those controls that is easier to describe with an image, so, see below! :-)

SnapshotView - the 'Controls' section of the image has been selected.

SnapshotView – the ‘Controls’ section of the image has been selected.

 

Translations
We did a big push in ControlsFX 8.0.6 to externalise all translatable strings, and to get the community to help translate these strings into their local languages. I am so pleased to say that the community did an excellent job, resulting in ControlsFX 8.0.6 being translated into 17 languages! Hopefully in future versions we can take that number even higher, but for now we really do have an excellent amount of language coverage.

Validation framework
As mentioned above, we introduced a decoration framework in 8.0.6, primarily to enable the validation framework. The validation framework helps developers to validate user input and assists with reporting errors and warnings. It is designed to be lightweight but extensible, and will grow over time as developers suggest desired functionality (we are definitely open to suggestions!).

Graphic decorations showing how validation failed.

Graphic decorations showing how validation failed.

CSS decorations showing how validation failed.

CSS decorations showing how validation failed.

Other miscellaneous improvements
We can’t list everything (that’s what the hg changelog is for!), but here are some other highlights:

  • The SpreadsheetView continues to be improved – performance is better, functionality is greater, and API is becoming more polished.
  • It is now possible to specify the effect to display when a lightweight dialog is shown (rather than the default gray background).
  • The FXSampler project (which is a standalone project that you can use to demonstrate your own JavaFX stuff!) now has support for custom welcome pages. Very cool!
  • The login dialog shakes (almost mockingly) when you type in the wrong username / password combination.
  • The PopOver control got some useful bug fixes and additional API for hiding PopOver.

Breaking Changes

There is always a tension when working on API between retaining a stable API and continuously improving the API. Believe me, I’ve heard all arguments in my work on JavaFX UI controls! Unlike JavaFX with ControlsFX we are a little more flexible with our backwards compatibility requirements. In other words, I am more than happy to break API to get a better API. This release is by far the biggest release for breaking API, so I want to spend a few moments outlining the major changes, and what you need to do to upgrade to ControlsFX 8.0.6.

Action extends EventHandler<ActionEvent>
Previously the Action interface had an execute(ActionEvent) method, but it seemed pointless to roll our own API when, by extending EventHandler<ActionEvent>, we could directly install an action into, say, the Button.setOnAction(EventHandler<ActionEvent>) method. Unfortunately, EventHandler has a handle(ActionEvent) method, so this means that in all cases where you had Action code, you simply need to rename your execute method to handle.

Dialogs now return Optional
With Java 8 introducing the Optional class, we have updated some of the Dialogs API to return Optional, rather than the object directly.  This means that previously where there was code that looked like the following:

String response = Dialogs.create()
    .title("Name Check")
    .masthead("Please type in your name")
    .message("What is your name?")
    .showTextInput();

if (response != null) {
    System.out.println(response);
}

You now instead need to do the following:

Optional<String> response = Dialogs.create()
    .title("Name Check")
    .masthead("Please type in your name")
    .message("What is your name?")
    .showTextInput();

response.ifPresent(name -> System.out.println(name));

In other words, code that previously checked for null will now no longer work, as the returned Optional will never be null! You need to instead operate on the Optional instead, as shown above.

Getting ControlsFX

As per usual, more details about getting and using ControlsFX can be found on the ControlsFX website. You can also read through a high-level summary of all the features in this release, and peruse the JavaDocs (where we put the bulk of our documentation) if you want the gritty details.

From all the ControlsFX contributors, we hope you enjoy this release, and we hope that you may consider supporting the project in the future!

There is a heap of links this week, and I’m already running late, so lets just jump right into them. Enjoy! :-)

That was the quickest JavaFX links post ever – sorry about the rush, things are a bit manic at the moment! :-) In any case, keep up the great work folks, you’re doing an amazing job.

Another week, and a heap more links! Great work folks, you’re up to all kinds of cool things! :-)

Catch you all next week!