Sunday, June 07, 2009

I'm moving to Wordpress

In the last few days I moved this blog to wordpress and you can reach the content through http://tomsondev.bestsolution.at/

Saturday, May 23, 2009

Useing Qt to write Equinox-OSGi-UI-Applications

I saw I didn't blogged since about 2 months. So I thought I'll start a series of blog entries showing off new things and paths I'm exploring.

I'll start with a Technical Topic because it's a really exciting thing I guess not only for me but also for the whole Equinox-OSGi/Java-Community.

Since some time Qt is released under LGPL and since some weeks now their Java-Binding named Qt-Jambi is released too under LGPL. I've been playing with Qt-Jambi (because my UFaceKit project has a Qt-Port) before but now that the code is under LGPL it's getting more interesting to the wider Java-audience and naturally also people who use Equinox-OSGi for their applications.

A simple QtJambi-Application


Before digging into the details what I've done let's look at a simply QtJambi-Application if we are not using Equinox-OSGi.


package at.bestsolution.qt;

import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QWidget;

public class HelloWorld extends QMainWindow {

public HelloWorld() {
setWindowTitle("Hello World!");

QWidget composite = new QWidget();

QGridLayout layout = new QGridLayout();
composite.setLayout(layout);

QLabel label = new QLabel();
label.setText("Label");
layout.addWidget(label,0,0);

QLineEdit text = new QLineEdit();
layout.addWidget(text,0,1);

setCentralWidget(composite);
}

public static void main(String[] args) {
QApplication.initialize(new String[0]);

HelloWorld world = new HelloWorld();
world.show();

QApplication.exec();
}
}

This looks not much different to a SWT-Application besides the fact that one doesn't has to pass a parent when creating a widget and instead of running the event loop one simply calls QApplication.exec().

QtJambi and Equinox-OSGi


Couldn't be hard you think when you've used other UI-Toolkits (SWT,Swing) in your Equinox-OSGi-Applications already but the problem is that Swing is not problematic because it is part of the JRE and SWT is shipped as an (in fact multiple) Equinox-OSGi-Bundle/Fragment.

What we need to do is to Equinox-OSGify the bundles coming from Qt but this task is more complex then it looks on the first sight because using the simple converter provided by PDE is not providing us a solution because QtJambi-Code expects to load the libraries in very special way which means we need to patch their Java-Code to make it aware of Equinox-OSGi.

The really cool thing is that patching and maintaining the patch is easier than one might think because they provide their sources through a git-repo one could simply clone and maintain the patched sources. So maintaining the patch is easier than it is for example to maintain a patch for the eclipse-platform because of git.

The tough thing is to get the environment setup in a way than one can produce .jars from the sources because one

  • Has to compile the Qt-Sources

  • To generate the Java-Binding-Classes to the Qt-Sources (extracted from the C++-Header-Files)


which is a bit time consuming and not documented very well at the moment. Though this is doable for a medium skilled Java-Dev I think one should be able to checkout the complete project with native and generated Java-Code and doesn't have to compile all the stuff.

After having managed to setup a build environment I patched the libary loading classes and recreated the .jar-packages. QtJambi is split in 2 .jars:

  • qtjambi.jar: Hold platform independent Java-Classes

  • qtjambi-${os}.jar: Holding native libraries for the platform and the JNI-Glue


So the setup is similar to SWT but in SWT also the Java-Code is part of the native fragment because it differs from platform to platform and the host bundle is simply an empty bundle. In contrast to that in Qt the Host-Bundle is holding all Java-Classes and in the native fragments one has the native-libs and JNI-Glue.

So what this all means for you? Not too much because I did 2 things as part of UFaceKit-Target-Setup:

  • Packaged my changes to the Java-Code and provide it for download

  • Added ant-tasks who fetch the native libs from Qt-Software and repackage them



One could also use these ant-tasks when not using UFaceKit (I'm using it for my RCP-Development-Setup).

The Equinox-OSGi-Support is not fully finished and I'll maybe rework it a bit in future when understanding the code better but for now it sufficient to go on and file a CQ to make use of Qt in UFaceKit. Let's see what's coming out from this now that Qt is LGPL.

Simple Qt-Jambi and Equinox-OSGi-Application


Let's create an Equinox-Application which uses Qt as UI-Toolkit now. The easiest thing is to use the PDE-Wizard to create a "Headless Hello RCP" and add a MainWindow.java.
package at.bestsolution.qt;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.gui.QPushButton;
import com.trolltech.qt.gui.QWidget;

public class MainWindow extends QMainWindow {

public MainWindow() {
QWidget widget = new QWidget();
widget.setObjectName("main_window");

QGridLayout layout = new QGridLayout();
layout.setMargin(0);
widget.setLayout(layout);

addHeader(layout,"Tom Schindl","at/bestsolution/qt/bookmarks.png");

QWidget content = new QWidget();
QGridLayout contentLayout = new QGridLayout();
content.setLayout(contentLayout);

addLine(0, contentLayout, "Firstname");
addLine(1, contentLayout, "Lastname");
addLine(2, contentLayout, "Age");

QPushButton button = new QPushButton();
button.setObjectName("submit");
button.setText("Submit");
contentLayout.addWidget(button,3,1);

layout.addWidget(content);

setCentralWidget(widget);
}

private void addHeader(QGridLayout layout, String labelText, String icon) {
QLabel header = new QLabel();
layout.addWidget(header);
header.setObjectName("header");
QGridLayout headerLayout = new QGridLayout();
headerLayout.setMargin(0);
header.setLayout(headerLayout);

QLabel headerIcon = new QLabel();
headerIcon.setObjectName("header_icon");
headerIcon.setPixmap(loadImage(icon));

headerLayout.addWidget(headerIcon);

QLabel headerText = new QLabel();
headerLayout.addWidget(headerText,0,1);
headerLayout.setColumnStretch(1, 100);
headerText.setObjectName("header_text");
headerText.setText(labelText);
}

private void addLine(int line, QGridLayout contentLayout, String labelText) {
QLabel label = new QLabel();
label.setText(labelText);
label.setObjectName("label");
contentLayout.addWidget(label);

QLineEdit text = new QLineEdit();
text.setObjectName("text");
contentLayout.addWidget(text,line,1);
}


private QPixmap loadImage(String path) {
try {
InputStream in = getClass().getClassLoader().getResourceAsStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream();

int l;
byte[] buffer = new byte[1024];

while ((l = in.read(buffer)) != -1) {
out.write(buffer, 0, l);
}

QPixmap pic = new QPixmap();
pic.loadFromData(out.toByteArray());
return pic;
} catch (Exception e) {
e.printStackTrace();
}

return null;
}
}

and modify the generated application class like this:
package at.bestsolution.qt;

import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;

import com.trolltech.qt.gui.QApplication;

public class Application implements IApplication {
public Object start(IApplicationContext context) throws Exception {
QApplication.initialize(new String[0]);

MainWindow window = new MainWindow();
window.show();

QApplication.exec();

return IApplication.EXIT_OK;
}

public void stop() {}
}

Well as you see I'm not a good designer and the application looks well not really nice though it looks native on my OS-X though this is only faked by Qt because they are drawing everything on the screen as far as I understood it.

One could think that this fact is a draw back of Qt but IMHO it's the other way round because with this strategy they can support things SWT can't support easily - Completely restyle your application using a declarative language and well they use CSS like e.g. E4 does too.

The first thing to do is to add a method to load a stylesheet to Application.java:
private String loadStyles(String cssPath) {
InputStream in = getClass().getClassLoader().getResourceAsStream(cssPath);
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder s = new StringBuilder();
String line;

try {
while( (line = r.readLine()) != null ) {
s.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}

return s.toString();
}

and set the style sheet on the main window:
public Object start(IApplicationContext context) throws Exception {
QApplication.initialize(new String[0]);

MainWindow window = new MainWindow();
window.setStyleSheet(loadStyles("at/bestsolution/qt/style.css"));
window.show();

QApplication.exec();

return IApplication.EXIT_OK;
}
and we need to define some styles:

resulting in this application:


which we all agree looks better than:



As you see this is also not my design but then one you get when using the Eclipse-Forms-API with the difference that in Eclipse one has to learn a new API to deal with besides SWT whereas in Qt the UI-Code is still Qt and styled by a declarative syntax and if you ask me the Forms-API is going to replace in space of Eclipse in E4 through SWT + CSS but this is only my personal opinion.

So should we all now move to Qt-Jambi to write UI-Applications in Java like we did years ago when we abandoned Swing and started using SWT?

Let's look at some potentially problematic areas:

  • Qt and QtJambi misses an application framework like eclipse RCP provides one for SWT-Application developers

  • Qt and QtJambi misses Databinding support like Eclipse-Databinding provides one for SWT, JavaBeans and EMF

  • Nokia removed all resources from QtJambi development and wants to build a community to work on it


For at least 2 of the above there are solutions already today:

  • E4's core application platform is UI-Toolkit agonstic so though E4 is not released until 1.5 years it would give people the possibility to use Qt as their UI-Toolkit of choice which supports many many things starting from animations, multimedia integration, ...

  • UFaceKit provides JFace-Viewer like and Eclipse-Databinding support for QtJambi if the CQ I'm going to file is approved


Still the killer problem is the lacking support from Nokia on QtJambi and it's unclear if a community could be build around it who not even maintains but also adds new features.

I think this is a bitty because with getting a real application framework with E4, it's themeing, multimedia and animation support I think QtJambi could get a real possibility to write cross-platform RCP-Applications in Java without the sometimes really hurting lowest common denominator problem we have in SWT.

So what should one do? Though QtJambi looks like a real solution for writing nice looking RCP-Applications the uncertainness caused by Nokia by cutting resources makes it unusable for most companies.

For form developers I could point you once more to UFaceKit which supports both SWT and Qt and your form application code is not affected by changing the underlying technology but one can still rely on native stuff where needed (e.g. using Qt animation/multimedia support).

For me as one of E4 committers and UFaceKit-Project lead it means:

  • I'd try to keep the application runtime widget agonstic if possible (well we are on a good track here)

  • I'll file a CQ to let UFaceKit make use of QtJambi and provide first class JFace-Viewer and Eclipse-Databinding support for QtJambi


  • 1. updated my wrong capitalization of Qt
    2. please note that I'm using Equinox specific stuff to make this work so it is maybe not runnable on other OSGi implementations but I'm happy to incooperate feedback and suggestions into my git-clone to support other OSGi implementations

Monday, March 02, 2009

Give your E4-Application a modern Look&Feel

EclipseCon is coming in about 3 weeks and I started preparing the stuff for my talks about E4 and UFaceKit.

In E4 we are trying to address some of the main pain points RCP-Application developers faced - Their application looks like Eclipse and the theming/presentation API is not flexible enough to modify all aspects of the UI (e.g. Toolbar/MenuBar, ...)!

The first step to make your application look different was that we introduced the concept of declarative styleing (CSS).

Let's take the demo E4-Photo-Demo-application as example.
This is the application without CSS:

This is the application with CSS:

But like in other aspects E4 goes further and allows you to exchange complete widgets like the application-shell, the menu and toolbar, the Stack-Folders (the standard theme uses CTabFolder) resulting in an E4-Demo-Application like this:

You want to know more about how this works and how the internals of the workbench make such things possible? Then I'd suggest to you attend the EcliseCon-talk about the modeled workbench Boris and I are delivering at EclipseCon09

But E4 goes even further! It allows you to plugin every widget-technology you want to! The internals don't care whether your application gets renderered by QT, Swing, UFaceKit you name it. So I've done that and here's my UFaceKit-Demo-Application built on top of E4:
Makeing UFaceKit a possible renderer of E4 opens the doors to all technologies supported by UFaceKit (Swing, QT, GWT, ...) and its advanced DeclartiveStyling-Support

Friday, February 27, 2009

News on UFaceKit

IP-Review passed

This is a great day in the short life of UFaceKit. We passed the initial IP-Review for our code base and I thank all the IP-Team for the great assistance and help to make our code base IP-clean.

Abstraction of Application-Bootstrapping

Until today the start up process of an application has been Toolkit specific (e.g. spinning the event-loop) this is now abstracted in a new interface called UIDesktop which can be compared to the mixture of SWT-Display and the Eclipse-Workbench.

This abstraction means that switching from SWT to QT means switching exactly one factory and that's it. This new UIDesktop concept is also a result of discussing a potential OpenGL-Implementation of the UFaceKit-API with one of our employees.

public void startup(UIFactory factory) {
UIDesktop desktop = factory.newDesktop();

desktop.runWithDefaultRealm(new UIRunnable() {

@Override
protected IStatus run(UIDesktop element) {
createUI(element,uiMethod);
return Status.OK_STATUS;
}
});

desktop.run();
}

// Creating application with SWT
startup(new JFaceFactory());

// Creating application with QT
startup(new QTFactory());

A first real world application

One of our employees is rewritting our one of our applications using UFaceKit and is making good progress. Writing a real world applications helps us to fill the last missing gaps in API. Maybe I can already show an intial version of the application on EclipseCon 09 then people can see a real world application using UFaceKit + EMF + CDO in my talks:By the way I'm nominated for 2 Eclipse-Awards

Saturday, January 17, 2009

Getting started with UFaceKit and QT

QT and UFaceKit

So the big news this week in opensource space was the announcement of Nokia to release their C++ cross-platform widget toolkit under LGPL. This is great and people now once more start to request a SWT-Port for QT. I don't know if any company is going to invest the development resources into such a port at least I haven't heard anything.

From UFaceKit point of view the announcement is great because we've been working since some time on an UFaceKit-Implementation for QT. Today I invested some time to implement features to render the AddressBook-Application i showed you in my last blog entry

Below is the application rendered using the CleanlooksStyle on MacOSX:



The only change to the code I showed you last week is how the application is launched.
For SWT the launcher looks like this:
public class Launcher {
public static void main(String[] args) {
final Display display = new Display();

Realm.runWithDefault(SWTObservables.getRealm(display), new Runnable() {
public void run() {
JFaceFactory factory = new JFaceFactory();
Workbench workbench = new Workbench(factory);
workbench.open();

while( ! workbench.isDisposed() ) {
if( ! display.readAndDispatch() ) {
display.sleep();
}
}
}
});
}
}

And for QT:
public class Launcher {
public static void main(String[] args) {
QApplication.initialize(new String[0]);
QApplication.setStyle(new QCleanlooksStyle());

Realm.runWithDefault(QTObservables.getRealm(), new Runnable() {
public void run() {
QTFactory factory = new QTFactory();
Workbench workbench = new Workbench(factory);
workbench.open();
QApplication.exec();
}
});
}
}


And now with styles applied the whole application looks like this:



I'm still in the process to make myself familiar with the QT-API and how I'm supposed to use and implement certain functions. Even if you don't want to use our UFaceKit-API the work we are doing here is interesting to you probably because we provide for example QTObservables for use with Eclipse-Databinding and a Combo/List/Table/Tree-Viewer implementation for QT-Controls.

UFaceKit Dokuware

I was asked to provide instructions how to get the applications I show in my blog running the locally and play with them. I've opened a new section in the Eclipse-Wiki holding all informations about our project - outlining our goals, instructions how to get the current code base running, and hopefully much more information soon.

Wednesday, January 14, 2009

Pimp your application L&F with UFaceKit

Does your application look like this or hopefully a bit better than this really ugly example?

Making applications look nice and still not cluttering your code with these theming informations is something not provided out of the box by Eclipse. Still the situation is changing since the E4-Team is working on "native" SWT-CSS integration (Kevin McGuire and Kai Tödter) - if I'm not mistaken the code should in theory also work in 3.x.

But besides E4 there's another project called UFaceKit which provides a high-level widget-toolkit API (the application above is written with UFaceKit in about ~250 Lines of code) and part of this high-level abstraction is direct support for Declarative-Styleing.

Let's at first take a look at the above application. I've split it into 3 Classes:

When coding with UFaceKit and you choose to use the SWT-Implementation (we also provide Swing and QT though SWT is the most stable and feature rich) you get the native platform L&F (as you see above) but the application is not really visually appealing.

If you don't have support for declarative styling you'd now have to clutter your code with themeing informations (e.g. setting background-colors, ...) and your code is soon getting unmaintainable. The Web-Guys already found this out for a while and invented CascadingStyleSheets (CSS). So why not learning from them and bring CSS (I more like the term Declarative-Styleing) to the world of Java-Desktops.

As mentionned before the E4-Team is working on CSS support and so does UFaceKit but this is not the only thing. UFaceKit abstracts styling support and you can plug-in your own declarative syntax. Out of the box we support:

  • CSS: Like you know it from Web-Development. We currently don't support all features from CSS2 but only the most important ones

  • USML: UFaceKitStylingMarkupLanguage is a very simply XML-Definition for css-like styles which has the adavantage that it doesn't add any dependencies like CSS-Support does


As state we don't suppport all features CSS2 defines but a subset of the most important things:

  • ID-Definitions like #myelement { }

  • Class-Definitions like .mylabel { }

  • Element-Definitions like UILabel { }

  • Support for pseudo-Attributes like :hover, :focus

  • Support for attribute-selectors like .mylabel[@value >= 10]


Let's see what we can achieve by adding this styling support our application.


Amazing isn't it? No single line of application code has changed between those screenshots! As you might noticed I've used Kai Tödters E4-Example application as master and the data is backed up in XMI useing the EMF-Toolchain.

What can you expect in future from UFaceKit:

  • Working on better support for Swing (many Styling things are missing)

  • Working on better support for QT (some styling and control things are missing)

  • Finishing implementation of current API functions

  • Adding JUnit-Test, ...

  • Declarative Syntax to describe and visual design your UI using EMF

  • ...


As you see there's much work that needs to be done and if you are interested in helping out you are more than welcome.

Thursday, January 08, 2009

Where do you go (JFace)Viewers

The presence


Today I thought about a problem of JFace-Viewers when it comes to clever memory management like it is provided for example by CDO. CDO has a very clever memory management concept where objects are swapped out of the memory if they are not referenced in application code.

When using CDO in conjunction with JFace-Viewers this concept doesn't work because JFace-Viewers restore the model element into the TableItem/TreeItem-data-slot and so CDOs clever memory management is not working and the whole model resides in memory.

Inspired by Ed's efforts to minimize the memory footprint of EObject (see bug 252501), I started to think how we could improve on the other side of the fence. I've started today implementing a set of specialized viewer classes which makes it possible for you to take advantage of the clever memory management supplied for example by CDO.

The idea is simple. Instead of restoring the real object in the viewer the object gets translated into a key value (in case of CDO it could the a CDOID) and so CDO can free memory ASAP. The code is available from the UFaceKit-Repository because the scope of UFaceKit is also to provide higherlevel utilities for current Eclipse-Technologies beside inventing it's own high-level API.

The future


The Viewer-Concept provided by JFace for StructuredControls (Combo, List, Table, Tree, TreeTable) is one of the most used concept in Eclipse-Applications and although they are very powerful and we fixed many deficiencies we could provide much better useablility and user experience in E4.

Some of them coming to my mind are:

  • No Toolkit-Independence we can only target SWT like controls

  • Usage of Java5 generics

  • Multiple different APIs to achieve solve a problem

  • Problem with memory intensive models

  • (Fill in your favorite problem)



If you are a regular reader of my blog you know that in my UFaceKit-Project I've already written a JFace-Viewer like implementation for other widget toolkits (QT, Swing). I've today restarted think whether this would be a good thing for E4 in general and so I filed bug 260451.

I'd like to see Eclipse-Viewer getting a project like Eclipse-Databinding which is split into a general and toolkit specific part and integrate itself seamless into the concepts provided by Eclipse-Databinding. I'd invite all of you to take part in a renewed implementation of the viewer concept by adding yourself to bug 260451 and take part in the design discussion hopefully takeing place there.

The intial list of points I'd mentionned in the bug are:

  • Cross-Toolkit like Eclipse-Databinding I'd like to see Viewers getting split
    a Toolkit-Neutral and Toolkit-Specific API so that implementation for e.g.
    Swing, QT, ... can be created.

  • Better support for big model graphs (e.g. better support for CDO) (see bug
    260422
    )

  • Revised inline editing

  • Direct-Databinding support

  • Builtin support Async-Programming (see bug 253777)

  • Support for Java5-Generics

  • Builtin databinding support (e.g. a Viewer could direclty implement the
    IObservableValue interface)