Tuesday, June 26, 2007

Branding for Windows (How to create .ico files automatically)

After some time not having developed for Win32. I today had to brand a small RCP-application and once more completely forgot how to create this "Programm Launcher icon" using opensource tools.

So I thought I have to restore this information somewhere I can find it later on:

1. Get nice icons:
The starting point for me is one of the open-source icon-collections (www.icon-king.com/) or oxygen.

2. Boot you favorit Linux Distro (Sorry Win-Users for you this story ends here (or you grab CygWin)):
Install the following tools:

  • convert: Chances are high it's already installed

  • icotool: if not installed and not available for your distro (icoutils)

3. Copy the images:
Copy images the images the with the various sizes we need to a directory and given them eaually starting names. In my case these are:

  • icon_16_16.png

  • icon_32_32.png

  • icon_48_48.png

4. Create .ico-File:
The ico-File needed by RCP has to hold 6 images (32bit and 8bit).
So we need to convert the images to 8bit ones:
tom@vinea:icons>

mkdir target

# Workaround because image magick doesn't seem to reduce colors when
# converting from png to png
convert -colors 256 icon_16_16.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_16_16_8bit.png

convert -colors 256 icon_32_32.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_32_32_8bit.png

convert -colors 256 icon_48_48.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_48_48_8bit.png

Copy the original icons over to target-dir:
tom@vinea:icons>
cp -f icon_16_16.png target
cp -f icon_32_32.png target
cp -f icon_48_48.png target

Create the .ico-File using icotool:
tom@vinea:icons>
icotool -c target/icon_16_16_8bit.png target/icon_16_16.png \
target/icon_32_32_8bit.png target/icon_32_32.png \
target/icon_48_48_8bit.png target/icon_48_48.png \
> target/icon.ico

Here's the full script for reference:
#!/bin/sh

rm -rf target
mkdir target

# Workaround because image magick doesn't seem to reduce colors when
# converting from png to png
convert -colors 256 icon_16_16.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_16_16_8bit.png

convert -colors 256 icon_32_32.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_32_32_8bit.png

convert -colors 256 icon_48_48.png target/tmp.gif
convert -colors 256 target/tmp.gif target/icon_48_48_8bit.png

# Copy images
cp -f icon_16_16.png target
cp -f icon_32_32.png target
cp -f icon_48_48.png target

icotool -c target/icon_16_16_8bit.png target/icon_16_16.png \
target/icon_32_32_8bit.png target/icon_32_32.png \
target/icon_48_48_8bit.png target/icon_48_48.png \
> target/icon.ico

Friday, June 22, 2007

Why do developers need Code-Snippets

Many of you may already have noticed that we started a Snippet collection for JFace-Elements like the one you know from SWT. Yesterday I updated the wiki-page to show all snippets with a short description.

Are Snippets only something we provide because we love our users soooo much? To me the answer is no.

There are multiple reasons why snippets are a great thing:

  • Help for users to get started easily (Users)

  • Useful templates for users to log bugs (Users/Developers)
    Without a reproduceable testcase it is very hard to track bugs. Be prepared that JFace-Devs will insist even more on Snippets because now you have starting points to create Snippets easily. Insisting on snippets we often found out that we are not the one to blame but someone different (including the bugreporter itself)

  • Useful to mark bugs as invalid (Developers)

  • Useful to check no regressions are introduced (Developers)
    We also added snippets to our collection although their Classes are deprecated because this way we had an easy test case that we don't break any backwards contract. In our case we did this for TableTreeViewer

  • Development example for new features (Developers)
    A good example is Snippet026 which was used to develop Cell-Navigation and Editor-Activation throughout the whole 3.3 cycle.

  • Advertise new API

Tuesday, June 12, 2007

I'm perFLEXed

Yesterday Adobe released it's Flex 3 and naturally I went there to see this new cool technology. I downloaded it and got an Eclipse with a GUI-Builder to create SWF-Applications. The nice thing is that Flex uses an XML-Format to store the GUI, ... .



I guess you know what's coming now, don't you? I sat down and looked closer to find out that it would be fairly easy to write a Transformer to convert this in my custom EXSWT-Format used to build SWT/JFace-GUIs. After about 2 hours I now have a minimal XSLT-Stylesheet transforming MXML-Elements (currently mx:label, mx:combo, mx:button) to EXSWT and feeding it into my EXSWT-Lib. The only problem are different heights and widths needed by SWT and SWF but those are minor problems.

Here's the original Flex-Project View one can export as an SWF-Application:



And here the one displayed using SWT-Widgets:



This is only a simple example but it shows how easy it is to define highlevel dialects on top of EXSWT which is a more or less lowlevel XML-Language.

You can as always get the sources from my SVN-Repository and I have once more prepared a .psf-File for all Subclipse users.

Splash-Screen and Threads

Today I thought it would make my application look much more professional if the login-dialog is part of the splash-screen. The new extension point added in eclipse makes this possible and even provided an template implementation I could use without problem.

The process is straight forward:
  • Create a Product Configuration (or use your existing one)
  • Switch to the Splash-Tab
  • Select in the Customization-Section the Interactive-Template
  • Switch to the Overview and "Launch an Eclipse application"
You are done. That was easy, wasn't it? To make this work you wouldn't need any help. The tricky thing I faced starts now. In my case I'm authentificating using a database-server and to not block the UI im doing this in a seperate thread and showing a ProgressBar in the mean while.

When the application starts up the splash should look like this:

And while Logging into Database:

So the first action is to add the "Check Login"-Label and the Progress bar like this:

private Label progressLabel;
private ProgressBar progressBar;

/** many lines of code */

private void createProgressInfo() {
progressLabel = new Label(fCompositeLogin,SWT.NONE);
progressLabel.setText("Überprüfung läuft");
GridData data = new GridData();
data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT - 50;
progressLabel.setLayoutData(data);
progressLabel.setVisible(false);

progressBar = new ProgressBar(fCompositeLogin,SWT.NONE|SWT.INDETERMINATE);
data = new GridData(SWT.NONE, SWT.NONE, false, false);
data.widthHint = F_TEXT_WIDTH_HINT;
data.horizontalSpan = 2;
progressBar.setLayoutData(data);
progressBar.setVisible(false);
}

private void toggelCheckProgress(boolean state) {
progressLabel.setVisible(state);
progressBar.setVisible(state);
fCompositeLogin.layout();
}


We initially set the those two widgets invisible and show them later when we start the authentification. To make this easy we add helper method to turn the visibility on and off.

The next part is to modify the handleButtonOKWidgetSelected()-method like this:

private volatile int loginStatus = -1;

/** many lines of code */

private void handleButtonOKWidgetSelected() {
final String username = fTextUsername.getText();
final String password = fTextPassword.getText();

toggelCheckProgress(true);

Thread t = new Thread() {

public void run() {
if( login(username,password) ) {
loginStatus = 1;
} else {
loginStatus = 2;
}
}
}
t.start();
}

The content of the method is straight forward. It starts a thread and executes a potentially long running task in our case login(String,String). Our task is now to sync back to the gui-thread and:
  1. Proceed with start up (hiding the login details from the splash-screen)
  2. Display Login-Failure to the user
Normally you do this using Display#(a)syncExec() but that's not available in the splash-screen. The work-around I used as you see above is setting a special variable named loginStatus. The trick is now that you add checks for this variable to the Event-Loop method which looks like this afterwards:

private void doEventLoop() {
Shell splash = getSplash();
while (fAuthenticated == false) {
if (splash.getDisplay().readAndDispatch() == false) {
if( loginStatus == 1 ) {
loginSuccess();
} else if( loginStatus == 2 ) {
loginFailure();
}

splash.getDisplay().sleep();
}
}
}


Your are nearly done now the only two methods missing are:

private void loginSuccess() {
toggelCheckProgress(false);
fCompositeLogin.setVisible(false);
fAuthenticated = true;
loginStatus = -1;
}

private void loginFailure() {
toggelCheckProgress(false);
loginStatus = -1;
MessageDialog.openError(
getSplash(),
"Authentification failed",
"Your username or password was wrong");
}


Well that's all. You are done and have a splash screen who is authenticating without blocking the UI-thread without Display#(a)syncExec. I need to thank Kim for pointing me to this solution and she promised that there will be added API in 3.4 to make this more easier.

Saturday, June 09, 2007

Things are evolving

It's been now a few months I started reworking my the first draft implementation which already provided many interesting things but there was still Java-Code needed to bind-POJOs and to interact with the Datasource.

What's new:
  • XBL (XmlBindingLanguage) to connect your model with the help of the databinding framework to SWT-Widgets
  • Switched to work on top of the Eclipse-Command-Framework
  • Added themeing framework
  • API cleanup
  • Refactoring, refactoring
I still see this as a research project which is not useable for production in the near future but if the community likes what I'm doing here these are the next things on my list:
  • implement INSERT/UPDATE/DELETE on top of the COMMAND-Framework
  • evolve XBL (new features, refactoring, ...)
  • Transformer-Framework for EXSWT and XBL (use a highlevel dialect translated to those low-level ones)
  • Implement new provider which is able to fetch XBL and EXSWT files via HTTP. This would make changing the GUI without the need to redeploy your application to the client (what a cool feature RAP without the Browser :-)
  • Refactoring, Refactoring, ....
If you are interested you can checkout the current project from my companies SVN-Repository. When using the Subclipse-Plugin I've added you a .psf-File to the project helping you to easily checkout all needed projects from SVN.