e(fx)clipse has been released on June 6th but because of the high load of JavaFX projects we are working on I did not have time to write the public release announcement.
In total we have worked on ~100 tickets most of them adding new features. We also moved our dev infrastructure to github.com and while doing that we’ve split the project into 2 repositories:
- efxclipse-rt: Contains the runtime library
- efxclipse-eclipse: Contains the Eclipse Tooling
We believe that moving to github and the upcoming pure maven-build-story we currently work on in an extra branch will make it easier for others to consume our libraries in none OSGi/Eclipse/e4-Projects.
While we are switching our project structure to pure maven you can already consume our libraries from a maven-repository we host ourselves (see http://maven.bestsolution.at/)
Let’s take a short tour through some of the 3.0 highlights.
Support for Java 9
3.0 is the first release who is fully compatible with Java9 and JPMS. Historically we used non-public APIs and even used reflection to eg “hack” DnD in TabFolder. All code that would be broken in Java9 has been reworked to run on Java8 and Java9.
Some of the none public APIs we used in Java8 have been promoted to public API in Java9 and to support both Java 8 and 9 in the same codebase we extracted those into utility class org.eclipse.fx.ui.controls.JavaFXCompatUtil
:
Java 8 | Java 9 | JavaFXCompatUtil |
---|---|---|
Window#impl_getWindows() | Window#getWindows() | getAllWindows() |
KeyCode#impl_getChar() | KeyCode#getChar() | getChar(KeyCode) |
KeyCode#impl_getCode() | KeyCode#getCode() | getCode(KeyCode) |
Utilities to work with JavaFX Properties
FXBindings
JavaFX has a Bindings
class to setup bindings between different Observable
s but we missed some features we frequently need in our application code hence we added an org.eclipse.fx.core.bindings.FXBindings
who eg has:
tenaryBinding(ObservableBooleanValue, ObservableValue<T>, ObservableValue<T>) : Binding<T>
allowing you to defined if-else in a JavaFX binding wayconcat(ObservableList<? extends A>...) : ListBinding<A>
to concat the lists to one and keep the target updated when one of the source lists changeconcat(String, ObservableValue<T>...) : StringBinding
concat the lists and concat the items with the given delimiter and keep the binding updatedbindContent(List<T>, ObservableList<E>, Function<E, T>) : Subscription
similar to Bindings.bindContent but allows to use a converter function
A very special feature is a BindingStream
you can create with bindStream(ObservableValue<T>)
who is similar to Bindings.select
but is:
- Typesafe
- Provide a Property as the leaf
Let’s look at a concrete example.
class Person { public ObjectProperty<Address> address(); } class Address { public StringProperty street() { /* ... */ } } class UI { ObjectProperty<Person> currentPerson = /* ... */; TextField street; bindUI() { street.textProperty().bindBidirectional( FXBindings.bindStream( currentPerson ) .map( Person::address ) .collect( FXCollectors.toProperty( Address::street ) ) ); } }
@ContextValue improvements
@ContextValue
is IMHO one of the coolest concepts we introduced in e(fx)clipse to make reuseable components. In 3.0 we added a scope
-Property who allows you to fix a publishing scope.
As of 3.0 we support:
APPLICATION
: Publish the value in the IEclipseContext of the applicationLOCAL
: Publish the value in the local IEclipseContextDYNAMIC
: Publish the value using IEclipsContext#modify and the application container is responsible to mark the target context
with DYNAMIC
as the default.
ThreadSynchronize improvements
Halt program flow
We added a new API to halt the program flow (NOT the event loop) like this:
ThreadSynchronize t = ...; TextField username = new TextField(); BlockCondition<String> w = new BlockCondition<>(); username.setOnAction( e -> w.release( username.getText() ) ); System.out.println(t.block( w ));
Headless implementation
We at BestSolution use the MVVM-Pattern for our JavaFX applications and there we fetch data from backend-services in none-ui-threads and so we need to synchronize from a Background- to the UI-thread using ThreadSynchronize.
While things work perfectly fine in the real application because the JavaFX Framework is up and running things fall apart when you test your ViewModel in a headless JUnit-Tests. For that purpose there’s now the possibility to create a ThreadSynchronize
instance like this:
ThreadSynchronize t = ThreadSynchronize.createBasicThreadSyncronize( new EventLoop() );
Pingback: JavaFX links of the week, August 7 | JavaFX News, Demos and Insight // FX Experience