QxWT a wrapper for Qooxdoo-JS

In my last blogs I wrote about my current exploration of Qooxdoo and despite the silence since then I made a lot of good progress. I explored different things:

  • Rewrite the whole library in plain-GWT: Doable but well a bit of work and without haveing a something founding this undoable
  • Simply write a wrapper using GWT’s JSNI-calling interface: Doable in an acceptable time, though to get acceptable load-performance I need to investigate a bit (minimizing JavaScript loading, …)

After having explored the above options I decided to go down to route writing a wrapper library and well I think I was quite successful until now because I now have the following examples from their demo running:

Running Demos

If you look at the list you’ll notice that in the end the all important controls to write UI applications are available to me now and naturally the next thing is to make them UFaceKit-Viewer and UFaceKit-Databinding aware.

I haven’t started yet with Databinding support because for more complex controls having a UFaceKit-Viewer implementation is much more important writing those “dumb”-Observables is a piece of cake since 3.5 and the new Properties-API. So the first thing I can show you is how to implement an UFaceKit-Viewer for QxWT-Widgets:

package at.bestsolution.ufacekit.qx.viewers.example.client;

import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.ufacekit.ui.viewers.CollectionContentProvider;
import org.eclipse.ufacekit.ui.viewers.LabelConverter;

import at.bestsolution.qx.wrapper.client.application.QooxdooApp;
import at.bestsolution.qx.wrapper.client.application.QxAbstractGui;
import at.bestsolution.qx.wrapper.client.ui.layout.QxVBox;
import at.bestsolution.qx.wrapper.client.ui.window.QxWindow;
import at.bestsolution.qx.wrapper.client.util.gwt.QxOption;
import at.bestsolution.ufacekit.qx.viewers.TableViewer;
import at.bestsolution.ufacekit.qx.viewers.TableViewerColumn;

public class TableViewerExample extends QooxdooApp {
  @Override
  protected void run(QxAbstractGui application) {
    QxWindow window = new QxWindow("JFace TableViewer",
      "/icon/16/apps/office-spreadsheet.png");
    window.setWidth(600);
    window.setHeight(400);
    window.setContentPadding(0, 0, 0, 0);
    window.setShowClose(false);
    window.setShowMinimize(false);
    window.setLayout(new QxVBox());
    window.open();

    application.getRoot().add(window, QxOption.leftTop(50,10));

    TableViewer<Person, Collection<Person>> tableViewer = 
      new TableViewer<Person, Collection<Person>>(3);
    tableViewer.setContentProvider(
      new CollectionContentProvider<Person>()
    );
    
    TableViewerColumn<Person> col = 
      new TableViewerColumn<Person>(tableViewer, "Firstname");
        col.setLabelConverter(new LabelConverter<Person>() {
          @Override
          public String getText(Person element) {
            return element.getFirstname();
          }
    });

    col = new TableViewerColumn<Person>(tableViewer, "Lastname");
    col.setLabelConverter(new LabelConverter<Person>() {
      @Override
      public String getText(Person element) {
        return element.getLastname();
      }
    });

    col = new TableViewerColumn<Person>(tableViewer, "Age");
    col.setLabelConverter(new LabelConverter<Person>() {
      @Override
      public String getText(Person element) {
        return element.getAge() + "";
      }
    });

    Collection<Person> ps = new ArrayList<Person>();
      for (int i = 0; i < 10000; i++) {
        ps.add(new Person("First " + i, "Last" + i, i));
      }
    tableViewer.setInput(ps);

    window.add(tableViewer.getTable(), QxOption.flex(1));
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN" 
   "http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/distro-source/core/src/gwt-module.dtd">
<module rename-to='at_bestsolution_ufacekit_qx_viewers_example'>
  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Other module inherits                                      -->
  <inherits name="at.bestsolution.qx.wrapper.QxScript" />
  <inherits name="at.bestsolution.qx.wrapper.QxEngine" />
  <inherits name="org.eclipse.ufacekit.ui.Viewers"/>
  <inherits name="org.eclipse.ufacekit.core.UBean" />
  <inherits name="at.bestsolution.ufacekit.qx.QxViewers"/>

  <!-- Specify the app entry point class.                         -->
  <entry-point class='at.bestsolution.ufacekit.qx.viewers.example.client.TableViewerExample'/>
</module>

This results in an demo application like this:

You’ll probably notice the big start up time but this is because I’m loading all Qooxdoo-JavaScript files one by one until now without any size optimization but this is something to address later. The important fact for me now is the runtime/rendering performance of Qooxdoo and I’ll have to say that I’m amazed how fast one can scroll those 10.000 items (well I also tested with 100.000 and there’s no difference once the control is shown).

Another thing you might notice is that the colum headers are not correct and that one needs to define the amount of columns before creating the viewer. This is because I’m by far no expert in Qooxdoo and didn’t find out how to do this stuff until now so bear with me.

The last thing you might observe is that all this stuff is not under the org.eclipse.ufacekit-namespace but under at.bestsolution. The reason for this is that if there’s no one else puting resources (time and/or money) into this I don’t see a reason for releasing it into the public domain.

In the end something about Qooxdoo. I have to say that I’m amazed by the performance but what amazes me even more is that this is the first JavaScript-UI-Library I’ve worked with really concentrating on providing you widgets, just like SWT does, not requiring me to use their stores, domain object models, MVC-story, … – it’s “just” an widget library.

UFaceKit and Java5-Viewers

I had some time today to once more work a bit on UFaceKit and it’s viewer implementation and I think I added a feature which makes sense to show of.

I was working on the rewrite of an old application we wrote 3 years ago to use the Highlevel-Databinding-API I’m developing as part of the UFaceKit-Project. One of the common problems I had in my RCP-Application was that SWT-Combo-Widgets are not friendly if you have many entries because native keyboard selection is not supported on by default.

Inspired by a proposed component for JFace I wrote such a Viewer-Implementation from scratch which can be used like this:

/**
  * @param args
  */
public static void main(String[] args) {
  final Display d = new Display();
  Shell shell = new Shell(d);
  shell.setLayout(new GridLayout());
		
  Text text = new Text(shell,SWT.BORDER);
  text.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
  final Collection<Person> persons = new ArrayList<Person>();
  persons.add(new Person(1, "Tom"));
  persons.add(new Person(2, "Udo"));
  persons.add(new Person(3, "Bernd"));
  persons.add(new Person(4, "Tom"));
  persons.add(new Person(5, "Thomas"));
		
  final ProposalViewer<Person, Collection<Person>> viewer = 
    new ProposalViewer<Person, Collection<Person>>(text);

  viewer.setLabelConverter(new LabelConverter<Person>() {
    @Override
    public String getText(Person element) {
      return element.name + " ( ID-"+element.id+")";
    }
  });
  viewer.setContentProvider(
    new CollectionContentProvider<Person>()
  );
  viewer.setInput(persons);
  viewer.addSelectionChangedListener(
    new ISelectionChangedListener<Person>() {
      public void selectionChanged(
        SelectionChangedEvent<Person> event) {
          if( event.getSelection().isEmpty() ) {
            System.out.println("<Empty>");
          } else {
            for( Person p : event.getSelection() ) {
              System.out.println(p.name);
            }	
          }
      }
  });

  Button b = new Button(shell,SWT.PUSH);
  b.setText("Selection");
  b.addSelectionListener(new SelectionAdapter() {
    @Override
    public void widgetSelected(SelectionEvent e) {
      viewer.setSelection(
        new StructuredSelection<Person>(
          persons.iterator().next()
        )
      );
    }
  });
  shell.open();

  while( ! shell.isDisposed() ) {
    if( ! d.readAndDispatch() ) {
      d.sleep();
  }
}

There are some interesting things to notice about the Viewers and their implementation:

  • Java5 Language Features like Generics, for-loop above Selection
  • A generic interface definition making it widget-toolkit agnostic (I’ve already implemented some Swing, Qt, SWT, GWT, SmartGWT-Viewers)
  • Automatic Databinding support because it works on the Interface-Definition

How nice this new SWT-Proposal-Viewer integrates itself into my application take a look at this small screencast:

and for the readers of blog aggregators here as an image Screenshot

E4@Eclipse Application Developer Day

In my last post I published the demo applications I planned to show of at EADD in Karlsruhe and here are the PDF-slides.

The talk was split into 4 areas:

  • History and Reasons
  • Design ideas (EMF-Model, IEclipseContext, Declarative Styling, DI)
  • The implementation of the ideas + BackwardsCompat
  • Demos:
    • Application development with EMF-XMI-Editor using the E4-PhotoDemo
    • Declarative-Themeing via E4-Contacts-Demo
    • Workbench-Renders: Using PShelf and Ribbon using the E4-Contacts-Demo
    • Backwards compat by launching our E4-Builds and writing a HelloWorld application
    • Abandoning of Static and Singleton by launching E4-Contacts-Demo as a RAP-Application with unmodified workbench code

The talk was quite well received and I showed how we try to create innovation in the core-platform. I’d like to thank EclipseSource who made my travel to Karlsruhe possible by funding the half of my travel costs.

E4 – A new area for RCP/RIA-Applications

I’m on the road to prepare my example for the E4 talk I’m delivering on the Eclipse-Developers-Day in Karlsruhe and I have to say that in my eyes E4 is going to open up a new world for Eclipse-RCP-Developers.

Though RCP-Applications written in 3.x might not look too bad no one can deny that the UI-Design is coming from an IDE background and compared to modern Web-UIs it looks boring (which is not a bad thing per se for business applications). The problem in 3.x is that it is very hard to impossible to change the L&F of your application.

E4 provides different multiple solutions to fix the L&F:

  1. Declarative-Styleing through CSS
  2. The possibility to define your own renderes to exchange Widget A through Widget B if CSS is not enough to theme your application

To demostrate what you can achieve when you combine the 1st and 2nd possibility I create a small screencast

where you see the famous E4-Photo-Application revamped

E4 Photo Demo

A second example application is our E4-Contacts-Demo created and maintained by Kai Tödter which shows advanced css-styles like radial gradients.

Contacts Demo

I use this application to show you another nice thing you can do with E4’s declarative styling support. You can adjust the styling of your application while it is running so that you can experiment with various font and color settings WITHOUT shutting down your application.

If all this would not be enough you can run the unmodified code (please take this literally) from the example application above in your browser using the RAP-Framework.

E4-Rap-Screenshot

If you are interested in E4 and what’s going on behind the scenes of the next major Eclipse-Release I hope to see you in Karlsruhe on Tuesday July 7th.