Samstag, 6. August 2016

Hi5: Eclipse 4 API for web developers

About

HTML5/CSS/JavaScript seem to become the primarily stack of technologies to develop UI/frontend applications. The Hi5 project aims at providing an Eclipse 4 API port for web developers.

The following is the architectural overview of the idea behind the project:

Picture: overall architecture of the Hi5 idea

Server side

On the server side (backend) the infrastructure of the Eclipse RCP platform is handling requests that the web client doing. This includes collecting all available E4 fragments and merging them into the application model. Next, the merged application model is transformed into a HTML DOM representation which then sent to the client via HTTP.

With the Eclipse Communication Framework (ECF) there is also great support for a service driven development approach as OSGi services can serve as web services, for example, using ECF's JAX-RS integration.

Client side

On the client side you can use your favorite framework/library to provide a smooth and reactive UI. By default, jQuery, jQuery UI and jQuery mobile are used.

Deployment modes

The application can be deployed in several modes:
  • server/client mode: Eclipse RCP backend runs on a server and the client runs in a web browser
  • local mode: Eclipse RCP backend runs locally and the client runs in a JavaFX WebView instance

Demo

The following screeshot shows a demo application running in the "local mode", i.e. the client is run using the JavaFX WebView as renderer:


Summary

With HTML5/CSS/JavaScript gaining more and more attraction to developers, this approach makes absolutely sense. It allows for going with the trends of the web developer communities (with regards to UI toolkits) but relying on the Eclipse 4 and OSGi platform as a robust and modular backend.

Links

[1] Hi5 GitHub repository: https://github.com/erdalkaraca/hi5

Mittwoch, 4. Mai 2016

Eclipse lambda driven UI creation

About

With the addition of lambda expressions to the Java 8 language, you can now create nice APIs for reducing boilerplate code. One of tedious tasks has always been the creation of UI code as it involves lots of boilerplate code and keeping track of what control/widget is a child of another. This article introduces a small helper library I use in my projects. It is about a thin lambda driven API for creating structured UI code.

Conventional UI code

The following code will create a simple UI form:
private Text text;

public void createUIConventional(Composite parent) {
    parent.setLayout(GridLayoutFactory.swtDefaults().numColumns(3).create());

    Label label = new Label(parent, SWT.NONE);
    label.setText("Selection");

    ComboViewer viewer = new ComboViewer(parent, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY);
    customizeComboViewer(viewer);
    viewer.getCombo().setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

    Button button = new Button(parent, SWT.NONE);
    button.setText("Apply");
    button.addSelectionListener(new SelectionAdapter() {
        @Override
        public void widgetSelected(SelectionEvent e) {
            text.setText("Selection:  " + viewer.getCombo().getText());
        }
    });

    text = new Text(parent, SWT.READ_ONLY | SWT.BORDER);
    text.setLayoutData(
            GridDataFactory.swtDefaults().span(3, 1).grab(true, true).align(SWT.FILL, SWT.FILL).create());
}


As you can see, SWT requires that you always create a new Control/Widget as a child to an existing one, i.e. you have to provide the parent as the first constructor parameter.
Furthermore, if you have lots of UI elements to create, the readability of the code quickly decreases and you can hardly see the hierarchy of the UI widgets WITHIN the code.

In the past, I often used local code blocks to denote the hierarchy of UI controls within the code to achieve better readability.

Lambda driven UI code

The above example can now be rewritten as follows:

 private SwtUI root;

 public void createUI(Composite parent) {
  root = SwtUI.wrap(parent);
  root.layout(GridLayoutFactory.swtDefaults().numColumns(3).create())//
    .child(() -> SwtUI.create(Label::new)//
      .text("Selection"))//
    .child(() -> ViewerUI.createViewer(ComboViewer::new, SWT.BORDER | SWT.SINGLE | SWT.READ_ONLY)//
      .id("selectionCombo")//
      .customizeViewer(this::customizeComboViewer)//
      .layoutData(new GridData(GridData.FILL_HORIZONTAL)))//
    .child(() -> SwtUI.create(Button::new)//
      .text("Apply")//
      .on(SWT.Selection, this::onButtonClick))//
    .child(() -> SwtUI.create(Text::new, SWT.READ_ONLY | SWT.BORDER)//
      .id("textField")//
      .layoutData(GridDataFactory.swtDefaults().span(3, 1).grab(true, true).align(SWT.FILL, SWT.FILL)
        .create()));
 }

Now, by using method pointers internally, instantiating a control/widget does not need its parent any more as it will always be parented within the current context.

You can find the code at:

https://github.com/erdalkaraca/lambda-ui

Check it out into your workspace and experiment with it. Do not hesitate to give feedback.