On DemoCamp-Tour

I’m on the road since yesterday for a week of DemoCamps. The first one is in my homelands capital Vienna on Monday 30th of (M)November and the second one in Hamburg on Firday 4th of December the month following (M)November.

Looking at the number of people registered (77! people in Vienna and 101! people in Hamburg) I think those 2 events (as well as all other DemoCamps all over the world) are a good opportunity to meet people who are not at the big conferences. I’ll spread the word a bit about e4 and show people why we believe in it, what we did and what we plan to do until the 1.0 ships. So it is not late to sign up for the free DemoCamps and meet people of the Eclipse Hall of Fame like Chris Aniszczyk and Jeff McAffer for example in Vienna.

Speaking about presentations I submitted a talk/tutorial proposal for EclipseCon 2010. The deadline for proposals is 20 days from now so don’t miss it and submit your proposal so that people can give feedback which helps the program committee to choose your talk.

QxWT 0.8.2.0 Released

I’m happy to announce the 0.8.2.0-Release (yes 4 digit version) of QxWT. I decided to use a 4 digit version because then the first 3 digits reflect the qooxdoo version and the 4th is for bugfixes which are purely QxWT specific.

There’s is a know problem on Linux-Hosted mode which is a problem with the qooxdoo sources but I didn’t investigated why the old mozilla used there fails but instead suggest to use the upcoming GWT 2.0.

I’ve now started working towards 0.8.3 and the first test suggest that I can provide 0.8.3 builds and release candidates quite quickly but this heavily depends on the time I can spend because I’m going to travel a bit in the next weeks.

Release QxWT-0.8.2-RC2

One week after release of RC1. We’ve just published RC2 of the Qooxdoo-GWT-Wrapper QxWT. You can fetch the release from our project site.

RC2 holds the following changes:

  • Completed Qooxdoo-FX-Support
  • 100% of the framework JavaDoc’ed (online)
  • Removal of unneeded images to optimize jar-sizes
  • Themes extracted into extra-jars to optimize jar-sizes

Because of the modified packaging to make the example from here run on RC2 you need to make the following adjustments:

  • Drop the following jars into your lib-directory:
    • org.ufacekit.qx.script.minjs-0.8.2-rc2.jar
    • org.ufacekit.qx.theme.modern-0.8.2-rc2.jar
    • org.ufacekit.qx.wrapper-0.8.2-rc2.jar

    and the remove all *-rc1.jars

  • Adjust the GWT-Module-XML
    <?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='myfirstqxapp'>
      <!-- Inherit the core Web Toolkit stuff.                        -->
      <inherits name='com.google.gwt.user.User'/>
      <inherits name="org.ufacekit.qx.wrapper.QxScript" />
      <inherits name="org.ufacekit.qx.QxEngine" />
      <inherits name="org.ufacekit.qx.theme.modern.QxTheme" />
    

    to include org.ufacekit.qx.theme.modern.QxTheme

The source code of the example is now also available from our SVN-Repository. So you only have the check it out and give it a spin. There’s currently a know problem on Linux which I’ve tracked down to a JS-Error in the Qooxdoo-Sources which will be fixed until the final release.

Release QxWT-0.8.2-RC1

QxWT-0.8.2-rc1

I happy to announce that a first release candidate of the GWT-Wrapper for the Qooxdoo-Widget-Library can be downloaded from our project homepage.

I started working on QxWT because I needed a GWT-Widget library providing me access to advanced controls like tables and trees and is released under a license which makes it possible to get integrated in commercial applications without paying license fees. I know there are other libraries out who already provide such a features but none of them provided me all features I wanted to have – for the record I don’t want to mess around with stores, buy in to a special domain model technology, … ).

What is QxWT

QxWT is a GWT wrapper for the qooxdoo-JS-Library. The qooxdoo-library is used for example by the RAP team as the client-side widget library. QxWT follows the qooxdoo-API as much as possible but naturally some constructs available in JavaScript can not get translated the Java 1:1 so some API methods have been adjusted. The biggest difference is that QxWT adopts the GWT-Event-Handler-System instead of wrapping the one of Qooxdoo but then once more provides 99% the same API.

One of the most important things is that Java-Developers expect to have the API documentation available in their IDE and I’ve worked with many GWT-Libraries who are not providing a good documentation. QxWT will provide full JavaDoc of all API methods when we release the final version of QxWT-0.8.2. In the RC we have documented already 99% of the widget-API but e.g. the Event-API completely lacks JavaDoc.

The second important thing is that the qooxdoo-JS-Library as well as QxWT are released under EPL which should allow you to easily use in corporate environments as well as in opensource projects.

Future plans

QxWT

  • Release 0.8.2 with the following features:
    • Based upon 0.8.2 release of Qooxdoo
    • 95% of the Widget-API of qooxdoo
    • 100% JavaDoced API
  • Release 0.8.3 with the following features:
    • Based upon 0.8.3 release of Qooxdoo
    • Eclipse-Wizard for setting up a QxWT-Project
    • Postprocess step to optimize deployment size of Qooxdoo-JS

UFaceKit for QxWT
After the release of QxWT 0.8.3 we are going to provide the following UFaceKit-Implementations

  • Qx-Databinding
  • Qx-Viewers
  • Qx-UFaceKit-Implementation
  • GWT-Integration for e4 so that you can access workbench-services from GWT-Applications (See the wonderful PDE-Editor written by Boris Bokowski for e4-0.9)

Getting started with QxWT

The following should give you a jump start on how to create a QxWT-Application from scratch (I assume you have the Google-Eclipse-Tools installed).
Setup of a new project

  1. Download the latest QxWT release form UFaceKit.org and unzip it somewhere on your hard drive
  2. Create a new GWT-Application named “MyFirstQxApp”
    screen1
  3. Create a directory named “lib” in the “MyFirstQxApp”-Project and copy the qx-jars from the download into it
    screen1_5
  4. Copy the “class”-Folder from the download into the war-Folder of your project
    screen1_6
  5. Open the MyFirstQxApp.html and add the following lines directly below the title
    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Web Application Starter Project</title>
    <script type="text/javascript">
      window.qxgwtmodule = "myfirstqxapp";
    </script>
    

    Please note that the “myfirstqxapp” must match the value you have as a “rename-to” in your “$MODULE.gwt.xml”

    Beside that you can delete the HTML-Code in the body-Tag so that it looks like this:

    <body>
    <!-- OPTIONAL: include this if you want history support -->
     <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
    </body>
    
  6. Add the Qx-jars to your build pathscreen2
  7. Make your GWT-Module inherit from Qx-Libraries like this:
    <?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='myfirstqxapp'>
      <!-- Inherit the core Web Toolkit stuff.                        -->
      <inherits name='com.google.gwt.user.User'/>
      <inherits name="org.ufacekit.qx.wrapper.QxScript" />
      <inherits name="org.ufacekit.qx.QxEngine" />
    </module>
    
  8. Open MyFirstQxApp.java remove everything beside the class definition
    package org.ufacekit.qx.my.client;
    
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class MyFirstQxApp {
    }
    

Your first cup of QxWT

  1. In GWT every application starts with an entry point and so does a plain Qooxdoo-JS-Application. That’s why QxWT provides you a specialized class which bridges both systems. So the first thing you need to do is to make your GWT-EntryPoint class inherit from org.ufacekit.qx.wrapper.application.QooxdooApp
    public class MyFirstQxApp extends QooxdooApp {
    	@Override
    	protected void run(QxAbstractGui application) {
    		// TODO Auto-generated method stub
    	}
    }
    
  2. The run method will by called once both framework start ups are finished and you are ready to create the application.

  3. The QxAbstractGui is the application scope into which your QxWT-Application is running in currently the only thing it provides you access to is the viewport you can add your UI-Widgets (QxComposite) to. Let’s as a first exercise create a GroupBox somewhere on the screen
    protected void run(QxAbstractGui application) {
      QxGroupBox container = new QxGroupBox();
      container.setContentPadding(16, 16, 16, 16);
      
      application.getRoot().add(container, QxOption.leftTop(50, 30, "%"));
    }
    

    This code creates a groupbox and positions it 50% to the left and 30% to the top of the browser window. As you’ll notice QxWT works different to SWT because you don’t pass the parent of a widget to the constructor but you add the widget later on to the parent together with some layout informations, for swing developers this should be quite familiar.
    Your ui looks like this now:
    screen3

  4. QxWT like every other widget library provides the possibility to layout child-controls using layout managers so the next thing we do is to set a layout manager on the groupbox widget like this:
    QxGridLayout layout = new QxGridLayout(9, 5);
    layout.setColumnAlign(0, HAlign.LEFT, VAlign.MIDDLE);
    layout.setColumnAlign(1, HAlign.RIGHT, VAlign.MIDDLE);
    
    container.setLayout(layout);
    

    and add 2 children (a label and a text field) like this:

    QxLabel label = new QxLabel("Greeting");
    container.add(label, QxOption.rowColumn(0, 0));
    		
    QxTextField field = new QxTextField();
    container.add(field, QxOption.rowColumn(0, 1));
    

    The code should be quite self-explanatory and result in this UI.screen4

  5. As a final step let’s add a button which invokes a remote services. So the first step is to add a button like this:
    QxButton button = new QxButton("Submit");
    container.add(button, QxOption.row(1), QxOption.column(0), QxOption.colSpan(2));
    

    Once more quite self-explanatory beside the fact that the button is spaning 2 columns. The next thing to do is to react on button clicks which could be done in different ways but using a command which is attached to the control is the better one. So the first thing we do is to define a command and connect the button to it

    QxCommand cmd = new QxCommand("CTRL+S");
    button.setCommand(cmd);
    

    As you might guess the advantage of a command is that you can attach a keyboard sequence so the command not only gets executed when the user presses the button but also when entering a the keyboard sequence CTRL+S. The last thing we need to do is to attach a listener to the command which gets informed when the command is called. So we are adding an inner-class which looks like this:

    class QxExecuteHandlerImpl implements QxExecuteHandler {
      private QxTextField field;
    
      public QxExecuteHandlerImpl(QxTextField field) {
        this.field = field;
      }
    
      public void execute(QxExecuteEvent executeEvent) {
      }
    }
    

    and attach it to the command like this:

    cmd.addExecuteHandler(new QxExecuteHandlerImpl(field));
    

    The application should look like this now:
    screen5

  6. Next step is to call the remote service which should be quite familiar to people who know GWT already.
    public void execute(QxExecuteEvent executeEvent) {
      GreetingServiceAsync service = GWT.create(GreetingService.class);
      service.greetServer(field.getValue(), new AsyncCallback<String>() {
        public void onFailure(Throwable caught) {}
    
        public void onSuccess(String result) {}
      });
    }
    

    and display the result for example using a QxWindow like this:

    public void onFailure(Throwable caught) {
      QxWindow window = new QxWindow("Error");
      window.setLayout(new QxVBoxLayout(10));
      QxAtom atom = new QxAtom(caught.toString(),"/myfirstqxapp/qooxdoo-0.8.2-sdk/framework/source/resource/qx/icon/Oxygen/48/status/dialog-error.png");
      atom.setRich(true);
      window.add(atom);
      window.center();
      window.open(); 
    }
    
    public void onSuccess(String result) {
      QxWindow window = new QxWindow("Remote Answer");
      window.setLayout(new QxVBoxLayout(10));
      QxAtom atom = new QxAtom(result,"/myfirstqxapp/qooxdoo-0.8.2-sdk/framework/source/resource/qx/icon/Oxygen/48/status/dialog-information.png");
      atom.setRich(true);
      window.add(atom);
      window.center();
      window.open();
    }
    

    If you now run your application, enter a text and hit the submit button or as alternative press CTRL+S your application should react like this:
    screen6

Here’s the complete application class once more for reference:

package org.ufacekit.qx.my.client;

import org.ufacekit.qx.wrapper.application.QooxdooApp;
import org.ufacekit.qx.wrapper.application.QxAbstractGui;
import org.ufacekit.qx.wrapper.event.QxCommand;
import org.ufacekit.qx.wrapper.event.type.gwt.QxExecuteEvent;
import org.ufacekit.qx.wrapper.event.type.gwt.QxExecuteHandler;
import org.ufacekit.qx.wrapper.ui.basic.QxAtom;
import org.ufacekit.qx.wrapper.ui.basic.QxLabel;
import org.ufacekit.qx.wrapper.ui.form.QxButton;
import org.ufacekit.qx.wrapper.ui.form.QxTextField;
import org.ufacekit.qx.wrapper.ui.groupbox.QxGroupBox;
import org.ufacekit.qx.wrapper.ui.layout.QxGridLayout;
import org.ufacekit.qx.wrapper.ui.layout.QxVBoxLayout;
import org.ufacekit.qx.wrapper.ui.layout.QxGridLayout.HAlign;
import org.ufacekit.qx.wrapper.ui.layout.QxGridLayout.VAlign;
import org.ufacekit.qx.wrapper.ui.window.QxWindow;
import org.ufacekit.qx.wrapper.util.gwt.QxOption;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class MyFirstQxApp extends QooxdooApp {
	
	class QxExecuteHandlerImpl implements QxExecuteHandler {
		private QxTextField field;
		
		public QxExecuteHandlerImpl(QxTextField field) {
			this.field = field;
		}
		
		public void execute(QxExecuteEvent executeEvent) {
			GreetingServiceAsync service = GWT.create(GreetingService.class);
			service.greetServer(field.getValue(), new AsyncCallback<String>() {

				public void onFailure(Throwable caught) {
					QxWindow window = new QxWindow("Error");
					window.setLayout(new QxVBoxLayout(10));
					QxAtom atom = new QxAtom(caught.toString(),"/myfirstqxapp/qooxdoo-0.8.2-sdk/framework/source/resource/qx/icon/Oxygen/48/status/dialog-error.png");
					atom.setRich(true);
					window.add(atom);
					window.center();
					window.open(); 
				}

				public void onSuccess(String result) {
					QxWindow window = new QxWindow("Remote Answer");
					window.setLayout(new QxVBoxLayout(10));
					QxAtom atom = new QxAtom(result,"/myfirstqxapp/qooxdoo-0.8.2-sdk/framework/source/resource/qx/icon/Oxygen/48/status/dialog-information.png");
					atom.setRich(true);
					window.add(atom);
					window.center();
					window.open();
				}
				
			});
		}
	}

	@Override
	protected void run(QxAbstractGui application) {
		QxGroupBox container = new QxGroupBox();
		container.setContentPadding(16, 16, 16, 16);

		QxGridLayout layout = new QxGridLayout(9, 5);
		layout.setColumnAlign(0, HAlign.LEFT, VAlign.MIDDLE);
		layout.setColumnAlign(1, HAlign.RIGHT, VAlign.MIDDLE);
		
		container.setLayout(layout);
		
		QxLabel label = new QxLabel("Greeting");
		container.add(label, QxOption.rowColumn(0, 0));
		
		QxTextField field = new QxTextField();
		container.add(field, QxOption.rowColumn(0, 1));
		
		QxButton button = new QxButton("Submit");
		container.add(button, QxOption.row(1), QxOption.column(0), QxOption.colSpan(2));

		QxCommand cmd = new QxCommand("CTRL+S");
		button.setCommand(cmd);
		
		cmd.addExecuteHandler(new QxExecuteHandlerImpl(field));
		
		application.getRoot().add(container, QxOption.leftTop(50, 30, "%"));
		
	}	
}

If you want to learn more of the APIs you can take a look at the demo-Project in our subversion repository and naturally you can support my work on this by making a donation (See paypal button at the left of the page).

Stay tuned for more news on this and other cool stuff – there are a lot of ideas floating around in my head (some of them even translated into source-code)

e4 on the road

If you are curious on what e4 is all about and get a first impression you’ll probably want to attend one of the following events where I’m going to talk about e4:

If you haven’t done yet it’s still time to register for free to those events.

Because I’m doing this in my spare time (well I’ll take one or two days off) I even had to reject requests for talks which is a bitty. Still there are more e4 presentations in the queue but their dates are not fixed yet (I’ll be very likely in Z├╝rich at the Java User Group Switzerland and maybe going to Lille). I’ll post details about those events once the dates are fixed.

A big thank you to the people and companies who make/made the travels to Hamburg or e.g. to EADD possible by paying my travel expenses.

The core-platform, e4 – some random thoughts

At the Eclipse Summit there’s was a special symposia where discussion about Eclipse Foundation 2.0 happened. I’m not going into detail but as others already also found out (e.g. Bjorn) the investment into core platform is decreasing and too few people understand that without a properly maintained platform-core their business will be broken sooner than they imagine.

One of the problems I see from the point of an indivual committer (I own my company so individual might not be the right term here) is: Making money from working on those low levels of the Eclipse Ecosystem stack is nearly impossible whereas gaining revenue from things up in the stack e.g. getting payed for adding features to Nebula for example is easier. This is the reason I had to reduce (=stop) my work investment in the 3.x (though I’m still fixing severe bugs when found it code I introduced into the repository).

Looking at e4 the situation is similar because we are here also developing something which is at the bottom of the whole stack – well e4 is a new application runtime platform.
The difference to 3.x is that:

  • I can at least justify my investment with an academic interest
  • I believe with e4, eclipse is prepared for the future and without it other platforms will outpace it in the short-term and make it obsolete in the long-term when we talk about RCP/RIA-Applications (for IDEs it might be a bit different) which will make my Java, SWT, Eclipse, … know-how obsolete as well

but without an immediate use case or customer who needs certain features in e4 I can only spend my spare time into this.

I still hope that I can find a customer or a business use case which makes it possible to also invest work time (1-2 days a week) into it (I think my in depth knowledge about the core design is something others might cause some trouble to get started) but at the moment it’s not looking very promising because like it is with 3.x people take the core for granted.

Anyways Eclipse is with e4 getting once more an innovative core-platform and I’m proud to be and stay part of it – especially e4.