Announcing ControlsFX 8.0.6

Announcing ControlsFX 8.0.6

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!

JavaFX links of the week, May 26

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.

JavaFX links of the week, May 19

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

Catch you all next week!

Resizable Grid using Canvas

Resizable Grid using Canvas

I was hacking on a application today and wanted a dot grid in the background. Canvas is well suited to this as you don’t need 1000s of nodes for every dot on the grid. Canvas by default has a fixed size so I wrapped it in a Pane to make it Resizable. I thought this might be a generally useful example to show how to create a resizable canvas node. Also if you ever need a grid, it could be applied to a normal line grid just as easily. So here is a little test app with a single node of my DotGrid.

 

Dot Gird Test App
Test Application

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
* Test app for DotGrid
*/
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

/**
 * Test app for DotGrid
 */
public class DotGridTestApp extends Application {

    @Override public void start(Stage stage) throws Exception {
        stage.setScene(new Scene(new DotGrid(), Color.WHITE));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Dot Grid Class


import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;

/**
 * A node that draws a triangle grid of dots using canvas
 */
public class DotGrid extends Pane {
    private static final double SPACING_X = 25;
    private static final double SPACING_Y = 20;
    private static final double RADIUS = 1.5;
    private Canvas canvas = new Canvas();

    public DotGrid() {
        getChildren().add(canvas);
    }

    @Override protected void layoutChildren() {
        final int top = (int)snappedTopInset();
        final int right = (int)snappedRightInset();
        final int bottom = (int)snappedBottomInset();
        final int left = (int)snappedLeftInset();
        final int w = (int)getWidth() - left - right;
        final int h = (int)getHeight() - top - bottom;
        canvas.setLayoutX(left);
        canvas.setLayoutY(top);
        if (w != canvas.getWidth() || h != canvas.getHeight()) {
            canvas.setWidth(w);
            canvas.setHeight(h);
            GraphicsContext g = canvas.getGraphicsContext2D();
            g.clearRect(0, 0, w, h);
            g.setFill(Color.gray(0,0.2));

            for (int x = 0; x < w; x += SPACING_X) {
                for (int y = 0; y < h; y += SPACING_Y) {
                    double offsetY = (y%(2*SPACING_Y)) == 0 ? SPACING_X /2 : 0;
                    g.fillOval(x-RADIUS+offsetY,y-RADIUS,RADIUS+RADIUS,RADIUS+RADIUS);
                }
            }
        }
    }
}

There really is not much too it, when the layout is applied to Pane check if size has changed and redraw the canvas. There are a couple of optimizations you could do here if performance was a issue.

  • When the Pane gets bigger don’t clear, just draw any new dots needed. If you were animating the size growing then this might be a good win.
  • Draw the dot once into a WritableImage using another Canvas or Circle node and snapshot(). Then draw that image for each dot. That way turn out to be a performance win, but maybe not. If you had more complex dots, like company logos then this would probably be a good gain.

In this case I have not set any preferred size for the DotGrid so it will be whatever size its parent wants it to be. If you need it to be a minimum size you could call setPrefSize() or setMinSize() in the constructor.

Announcing SceneBuilder 2.0

Announcing SceneBuilder 2.0

Amazing news everyone, SceneBuilder 2.0 is released today. It has many cool new features and was a complete rewrite from the ground up so that it can be split into parts and embedded in your favorite IDE.

Download

Mo has put up a great video tutorial for SceneBuilder 2 on YouTube: Watch

Scene Builder 2

Whats New

  • JavaFX Scene Builder Kit. JavaFX Scene Builder Kit is an API that allows the integration of Scene Builder panels and functionalities directly into the GUI of a larger application, or a Java IDE, such as NetBeans, IntelliJ, and Eclipse. See Working with the JavaFX Scene Builder Kit for more details.
  • Ability to add custom GUI components to the Library. Custom components imported from a third party JAR file can now be added permanently to the Library of available GUI components. See Adding Custom Components to the Library for more information.
  • Support for new JavaFX 8 UI components. The new UI components, TreeTableView, DatePicker, and SwingNode, that were introduced in the Java SE 8 are now supported in Scene Builder 2.0. To see the list of JavaFX 8 UI components that are available, type FX8 in the Library panel’s search text field.
  • 3D Support. FXML documents containing 3D objects can now be loaded and saved in the Scene Builder tool. You can view and edit properties of the 3D objects using the Inspector panel. You can not, however, create new 3D objects using the Scene Builder tool. See JavaFX Scene Builder User Guide for more information.
  • Support for Rich Text. A new container, TextFlow, is now available in the Library of GUI components. You can drag multiple text nodes and other types of nodes, into the a TextFlow container. You can also directly manipulate the text nodes to re-arrange them in the container. Inline and property editing features are also available for each text node.
  • Library Panel Improvements. The default viewing option for the Library panel is a new feature that gives you the option to view all the component categories as collapsible sections.
  • Hierarchy Panel Improvements. It is now more flexible to re-parent objects from one container to another container. It is also possible to drag and drop an object from the Hierarchy Panel to the Content Panel, and vice versa. You can also now select multiple objects in the Hierarchy Panel in order to re-parent them.
  • Content Panel Improvements. You can now manipulate the components of an HBox, VBox, FlowPane, or Toolbar container directly in the Content Panel to re-order them. You can also insert a new component at any position in the container. Note that this direct manipulation is currently not available for the TilePane container.
  • Inspector Panel Improvements. Many property editors in the Inspector panel use the Suggested List dialog window, which displays a list of selectable values from which you can make a selection instead of manually entering them. For example, the CSS Style editor provides a list of applicable CSS properties, based on the currently selected object(s). List handling has also been simplified. Multi-selection of components of different types (i.e. Button + TextField) is now supported. In addition, the usability of many of the property editors, such as AnchorPane Constraints, Rotate, and Padding, have been improved.
  • Preview Window Improvements. The content in the Preview window is now automatically refreshed as the current FXML document is being edited. Hence, there’s no need to use the Refresh command in order to preview the modified UI layout.
  • Change in the Include FXML Command. When you click File from the Menu bar and then click Include, you can only select the FXML menu item if the current FXML document you are editing is saved on your system’s disk and is not empty.