e(fx)clipse 2.4.0 & Eclipse Neon Builds available

For those who want to get an easy head start into JavaFX development with Eclipse as an IDE BestSolution provides a service many developers make use of (eg in June the IDE got downloaded 4000 times).

We provide All-in-One builds similar to the ones you can grab from Eclipse.org but we bundle even some external libraries for you with it.

We now managed to update the provided IDE to the latest and greatest:

  • Eclipse 4.6.0 SDK
  • e(fx)clipse 2.4.0
  • Xtext 2.10.0
  • EGit 4.4.0
  • WST-XML 3.8.0
  • Subclipse 1.8.20
  • m2e 1.7.0
  • bndtools 3.2.0
  • AnyEditTools 2.6.1
  • Findbugs 3.0.2
  • Eclemma 2.3.3

Finally if you like this an other services (eg. leaving no question at the newsgroup unanswered) BestSolution provides for free think about sponsoring our work.

If you rely on e(fx)clipse for your commercial product we suggest you sign a service and support contract with BestSolution.

e(fx)clipse 2.4.0 released

we are happy to announce that e(fx)clipse 2.4.0 has been released last week. The main working area in this release has once more been the code editor framework.

Code editor framework

Starting with this release we are have replacement for all features one is used from your Eclipse IDE Code-Editing framework, like keyboard navigation, hover-information, … .

We’ve as always taken extra care that we are not introduce JavaFX dependencies but kept a clean split between core-services providing the plain data and visualization services presenting those plain data points (eg in JavaFX).

  • Lexical-Code-Highlighting improvements:
    • Our custom rules have been adjusted to match the highlighting behavior known from the Eclipse Java-Editor.
      Old

      New

    • New rules to eg support lua multi-line string and comments. I confess I’ve not seen a language before who has a similar concept for multi-line constructs. If you are not familiar with lua let me try to explain it. A multi-line comment starts with --[ followed by an optional number of "="-chars followed by another "[" and then ends with "]" the same amount of "="-chars than you used in the start section followed by another "]"
      --[==[
      I'm a multi line
      comment
      ]==]
      
      lua-code
      
      --[====[
      I'm a multi line
      comment
      ]====]
      

      We have enhanced our highlighting format to support this kind of rules. For lua it looks like this:

      // ...
      rule {
        multi_line __lua_ml_comment   "--[" pattern '(=*)' '['   => "]{0}]"
        single_line __lua_sl_comment  "--"  => ''
        multi_line __lua_ml_string    "["  pattern '(=*)' '['   => "]{0}]"
        single_line __lua_string      "'"   => "'" escaped by "\\"
        single_line __lua_string      '"'   => '"' escaped by "\\"
      }
      // ...
      
    • While the ldef-language allows to specify rules very easy those rules have to be defined up-front which sometimes is not possible to the highlighting needs to adapt based on other conditions. We enhanced the system to contribute rules dynamically by registering a service of type DynamicScannerRuleCalculator
  • Autocomplete improvments: You can now configure the editor to invoke auto-complete system not only on CTRL+Space but as well eg at the moment you type "."-character
  • Code navigation support: This release introduces code navigation like you know it from your Eclipse IDE (including low-level APIs to jump to positions inside your editor control)
  • Support for block matching: We implemented exemplary code to show how one can implement block matching (eg matching braces)
  • Code rearrangement with DnD: We now have support to rearrange code parts using DnD
  • Support for undo/redo: We’ve now connected the editor to the undo/redo system available in eclipse.text

e4 on JavaFX

Prebuilt Perspective Switchers

The framework now provides:

  • A perspective switcher control one can embed into the TrimBar (PerspectiveSwitcherComponent)
  • A heavy and a lightweight perspective switcher dialog and a handler to trigger the dialog the appropriate one

New tag to center MWindow

You can now add the tag "efx-center-on-screen" to your Application.e4xmi and the window will be centered on screen.

Tab-Context-Menu

One can now register MPopupMenu on an MPart who is translated into a context-menu assigned to the Tab in a TabPane. Just taq the MPopupMenu with "tabmenu" and e4 on JavaFX will take care for you to render the context menu.

Other new runtime APIs

TextUtil#templateValuSubstitutor(String,Map)

This new helper allows you to evaluate simple template expressions and applying formats on it.

class Person {
   String name = "Tom";
   Date birthday = new Date(1,4,79);
}

Person p = new Person();
TextUtil.templateValuSubstitutor( 
  "The birthday from ${p.name} is on ${p.birthday,date,short}", Collections.singletonMap("p",p) );

ImageProvider support HiDPI images

JavaFX itself supports HiDPI images already since sometime but the internal abstraction who is used by e4 on JavaFX lacked such a support. This has been fixed with this release.

Delayed observables

To appropriately support undo/redo in form based UIs it is very important to collect changes in logical units. A good example is the that you probably would not require the user to undo each and every keystroke in a text-field. To address this use case Eclipse Databinding for SWT has the concept of so called delayed observables who wait for a certain amount of time before they inform others about their modification.

Eclipse Databinding for JavaFX controls now has the same concept.

TextField f = new TextField();
IObservableValue textObs = JavaFXUIProperties.text2().observeDelayed(400, f);

Error-Decoration

For form base UIs it is crucial to display validation information. We added new API to our control-library to who supports field decorations. The API is designed to work equally well in a basic scenario as well as when using MVVM (in the same vein we added new properties you can publish in your ViewModels)

static class VM {
  private final ValidatedStringProperty firstname;
  private final ValidatedStringProperty lastname;
  private final StatusAggregator aggregator;

  public VM(String firstname, String lastname) {
    this.firstname = new ValidatedSimpleStringProperty(new SimpleStringProperty(this, "firstname",firstname));
    this.firstname.registerValidator(s -> s.isEmpty() ? Status.status(State.ERROR, -1, "Vorname muß befüllt sein", null) : Status.ok());

    this.lastname = new ValidatedSimpleStringProperty(new SimpleStringProperty(this, "lastname", lastname));
    this.lastname.registerValidator(s -> s.isEmpty() ? Status.status(State.ERROR, -1, "Nachname muß befüllt sein", null) : Status.ok());

    this.aggregator = new StatusAggregator(this.firstname,this.lastname);
  }
}

VM vm = new VM("Tom", "Schindl");

{
  Label l = new Label("Vorname");
  p.getChildren().add(l);

  TextField field = new TextField();
  field.textProperty().bindBidirectional(vm.firstname.bindProperty());

  NodeDecorator.apply(field, vm.firstname);
  p.getChildren().add(field);
}

Using TypeScript LanguageService to build an JS/TypeScript IDE in Java

Yesterday I blogged about my endeavors into loading and using the TypeScript Language Service (V8 and Nashorn) and calling it from Java to get things like an outline, auto-completions, … .

Today I connected these headless pieces to my JavaFX-Editor-Framework. The result can be seen in the video below.

To get the TypeScript LanguageService feeling responsible not only for TypeScript files but also for JavaScript I used the 1.8 beta.

As you notice JS-Support is not yet really at a stage where it can replace eg Tern but I guess things are going to improve in future.

JavaScript Performance V8 vs Nashorn (for Typescript Language Service)

On the weekend I’ve worked on my API to interface with the Typescript language service from my Java code.

While the initial version I developed some months ago used the “tsserver” to communicate with the LanguageService I decided to rewrite that and to interface with the service directly (in memory or through an extra process).

For the in memory version I implemented 2 possible ways to load the JavaScript sources and call them

  • Nashorn
  • V8(with the help of j2v8)

I expected that Nashorn is slower than V8 already but after having implemented a small (none scientific) performance sample the numbers show that Nashorn is between 2 and 4 times slower than V8 (there’s only one call faster in Nashorn).

The sample code looks like this:

public static void main(String[] args) {
  try {
    System.err.println("V8");
    System.err.println("============");
    executeTests(timeit("Boostrap", () -> new V8Dispatcher()));
    System.err.println();
    System.err.println("Nashorn");
    System.err.println("============");
    executeTests(timeit("Nashorn", () -> new NashornDispatcher()));
  } catch (Throwable e) {
    e.printStackTrace();
  }
}

private static void executeTests(Dispatcher dispatcher) throws Exception {
  timeit("Project", () -> dispatcher.sendSingleValueRequest(
    "LanguageService", "createProject", String.class, "MyProject").get());

  timeit("File", () -> dispatcher.sendSingleValueRequest(
    "LanguageService", "addFile", String.class, "p_0", DispatcherPerformance.class.getResource("sample.ts")).get());

  timeit("File", () -> dispatcher.sendSingleValueRequest(
    "LanguageService", "addFile", String.class, "p_0", DispatcherPerformance.class.getResource("sample2.ts")).get());

  timeit("Outline", () -> dispatcher.sendMultiValueRequest(
    "LanguageService", "getNavigationBarItems", NavigationBarItemPojo.class, "p_0", "f_0").get());

  timeit("Outline", () -> dispatcher.sendMultiValueRequest(
    "LanguageService", "getNavigationBarItems", NavigationBarItemPojo.class, "p_0", "f_1").get());
}

Provides the following numbers:

V8
============
Boostrap : 386
Project : 72
File : 1
File : 0
Outline : 40
Outline : 10

Nashorn
============
Nashorn : 4061
Project : 45
File : 29
File : 2
Outline : 824
Outline : 39

The important numbers to compare are:

  • Bootstrap: ~400ms vs ~4000ms
  • 2nd Outline: ~10ms vs ~40ms

So performance indicates that the service should go with j2v8 but requiring that as hard dependency has the following disadvantages:

  • you need to ship different native binaries for each OS you want to run on
  • you need to ship v8 which might/or might not be a problem

So the strategy internally is that if j2v8 is available we’ll use v8, if not we fallback to the slower nashorn, a strategy I would recommend probably for your own projects as well.

If there are any Nashorn experts around who feel free to help me fix my implementation

Why I think @UIEventTopic / @EventTopic have been a bad idea

I’ve been working on a document since some time who holds my thoughts on the future direction of Eclipse 4 or better the Eclipse 4 Application Platform.

At first I’d like to mention that these as my personal views, not aligned with the e4 committers, so you’ll most likely find others who disagree.

It’s not my intention put e4 or any e4 committer down and if I’d blame someone it would be myself because I was part of the e4 effort since day 1.

The document is not yet ready but inspired by a tweet from Marcel Bruch

I’d like to take one of the points I’ll mention in this big vision/reflection document and explain why I think in retrospect providing those 2 annotations is wrong.

OSGi-Leakage

The first problem I have with those annotations is not an architectural one but caused by the bundle they are currently shipped in. We currently find them in “org.eclipse.e4.ui.di” and “org.eclipse.e4.core.di.extensions” who themselves require things like the Eclipse-DI-container, Equinox-container.

In my world of e4 components this is a deal breaker, as I want my code have no dependency on any of those bundles at compile time nor runtime but in general I think this is a minor problem and fixable. The architectural is the real blocker.

Event data is different to any other DI-Information

The real problem I have with @UIEventTopic and @EventTopic is the information they carry with them is totally different to any other data available in the DI-System (starting from OSGi-Services to Preference or IContextFunction derived values) because it’s only temporary. I think this characteristic makes @UIEventTopic/@EventTopic data not suited for DI.

The guess I have for those annotations being so popular is that they free you from the useage of IEventBroker (who leaks OSGi at an even larger scale by showing OSGi-Classes in its API, once more for no good reason) and the verbose code you need to write to subscribe (wild guess once more nobody was really worried about the OSGi-Class-Leakage).

@PostConstruct
void init(IEventBroker b) {
   b.subscribe( "my/event/Topic", new org.osgi.service.event.EventHandler() {
     public void handle(org.osgi.service.event.Event event) {
       handleEvent( (String)event.getProperty(IEventBroker.DATA) );
     }
   } );
}

private void handleEvent(String data) {
   // ...
}

In a Java8 world the verbosity can be reduced with the help of lamdas and method refs


import static my.sample.Util.extractEventData;

@PostConstruct
void init(IEventBroker b) {
  b.subscribe( "my/event/Topic", extractEventData(this::handleEvent));
}

private void handleEvent(String data) {
   // ...
}

// Util.java
public static <T> Consumer<Event> extractEventData( Consumer<T> dataConsumer) {
   return e -> (T)e.getProperty(IEventBroker.DATA);
}

The extractEventData could be provided by IEventBroker in a Java8 world BTW.

You loose typesafety for no good reason

IEventBroker and @UIEventTopic/@EventTopic trade IMHO typesafety for no good reason.

One can argue that this is the case for DI in general as well but you trade in this case typesafety against loose coupeling freeing your business code from dependencies on large framework (and yes I consider e4 and OSGi large frameworks) and providing you better testing support – so you get something in return.

This is not true for IEventBroker nor is it true for @UIEventTopic/@EventTopic, while IEventBroker could be fixed to provide a certain amount of typesafety (see e(fx)clipse EventBus) this will never be possible for @UIEventTopic/@EventTopic!

One could argue that on the receiver side you’ll have less framework bindings (in case one splits out the annotations from their existing owner bundle) but because the publisher requires the event bus anyways I don’t see any reason the receiver should not and the EventBus-Service is easy enough to be mocked in Unit-Tests.

And because it is not unlikely that many events are sent through the event system it puts pressure on the DI system which could have been avoid if you used the EventBus directly.