Round and round she goes

JFXtras has a TimePicker that uses a number of Sliders to represent hours, minutes and seconds. And even though this is functionally an OK user interface, it is visually not very appealing.

TimePickerHM

Recently I upgraded to a new phone and ran into this Android TimePicker, which I liked better than my slider UI. So I figured I would try and create something similar.

android-calendar-time-control-1

The first thing that is needed to create a UI like this, is to layout nodes in a circle. That turned out not to be too difficult, but the implementation was very specific for the circular time picker I was working on. And I figured it would be nice if the circular layout was reusable, so I got side-tracked in creating CircularPane.

CircularPane is a standard JavaFX layout implementation that does nothing more or less than position its children in a (partial) circle, like the JavaFX Buttons example below:

CircularPaneButton

Of course any node can be placed in a circular layout, the example below has some (rotated) primitive shapes:

CircularPaneRectanglesAndCircles

As soon as the nodes are getting more diverse, it becomes less clear if they are placed neatly in a circle. To visualize this better, CircularPane has a debug mode, where it will draw (in this case green) circles around the space allocated to each child:

CircularPaneRectanglesAndCirclesDebug

These circles visualize the layout logic; CircularPane searches for the largest node in its children, and uses that as the basis for the layout. The rectangles in the second and third CircularPane are a good example.
As soon as the largest child has been found, it is used to determine the smallest circle where all children can be placed on, assuming each child has the same space available as the largest child.

Besides using a full circle, it is also possible to instruct CircularPane to place its children in a partial circle, or an arc:

CircularPaneCircles200

Of course a larger diameter circle is needed to place these nodes, but the empty space is automatically clipped away.

Often when a circular layout is used, the nodes being laid out are also shaped as a circle. This allows the nodes to be visually easily positioned anywhere on the circle. But this fact allows for an optimization; nodes in JavaFX are rectangular, they have a width and height. A rectangle is the shape that fully uses a node’s available space. Not knowing what exactly is or will be drawn in a node, CircularPane must assume that any node might use all of its space, so the debug circles encompass the rectangle by basing their size on the diagonal. This can clearly be seen in the second example. But the first example shows that for circular nodes room is wasted: even the largest circle has spare room.

CircularPaneRectanglesAndCirclesDebug

So if all children are circular themselves, a more tight layout logic can be used, and the layout can be based on the width or height of the node instead of the diagonal. This is clearly visible in the first example below, where CircularPane was told that its children were all circular (or smaller):

CircularPaneChildrenAreCircles

With the recent popularity of wearable devices and especially Motorola announcing a round smart watch (the Moto 360, see below), a circular layout may just be what the doctor ordered. CircularPane currently is part of JFXtras-labs (8.0-r2) and will eventually move to JFXtras-layout, once all the tests and samples are in place.

LG360

Posted in Java, javafx, jfxtras, UI | 4 Comments

Named queries are evil

The JPA specification has the concept of named queries which is an attempt to ‘Don’t Repeat Yourself’ (DRY), but in my opinion it is more a ‘Mistake By Specification’.

The fact that a query is written as a string, and therefore is not compiler checkable, is a missed chance (solutions like QueryDSL offer great alternatives here), but not the point I would like to make. My issue is with the ‘named’ part.

The link to named queries above has the following example:

@NamedQuery(
    name="findAllEmployeesByFirstName",
    queryString="SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname"
)

What you see here is that there is a definition of a query (usually located at the top of the Entity class) and somewhere else the query is used to read employees from the database, like so:

Query queryEmployeesByFirstName = em.createNamedQuery("findAllEmployeesByFirstName");
queryEmployeeByFirstName.setParameter("firstName", "John");
Collection employees = queryEmployessByFirstName.getResultList();

The problem is that the named query in no way enforces or even specifies the parameters it requires. In this case it requires one, and its name of course suggest that, but this is a very thin and unstable relation, and not something I would like to base the stability of my code upon. After all, we all know how easy the name may go out-of-sync to the contents of the query.

What named queries try to prevent is that the query text is present on multiple locations. But the query and the required parameters are tightly related, basically they are a single unit which should not be split.

Because you need Java code anyhow to execute the JPQL query, I believe it is much better to wrap the query text and the parameters into a single method, where the query parameters are identical to the method parameters.

public Collection<Employees> findAllEmployeesByFirstName(String firstName) {
    Query query = em.createQuery("SELECT OBJECT(emp) FROM Employee emp WHERE emp.firstName = :firstname");
    query.setParameter("firstName", firstName);
    Collection<Employees> employees = (Collection<Employees>)query.getResultList();
    return employees;
}

This puts the query text and the parameters closely together, making it easier to keep them in sync, and (because the query text cannot be reused outside this method) ensuring that any change in the parameters is compiler checkable. It does not really matter if such a finder method is placed in a DAO object, or in a static method on the entity (emulating a named query). What ever suits your taste.

Having argued that named queries are a bad idea, but solely because you need to keep the query and parameters together, could lead to the approach of just scattering queries through out the code, as long as the parameters are there as well. And conceptually this is fine; the premises that ‘the EntityManager is the DAO’ would in fact encourage this. However, there is an additional advantage of moving queries into finder methods; domain level security. Domain level security becomes important when users can have different permissions on different instances of the same class. For example an user in a forum may have edit permissions on his own posts, but he is not allowed to edit posts of another user. And the user also may not be allowed to read post that are part of a shielded forum. Implementing such security, for example using Spring Security – Access Control Lists (ACL), requires checking individual objects. Named queries in their intended use do not have a single place where they are executed -otherwise it would not make much sense using named queries-, and it will be very hard to make sure all query results are processed by the domain level security. But scattering queries all over the place is not very practical either, using DAO classes makes this much easier.

So, to summarize; do not use named queries, they’re evil. But because of future requirements maybe you should not use the EM directly at all and stick to DAO’s.

Posted in Java, JEE, JPA | Leave a comment

The Java 9 named parameter pitch

In the previous post Daan van Berkel again made clear that a fluent API is so much more readable than the “regular” API’s. Unfortunately a lot of projects do not have the luxury of being able to convert their code to the fluent paradigm. But there are some easy improvements possible, one of them would be the introduction of named parameters.

Let me first start with a simple example:

    component.show(false, true);

Well, there is nothing wrong with that code, except as an outsider you have no clue what it is doing exactly. What do the two booleans indicate? This can only be solved by a round trip to the documentation. A fluent API would fix this:

    component.modal(false).centered(true).show();

But a lot of codebases cannot simply be converted to a fluent API, and fluent API’s are not easy to get right in the first place. Some developers improve bad readability by adding inline comments like so:

    show(false /*modal*/, true /*center*/);

That surely improves readability, but it also is very dangerous, because there is no validation that the comments actually match the meaning of the parameters. (Did I just now make an argument against comments, in contrast to my previous blog? Yes I did.) So what actually is needed is something like compiler checked comments; named parameters.

    show(modal:=false, center:=true);

This looks a lot more readable than the first example. What would happen here is that, given that the called method has parameter information available, the compiler would match that against the specified names. If they do not match, or no parameter information is available, named parameters would cause a compiler error. So there cannot be ‘incorrect comments’.

But if the compiler knows what parameters are expected and which are provided, then it can be smart about their sequence: it can rearrange the provided parameters to match the expected. So the compiler can rearrange this call to make it work correctly:

    show(center:=true, modal:=false);

The compiler knows the order of the parameters and at compile time can rearrange them to the correct order, in the end the resulting byte code should still be ‘just’ the old style call:

    component.show(false, true);

This approach is a compiler-only enhancement and perfectly backwards compatible. It improves readability, and allows for changes in the parameter sequence to not cause problems.

A point of attention is when changes are being made to parameters inside a call. In this situation reorder-than-evaluate has different results compared to evaluate-than-reorder. I believe the last is the most natural option, meaning that any expressions are evaluated before the parameters are reordered, so the parameter values match the sequence in the source code. For example assume a method “call(int p1, int p2)”:

    int a = 0;

    // parameters in the correct order:
    object.call(a++, a); // call(0,1)
    object.call(p1:=a++, p2:=a); // call(0,1)

    // changing the order of the parameters:
    object.call(p2:=a, p1:=a++); // call(0,0) evaluate than reorder 
    object.call(p2:=a, p1:=a++); // call(0,1) reorder than evaluate

What you see is that reorder-than-evaluate (4th call) has no influence on the effective method call, while evaluate-than-reorder (3rd call) results in a different call. Changing the order of the parameters should have obvious consequences. So even though the 4th call is identical to the 2nd (changing the order of the parameters at the caller has no effect), this is not the preferred behavior. Changing the order of the parameters at the caller should have obvious consequences; the “a++” happens after p2 has its value assigned, so the 3rd call (evaluate-than-reorder) is the preferred behavior.

A possible issue is the situation where a SNAPSHOT version of a jar contains parameter info, but the actual released jar does not; this would cause compiler errors. But I’d suggest that Java starts including parameter info per default anyhow, I know ctrl-space in IDE’s will greatly benefit from that as well.

Posted in Java | 10 Comments

To comment or not, that is the question

Recently I worked my way through the “Effective Unit Testing” book. A nice read, nothing too complex or difficult, but it is always good to read the opinions of someone who really put some effort into a certain topic. One point was the question if code should contain comments or not, mainly because comments can have a negative impact because they can be incorrect and misleading. So the proposed solution was to write code that does not require comments at all; write “self documenting code”.

In my current project I run into similar situations on a daily basis; my idea on how code should look differs from the most of the other developers. I see people writing tons of code without a single comment in them and declare them “self documenting”. The problem is that for some reason I do not seem to be able to get comfortable with that code, and I’m really starting to wonder if I’m getting old, and am missing out on the “new and improved way” of doing things. But I’m not one to accept that without an effort, so I gave it a shot.

Below is an example of a simple unit test. Please do not spent too much time on this, because it is the “before” example. But the test is ok, there is nothing technically wrong with it, it just can be written better.

    public void testVerifyGroupThenAddClient() throws ValidateException {
        // group starts off not verified
        GroupCare assertGroupCare = groupCareManager.findByObjectId(groupCare.getObjectId());
        assertNull(assertGroupCare.getVerifiedAt());

        // add client
        groupCareManager.addClient(groupCare, client.getData(), groupActivity.getData(), user);

        // group is not yet verified
        assertGroupCare = groupCareManager.findByObjectId(groupCare.getObjectId());
        assertNull(assertGroupCare.getVerifiedAt());

        // verify the group
        groupCareManager.verifyGroupCare(user, groupCare);

        // assert that the group is verified
        assertGroupCare = groupCareManager.findByObjectId(groupCare.getObjectId());
        assertNotNull(assertGroupCare.getVerifiedAt());

        // add new client
        groupCareManager.addClient(groupCare, client2.getData(), groupActivity.getData(), user);

        // group is no longer verified
        assertGroupCare = groupCareManager.findByObjectId(groupCare.getObjectId());
        assertNull(assertGroupCare.getVerifiedAt());
    } 

The next step was to apply the best practices according to the “Effective Unit Testing” book to it, which basically comes down to creating simple methods to be called in the test itself, and extract all scaffolding into helper methods. At first glance you will immediately see the improvement, and it most certainly is an improvement. However, now I want you to actually try and understand the test, actually read the code below. Humor me.

    public void testIfAddingClientToVerifiedGroupMakesItUnverified2() throws ValidateException {

        assertNotVerified(groupCare);

        addClient(groupCare, client, groupActivity, user);
        assertNotVerified(groupCare);

        verify(groupCare, user);
        assertVerified(groupCare);

        addClient(groupCare, client2, groupActivity, user);
        assertNotVerified(groupCare);
    } 

I’m very curious if you really have the feeling you understand what is tested in that code, but more importantly how much time and effort it took for you to understand it.

For me, I had been starting at that code for quite some time and it simply did not sit right. Yes, it is a huge improvement over the “before”, but I am used to write code differently: first write out what you intent to do (create a scenario), and then implement that. The big difference is that a scenario is written in a natural language, and natural languages are much easier to read for humans than computer code. And last time I checked (this morning under the shower) I still am human, and not a compiler.

So after I’d given that code a long stare, I decided it needed comments after all, which resulted in the code below. Again, please, read it and tell me which version is easier to comprehend.

    public void testIfAddingClientToVerifiedGroupMakesItUnverified3() throws ValidateException {

        // group starts off not verified
        assertNotVerified(groupCare);

        // when adding a client to the group, then it should stay not verified
        addClient(groupCare, client, groupActivity, user);
        assertNotVerified(groupCare);

        // when verifying the group, then it should become verified (obviously)
        verify(groupCare, user);
        assertVerified(groupCare);

        // when adding a second client to the group, then it should become not verified again
        addClient(groupCare, client2, groupActivity, user);
        assertNotVerified(groupCare);
    } 

So maybe I really am an old dump not being able to catch on to the latest way of writing code, but at least I confirmed that I’m still human ;-)

Update:
Daan van Berkel has pointed out that using a fluent API both in the domain objects and the test library (Hamcrest) will make the example much more readable. And he is right, fluent API’s are a great improvement, as you can see below. The fact is that my current project does not have a fluent API, and fluent API’s can be really difficult to write correctly. Never the less, is the improved example below “self documenting”? Would you have understood what is tested just as easily as the example with the comments?

    public void testIfAddingClientToVerifiedGroupMakesItUnverified2() throws ValidateException {

        assertThat(groupCare, is(not(verified())));

        groupCare.add(client.with(groupActivity)).as(user);
        assertThat(groupCare, is(not(verified())));

        groupCare.verify().as(user);
        assertThat(groupCare, is(verified()));

        groupCare.add(client2.with(groupActivity)).as(user);
        assertThat(groupCare, is(not(verified())));
    }
Posted in Java, unittest | 6 Comments

FXML builders detection

When you’re in the custom control business, you need hooks into the main framework to get the controls supported well. One of the features of JavaFX is the FXML UI notation format, it allows the coder to define (parts of) a scene with more ease and readability. FXML already is a pretty flexible and open technology, using reflection and the Java Bean standard (aka setters and getters) to try and automatically setup a control according to the values in the FXML file. But there are always situations that don’t fit.

One of those situation is the JFXtras CalendarTextField control and then specifically the date format properties. In the Java API these properties take instances of DateFormat, either a single one, or even a whole list. FXML at the moment does not know how to convert a string to DateFormat. So the dateFormat and dateFormats attributes below result in errors.

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import jfxtras.labs.scene.control.*?>

<VBox xmlns:fx="http://javafx.com/fxml">
    <children>
        <CalendarTextField dateFormat="yyyy-MM-dd HH:mm:ss" dateFormats="yyyy-MM-dd, yyyy-MM, yyyy"/>
    </children>
</VBox>

The FXML parser discovers that there is no setDateFormat(String) in the control, and no build-in converter to convert the String to DateFormat, and consequentially fails. One possible solution would be to add setters that take a string as a parameter to the control, but that not only results in problems because the setter requires an associated getter, which then conflicts with the existing getDateFormat(), but it also pollutes the Java API with stuff needed for FXML. Another approach could extend the control in a special FXML class, adding all FXML stuff there thus keeping the controls API clean, but that still does not solve the property naming / type conflicts. These approaches simply do not lead to nice implementations.

FXML has thought of that and the FXMLLoader supports a BuilderFactory. This builder factory is asked if it knows of a builder to build a certain class. The value strings in the FXML file are then written to the builder instead of the actual control, and then the builder is asked to “build()” the control. This allows to have setters with the correct name, taking string as the parameter and convert them to the appropriate type. For example the builder for CalendarTextField looks like this:

public class CalendarTextFieldBuilder implements Builder<CalendarTextField>
{
	/** DateFormat */
	public String getDateFormat() { return null; } // dummy, just to make it Java Bean compatible
	public void setDateFormat(String value) { iDateFormat = new SimpleDateFormat(value); }
	private SimpleDateFormat iDateFormat = null;

	/** Locale */
	public String getLocale() { return null; } // dummy, just to make it Java Bean compatible
	public void setLocale(String value) { iLocale = Locale.forLanguageTag(value); }
	private Locale iLocale = null;

	/** PromptText */
	public String getPromptText() { return null; } // dummy, just to make it Java Bean compatible
	public void setPromptText(String value) { iPromptText = value; }
	private String iPromptText = null;

	/** DateFormats */
	public String getDateFormats() { return null; } // dummy, just to make it Java Bean compatible
	public void setDateFormats(String value) 
	{  
		String[] lParts = value.split(",");
		iDateFormats = FXCollections.observableArrayList();
		for (String lPart : lParts) 
		{
			iDateFormats.add( new SimpleDateFormat(lPart.trim()) );
		}
	}
	private ObservableList<DateFormat> iDateFormats = null;

	/**
	 * Implementation of Builder interface
	 */
	@Override
	public CalendarTextField build()
	{
		CalendarTextField lCalendarTextField = new CalendarTextField();
		if (iDateFormat != null) lCalendarTextField.setDateFormat(iDateFormat);
		if (iLocale != null) lCalendarTextField.setLocale(iLocale);
		if (iPromptText != null) lCalendarTextField.setPromptText(iPromptText);
		if (iDateFormats != null) lCalendarTextField.setDateFormats(iDateFormats);
		return lCalendarTextField;
	}
}

Now, this is all nice and well, but if you write a custom builder like the one above, you need to inform the BuilderFactory that it exists. The default JavaFXBuilderFactory can’t do that, it just knows how to build the build-in types, but you can’t register custom builders. One workaround is to write your own BuilderFactory implementation and wrap the default builder factory, like so:

public class CustomBuilderFactory implements BuilderFactory {

    private BuilderFactory baseFactory;

    public CustomBuilderFactory() {
        baseFactory = new JavaFXBuilderFactory();
    }

    @Override
    public Builder<?> getBuilder(Class<?> aClass) {
        if (CalendarTextField.class.equals(aClass)) {
            return new CalendarTextFieldBuilder();
        } else {
            return baseFactory.getBuilder(aClass);
        }
    }
}

This will work, but it can become tedious if you start using multiple jars files containing controls; you need to add code for each control, you need to know how the builder class is called, and new releases may have new controls that are not adopted automatically. It simply is not an elegant solution. But do no despair, Java has a elegant solution readily available: ServiceLoader.

The specifics can be found in the Javadoc, but in essence it comes down to that you can define an interface, and then specify in the META-INF directory which implementations of that interface a jar file provides, these implementations are then automatically detected. JFXtraBuilderFactory uses this technique to automatically detect all builders that are available on the classpath.

So, these are the steps to take:

  1. Implement the jfxtras.fxml.BuilderService interface instead of the javafx.util.Builder interface on all builder implementations. (BuilderService extends the Builder interface and adds one additional method.)
  2. Create a file in your project / jar called “META-INF/services/jfxtras.fxml.BuilderService”
  3. In that file specify the full class name of all builders that you want to make auto-discoverable, each on a single line.
  4. Use the JFXtraBuilderFactory instead of the default, like so: FXMLLoader.load(url, null, new JFXtrasBuilderFactory());

So, this is what needs to be changed to the CalendarTextFieldBuilder file:

public class CalendarTextFieldBuilder implements BuilderService<CalendarTextField>
{
	...

	/**
	 * Implementation of BuilderService interface
	 */
	@Override
	public boolean isBuilderFor(Class<?> clazz)
	{
		return CalendarTextField.class.isAssignableFrom(clazz);
	}
}

And then the file “META-INF/services/jfxtras.fxml.BuilderService” must be created with one line in it:

jfxtras.labs.fxml.CalendarTextFieldBuilder

Done!

Posted in Java, javafx, jfxtras, UI | 2 Comments

Using CSS in JavaFX to keep the API clean

As a notorious skeptic, the usage of CSS for styling in JavaFX to me was something of a “yeah, nice, but we’ll see how it works out.”. There are some doubts in how CSS will work out when complete skins (like Synthetica for Swing) are created, in combination with third party controls. But last week I had a situation that won me over to the “it’s good” side.

A user of one of my controls, CalendarPicker in JFXtras, came to me and told me about their usage of the control. They had integrated it in their application and styled it Windows 8 alike using CSS. But, he said, our graphical designer wants the arrows of the month and year selector to be on either side of the value, and the value centered instead of left aligned. Shown below is the default UI for CalendarPicker and as you can see, it is not as the designer wants:

calendarpicker_usa

The CalendarPicker control is composed of many other controls; there are Labels and ToggleButtons (for the days), and on top are two ListSpinners (also a JFXtras control). ListSpinner is actually the first control I’ve written for JavaFX 2, a pretty long time ago already, and it already has the properties the designer needs in its API; arrow position, direction and value positioning. Some of their effects are shown below.

ListSpinner_styleable

But since the ListSpinner controls are nested in the CalendarPicker, these properties are not available on the API of CalendarPicker. The only Java way of allowing the user to control these properties, is by exposing them in CalendarPicker’s API, and forwarding it to the ListSpinners. So on CalendarPicker there would be properties like:

  • yearSpinnerArrowDirection
  • yearSpinnerArrowPosition
  • yearSpinnerValueAlignment
  • monthSpinnerArrowDirection
  • monthSpinnerArrowPosition
  • monthSpinnerValueAlignement

These methods are of course terrible if you consider that JavaFX tries to hide the actual visualization of a control, in order to keep its Java API clean. And even worse: these properties would be totally meaningless if the CalendarPicker would use a iPhone alike presentation (drums selectors), if it ever gets to run on touch devices.

So this request actually put focus on an existing API design flaw; these properties in ListSpinner’s API are inappropriate, ListSpinner may have different skins, who may not use arrows at all. So these properties should not be in the control’s API.

Styleable properties to the rescue! Styleable properties can be set using CSS, without exposing them via the Java API. That means that the properties can be removed from the ListSpinner control and moved into the skin, but also that they still can be set even if the control is embedded in another control. The idea is to introduce three properties like so:

.CalendarPicker .ListSpinner {
	-fxx-arrow-position:SPLIT;
	-fxx-arrow-DIRECTION:HORIZONTAL;
	-fxx-value-alignment:CENTER;
}

As shown above, these properties are available on ListSpinner and by using the CSS selectors the ListSpinners inside the CalendarPicker can easily be addressed.

Using styleable properties requires three steps:

  1. Create a styleable property.
  2. Create a binding record (called CssMetaData) to bind the CSS id to the property.
  3. Make the CSS engine aware of these properties.

Step 1: create a styleable property (JavaFX 2.2)
The first step is to create a StyleableProperty, there are a number of predefined types, but for our properties an Object version is needed, since we will be using enums.

public ObjectProperty<ArrowPosition> arrowPositionProperty() { 
	return this.arrowPositionObjectProperty; 
}
final private StyleableObjectProperty<ArrowPosition> arrowPositionObjectProperty = new StyleableObjectProperty<ArrowPosition>(ArrowPosition.TRAILING) {

	@Override
	public StyleableProperty<ListSpinnerCaspianSkin,ArrowPosition> getStyleableProperty() {
		return ARROW_POSITION;
	}

	@Override
	public Object getBean() {
		return ListSpinnerCaspianSkin.this;
	}

	@Override
	public String getName() {
		return "arrowPosition";
	}

	@Override public void invalidated() {
		// code here for reacting to changes
	}
};			
public ArrowPosition getArrowPosition() { 
	return this.arrowPositionObjectProperty.getValue(); 
}
public void setArrowPosition(ArrowPosition value) { 
	this.arrowPositionObjectProperty.setValue(value); 
}
public ListSpinnerCaspianSkin<T> withArrowPosition(ArrowPosition value) { 
	setArrowPosition(value); 
	return this; 
}
public enum ArrowPosition {LEADING, TRAILING, SPLIT}	

Note the use of a special styleable property implementation, which does not have the same constructors as normal properties, therefor a number of methods must be overridden.

Step 2: create a CssMetaData record (JavaFX 2.2)

This is actually the most important part; here the identifier in CSS is connected to the property, and the way the CSS value string is converted to the property is defined. JavaFX offers a handy EnumConverter to do this for us.

private static final StyleableProperty<ListSpinnerCaspianSkin,ArrowPosition> ARROW_POSITION 
	= new StyleableProperty<ListSpinnerCaspianSkin,ArrowPosition>(
		"-fxx-arrow-position", 
		new EnumConverter<ArrowPosition>(ArrowPosition.class), 
		ArrowPosition.TRAILING) {

	@Override
	public boolean isSettable(ListSpinnerCaspianSkin owner) {
		return !owner.arrowPositionObjectProperty.isBound();
	}

	@Override
	public WritableValue<ArrowPosition> getWritableValue(ListSpinnerCaspianSkin owner) {
		return owner.arrowPositionProperty();
	}
};

Step 3: make the CSS engine aware of the properties (JavaFX 2.2)

In JavaFX 2.2 the overriding of an internal and deprecated method is required, it comes down to getting the list of styleable properties from the parent, adding our own and returning that list.

@Override @Deprecated
public List<StyleableProperty> impl_getStyleableProperties() {
	if (STYLEABLES == null) {
		final List<StyleableProperty> styleables = new ArrayList<StyleableProperty>(super.impl_getStyleableProperties());
		Collections.addAll(styleables, ARROW_POSITION, ARROW_DIRECTION, VALUE_ALIGNMENT);
		STYLEABLES = Collections.unmodifiableList(styleables);
	}
	return STYLEABLES;
}
private static List<StyleableProperty> STYLEABLES;

So far JavaFX 2.2. In JavaFX 8.0 similar steps are needed, but beside the API now being public, there are some other changes.

Step 1: create a styleable property (JavaFX 8.0)

This is part is identical to the 2.2 code, except that classes are in different packages. This specific implementation uses lazy loading of the property, meaning the getter will return a default hard coded value until someone actually accesses the property.

public final ObjectProperty<ArrowPosition> arrowPositionProperty() {
	if (arrowPosition == null) {
		arrowPosition = new StyleableObjectProperty<ArrowPosition>(ArrowPosition.TRAILING) {

			@Override public CssMetaData<ListSpinner,ArrowPosition> getCssMetaData() { 
				return StyleableProperties.ARROW_POSITION; 
			}
			@Override public Object getBean() { 
				return ListSpinnerCaspianSkin.this; 
			}
			@Override public String getName() { 
				return "arrowPosition"; 
			}
			@Override public void invalidated() {
				// code here for reacting to changes
			}
		};
	}
	return arrowPosition;
}
private ObjectProperty<ArrowPosition> arrowPosition = null;
public final void setArrowPosition(ArrowPosition value) { 
	arrowPositionProperty().set(value); 
}
public final ArrowPosition getArrowPosition() { 
	return arrowPosition == null ? ArrowPosition.TRAILING : arrowPosition.get(); 
}
public final ListSpinnerCaspianSkin<T> withArrowPosition(ArrowPosition value) { 
	setArrowPosition(value); 
	return this; 
}
public enum ArrowPosition {LEADING, TRAILING, SPLIT}

Step 2: create a CssMetaData record (JavaFX 8.0)

One important change is that it is no longer allowed to define styleable properties on skins, because skins no longer implement the Styleable interface. This of course is strange, since it seems very natural to me that properties intended for visualization are defined in a skin and not in the control. After all, there is no guarantee that all skins use the same visual elements, for example the arrows we’re styling in this blog post do not exist in the drum skin of iOS date picker. Luckily there is an acceptable solution: define the styleable properties in the skin, but let them pretend to be in the control. This involves casting the skin of the control, but because the casting happens in the skin itself, it is ok; apparently that skin is being used by the control.

private static class StyleableProperties {
	private static final CssMetaData<ListSpinner, ArrowPosition> ARROW_POSITION 
		= new CssMetaData<ListSpinner, ArrowPosition>("-fxx-arrow-position", 
			new EnumConverter<ArrowPosition>(ArrowPosition.class), 
			ArrowPosition.TRAILING ) {

		@Override public boolean isSettable(ListSpinner n) { 
			return !((ListSpinnerCaspianSkin)n.getSkin()).arrowPositionProperty().isBound(); 
		}
		@Override public StyleableProperty<ArrowPosition> getStyleableProperty(ListSpinner n) { 
			return (StyleableProperty<ArrowPosition>)((ListSpinnerCaspianSkin)n.getSkin()).arrowPositionProperty(); 
		}
	};
            
	// more CssMetaData definitions here 
            
	private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
	static {
		final List<CssMetaData<? extends Styleable, ?>> styleables = new ArrayList<CssMetaData<? extends Styleable, ?>>(SkinBase.getClassCssMetaData());
		styleables.add(ARROW_POSITION);
		styleables.add(ARROW_DIRECTION);
		styleables.add(VALUE_ALIGNMENT);
		STYLEABLES = Collections.unmodifiableList(styleables);                
	}
}

Step 3: make the CSS engine aware of the properties (JavaFX 8.0)

The way the CssMetaData classes are made available to the CSS engine has changed, no longer overriding an internal method.

/** 
 * @return The CssMetaData associated with this class, which may include the
 * CssMetaData of its super classes.
 */    
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
	return StyleableProperties.STYLEABLES;
}

/**
 * This method should delegate to {@link Node#getClassCssMetaData()} so that
 * a Node's CssMetaData can be accessed without the need for reflection.
 * @return The CssMetaData associated with this node, which may include the
 * CssMetaData of its super classes.
 */
public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
	return getClassCssMetaData();
}

So, does it work?
Well, yes, it does…

CalendarPicker_CSS

Some final thoughts…

  • First, I really like this way of being able to style controls, doing this the old fashion way via Java API would have been highly upsetting.
  • The fact that styleable properties in 8.0 are not possible on skins anymore seems wrong. The workaround is more than acceptable though, so this is not really an issue.
  • Looking at the code, I wonder why there are separate StyleableXXXProperties classes. It seems to me all the CSS integration information is present in the CssMetaData class, so can’t we just use normal properties and call their setter?
Posted in Java, javafx, UI | 12 Comments

Supporting JSR310 (Jodatime) in JFXtras

Probably everyone is exited that Oracle is finally picking up the highly dubious date time implementation in Java called Calendar. It is interesting to see that large companies like Sun really have problems getting something as seemingly simple as date and time implemented correctly. Of course there are two sides to the problem, first there are all the intricacies of date and time, like time zones and other more or less subtle problems (this is where Date went wrong). And secondly there is the implementation aspect, where for 99% of the usages a date or time is considered an immutable value, like a number, easy to use for a developer (this is where Calendar went wrong, just take a look at the output of toString()).

Now, there are reasons why there is a CalendarPicker and not a DatePicker in JFXtras. And the primary reason is that Calendar has a notion of locality, which Date has not; for example in Germany the week starts on a different day (Monday) than in the USA (Sunday).

calendarpicker_usa

calendarpicker_de

Calendar actually is a good implementation when it comes to the domain of dates and times, Jodatime is added to Java 8 is because the implementation, the API, is bad.

Jodatime takes a little getting used to API wise, using methods like “plusDays” which feels domain-driven style and deviates from what a Java developer would expect IMHO, but it definitely is a big improvement for the developer. And Oracle is smart to use a mature and proven open source library as part of JSR310, instead of trying to reinvent the wheel itself. I hope Oracle will stick to this approach and simply standardize what is proven to work (*cough* layout *cough*).

Anyhow, when people started to ask if there would be a LocaleDateTimePicker in JFXtras a choice had to be made.

  1. Create a two totally separate controls.
  2. Implement one control and use it in the other.
  3. Extend one control and add the missing logic.

For the initial implementation I went for approach 1, it also was a great way to get to learn Jodatime better; so I copied over the CalendarPicker java files, and converted them. It turned out that after replacing all Calendar references with LocalDateTime, all I had to change were a few supporting methods that contain the Locale related code. In essence 90% of the code stayed the same. This approach would leave me with two almost identical implementations to support, and I had not even started on the other Calendar controls.

Considering the second approach also had some drawbacks. The controls contain more than just a Calendar value; they also have callbacks and other properties, and each property needs to be duplicated into the new control and bound to the encapsulated control. This again results in duplicate code, but way less than in approach 1. I think this approach is conceptually the best, but the CalendarPicker is still under active development (it’s in JFXtras labs after all), and I regularly add some functionality to support a certain use case.¬†Also lately my time is very limited with all kinds of money earning related stuff.

So when the latest functional addition to the calendar controls came along, I decided for option 3; let the JSR310 controls extend the calendar controls and add a LocalDateTime property. In controls of about 100 lines, I can add support for JSR310, and any improvements are picked up automatically. The only drawback is the fact that the JSR310 controls have a calendar property, but I figure that is a small price to pay (for now). Developers simply should not use that property, because in the future -when things have stabled out-, the calendar properties will be removed. But at the moment it allows for easy migration; the JSR310 controls are drop-in replacements for the calendar controls, and the user can slowly change his code to use the new date API.

So please take a peek at:

And let me know if they work out for you.

Posted in Java, javafx, jfxtras, UI | 2 Comments