Showing posts with label rcp. Show all posts
Showing posts with label rcp. Show all posts

Thursday, July 12, 2007

Selection service, archimedes and docs

Once again I am too late to keep my old pace. Anyway, the end of the semester is always very time consuming.

Anyway, I would like to comment on a few things about RCP today.
I learned a few stuff about it lately. First thing is that there is a very nice tutorial about it at http://www.eclipse.org/articles/Article-WorkbenchSelections/article.html. The other thing is that this selection service can be quite useful if you start working with it from scratch.

Archimedes didn't, until now, had anything to do with that service and refactoring it to use the service will be another big work. With this, there are now 5 tasks that have top importance:
  1. Remodel the intersection finder system
  2. Re implement persistence support with XML/Arc, images, pdf and svg.
  3. Refactor Archimedes to make it profit from RCP's selection service.
  4. Adapt Archimedes and its plugins to be built with maven.
  5. Improve Developer support and User support.
I listed those without a priority order but I am sure those are top level.

I should be getting more time to write here and to code during the next semester since I am quitting my job to dedicate to my masters.

The development speed, however, will probably not improve a lot since I am now almost on my own to code. I might get some help from one or two volunteers but it won't be enough to keep the pace from last semester.

Apart from that, regarding documentation. I finished translating an article I wrote with Mariana last semester for the FISL. She needs to read it and correct all my numerous mistakes but the big boring part (translating) is done.
In the same subject, we are preparing another article in English to present Archimedes at the Eclipse Technology eXchange that will be held at the OOPSLA 2007 in October at Montreal. Once we finished it, I will release it somewhere on the net and post the link. If I can, I will try to do it one week before the submission date so that I can hear critics.

Basically that is it. I wish I would write here more often since I probably don't post all I could and would like to. But, hey, it's life right? So seen you soon (hopefully).

Monday, June 25, 2007

ToolBar paths and Archimedes news

The end of the semester is always a disaster. Tons of things to do and not enough time.
For once I don't have tons of tests, the only hard work is to maintain the job, the work on Archimedes, the studies and the corrections going.

Anyway, enough complaining.
I got some news about Archimedes:
This release is coming to an end but I am proud to say that most of the work that should have been done is complete. There are a few details missing but those are mostly related to difficulties we are finding with RCP.
Both the import and the export feature that will become the save and open one are finished, all that is left to do is to integrate this with the platform so that the users can enjoy all the flexibility of Eclipse's wizards.

Also, Mariana is now responsible for releasing updates for the old 0.17.x version and get our bug fixes and new features ported to that platform until the RCP one is not perfect. I wish her luck and hope to see a lot of report from you guys when she does.

Most of the reported bugs have been correct so far and I even learned how to organize the action icons on the toolbar. This means that, from now on, Archimedes' toolbar will be a bit more organized than it was before.

Since I found absolutely NO documentation about this, I wanted to write a little bit about how to make it work. It is quite simple but worth saying.

Mainly, when you extend org.eclipse.ui.actionSet and create an action, you can add two attributes: menubarPath and toolbarPath. The first one is quite decently documented so you can find several tutorial that will explain you that you should add some MenuManagers in your ApplicationActionBarAdvisor and then refer to the paths you set on those managers to decide where the actions should appear.

Regarding the latter, you will find almost nothing. I've search a lot and very little is published to explain you one very tiny and simple thing: It works EXACTLY the same way. May sound stupid for me to say it like that but if you have no documentation or example, this may not be evident because when you create ToolBarManagers, you cannot add slots within those to specify boxes where the actions should appear. However, you must pretend that you did. In most cases, this will mean that you will simply copy paste whatever you did on the menubarPath to the toolbarPath.

I am pasting a simplified version of the fillMenuBar method and the fillCoolBar one as well as a couple of plugins that add actions to those slots.


protected void fillCoolBar (ICoolBarManager coolBar) {
  IToolBarManager fileBar = new ToolBarManager(coolBar.getStyle());
  coolBar.add(new ToolBarContributionItem(fileBar, "file"));
}


and


protected void fillMenuBar (IMenuManager menuBar) {
  MenuManager fileMng = new MenuManager("File", "file");
  fileMng.add(new GroupMarker("start"));
  fileMng.add(new Separator());
  fileMng.add(new GroupMarker("end"));
  menuBar.add(fileMng);
}


With those method set up, you can add plugins (or just your RCP application xml descriptor) that use those paths:


<actionSet description="The action set containing some file actions."
  id="br.org.archimedes.example.actionSet" label="File Action Set"
  visible="true">
    <action icon="icons/my_icon.png" style="push"
      id="br.org.archimedes.example.action"
      label="My Action" tooltip="An example action"
      menubarPath="file/end"
      class="br.org.archimedes.example.MyAction"
      toolbarPath="file/end"/>
</actionset>


If you just add a couple more of those plugins, you will see that all the actions will be grouped both on the menu and on the toolbar.

And that's about it for now. Have fun guys.

Thursday, June 7, 2007

A tutorial for programmer

I think I will just have to admit that no mather how often I hope to publish news on this blog, I will always be late. But the fact is, running late is the only thing that pushes me to write here so I will keep trying to keep a reasonable pace and I will keep complaining about being late. I hope you guys don't mind.

As for now, I have some news although not many. Archimedes is quite stuck this week since today (thursday) is a holiday and it was half of our programming time. The other half was monday and we didn't used it to program for once. It was burned down making up a talk and a demonstration about how to develop plugins for Archimedes.
I've tried to keep all the documents in english so I could share them later on the internet but I still have a big work to do: the screencast.
The talk was composed of three parts, two of which I made and the first one was made by an Archimedes collaborator (Julien Renaut). It is mostly focused on programming problems and how people can add features to Archimedes. His talk was about extensions and extension points which are some concepts used by eRCP to allow plugins to add functionality to the main software. His work was done in Portuguese but I will translate it and insert it into the main talk I will upload.
The second part was my talk which was a lot more about Archimedes and how our main structure works. It tries to let people understand the flow of information within the software. It has a couple of "UML" (those are not really UML but kind of) figures and a nice review about Archimedes' main classes. I need to add the notes on this talk so that people can look at the talk and understand what I was trying to talk about.
The third and last part was a small example of how to create a plugin project that would add a new element to the software. This is quite a long work and I want to have a screencast of that with my voice explaining what is going on. So it will probably take me some time (maybe a month) to have it all working fine.

Also, there is a volunteer architect building up a user guide much better than anything we could ever produce. It is currently ongoing and is in Portuguese but as soon as it is finished, I will ask for help on translating this to several languages.

Speaking of languages, I am getting desperate to have Archimedes' build system working with maven 2 has said before. This would allow me to have a src.zip deploy once more as well as a nice translation zip file to have people translating the software more frequently and easily.

So that's what I've been doing. I've also been working hard to try to solve the problems from the uva gadget but I've been failing a lot which is not really keeping my moral up. :( Also, my desktop seems to have died on me. This doesn't means many loses at the moment but makes me quite upset and will probably take me some precious time to fix. Until then I might just not have anything to test Archimedes on Windows or Linux so I hope you guys keep sending us reports.

That's it. Bye bye!

Tuesday, May 8, 2007

Combos as Contribution Itens on rcp

Okay! Maintaining the post rate for more then 1 day. My current record so far.
This time I will focus on a problem I had last week while implementing Archimedes' layer combo. Using combos in SWT is quite simple, you just create it linking it to its parent and add the texts. In an RCP application things are a bit more complicated since the widgets are positioned in the parent composite only when needed. This basically means that the ContributionItem abstraction is a closure to insert those widgets when needed.

I've implemented about 3 or 4 times this class because I had several problems and couldn't understand why since I got no exception message and the widget just wasn't being shown. I created this implementation thanks to an example posted in this mailing list (http://dev.eclipse.org/newslists/news.eclipse.platform.rcp/msg00952.html) by Jean-Michel Lemieux (author of "Eclipse Rich Client Platform: Designing, Coding, And Packaging Java Applications", one of the best books about eRCP I found). You can find a more complete implementation of this in Archimedes (br.org.archimedes.gui.rca.LayerComboContributionItem) but here goes a simplified version.


public class ComboContributionItem extends ContributionItem implements
  IContributionItem {
  private Combo layersCombo;
  private CoolItem coolItem;
  private List texts;
  public ComboContributionItem(List texts) {
    this.texts = texts;
  }
  public void fill (ToolBar parent, int index) {
    ToolItem item = new ToolItem(parent, SWT.SEPARATOR);
    Control box = createLayersCombo(parent);
    item.setControl(box);
    item.setWidth(500);
  }
  public void fill (CoolBar coolBar, int index) {
    Control box = createLayersCombo(coolBar);
    int flags = SWT.DROP_DOWN;
    if (index >= 0) {
      coolItem = new CoolItem(coolBar, flags, index);
    }
    else {
      coolItem = new CoolItem(coolBar, flags);
    }
    coolItem.setData(this);
    coolItem.setControl(box);
    Point toolBarSize = box.computeSize(SWT.DEFAULT, SWT.DEFAULT);
    coolItem.setMinimumSize(toolBarSize);
    coolItem.setPreferredSize(toolBarSize);
    coolItem.setSize(toolBarSize);
  }
  private Control createLayersCombo (Composite parent) {
    Composite top = new Composite(parent, SWT.NONE);
    GridLayout layout = new GridLayout();
    layout.marginHeight = 0;
    layout.marginWidth = 0;
    layout.verticalSpacing = 0;
    layout.horizontalSpacing = 0;
    layout.numColumns = 1;
    top.setLayout(layout);
    layersCombo = new Combo(top, SWT.READ_ONLY);
    for (String text : texts) {
      layersCombo.add(text);
    }
    layersCombo.setLayoutData(new GridData(GridData.FILL,
      GridData.BEGINNING, true, false));
    return top;
  }
  public void fill (Composite parent) {
    createLayersCombo(parent);
  }
  public void setText (String text) {
    if (layersCombo != null) {
      layersCombo.setText(text);
    }
  }
}


I've cut the package and imports info but this should not be hard to add. I suggest you just copy this code and alter it to match your needs slowly so you see the result. If you have any problem with this code or need help because things are not rendering, please contact me.

With some minor changes on this code, I managed to enable the layer combo once again. Which means Archimedes is now back with Layers. The layer editor is still a bit buggy since the last refactoring but it should be solved very soon. I hope I have some nice screenshots by the week end with everything solved out.

See you later guys.

Sunday, May 6, 2007

Loading files with RCP

Keeping my efforts to post about interesting things instead of just complaining most of the time like I use to do, today, I will write about how discover the file path of certain files from within an RCP application.

First of all, the problem of loading a file in that situation must be explained. It sounds a bit stupid to explain something if it seams there is no problem to solve, right?
So, loading a file when you are coding an RCP plug-in is a problem because you can never know where your application will be relatively to the plug-in. You could hack some way out of this by assuming some things about your platform since eRCP, by default, generates always the same structure. But the fact is that this could be broken by just a few minor changes on your platform. So if we want to solve the problem correctly, we have to rely on the main application to load things correctly since it knows exactly where it is and where the plugin is.

Now that the problem should be clear, let's understand what is eRCP solution to it. The first simple solution presented is implemented in the default Activator class eclipse generates for each plugin if required. This class contains a static method findImageDescriptor that loads an image with a relative path. This is very useful since most plug-ins have some kind of image that they wish to load (icons, images, etc...) but it obviously does not solve the problem of loading any file. This operation is a bit trickier because it is pretty well decoupled so that people can load things at the level they desire.

Before version 3.2, eclipse (and eRCP in general) suggested to use the method "find" implemented in the Activator class reachable from Activator.getDefault(). Since version 3.2, this has changed and that old method is now deprecated. I don't know the reason for sure but I would guess that they found out that the Activator class shouldn't contain knowledge about how to load a file. The fact is that the static class FileLocator was created to encapsulate that knowledge.

Now that class is quite simple to use and it is probably not a problem to find out how to use the FileLocator.find(Bundle, IPath, Map) method. Most of the time, you will get the bundle from you Activator class (getDefault().getBundle()) and the Map will be empty because you probably want to load a file that has no dynamic info (otherwise, check the javadoc to know how to use it). Most commons uses of this method will just instantiate a new Path with a String argument that is the path to the file relative to the plug-in's root folder. This will return you an URL instance containing the info about your bundle and the file's path. If you check it, you will notice it is not a normal path but something like "bundleentry://bundle_number/path_to_your_file". As you can guess, there is no way you can use that to instantiate a File or a FileInputStream to read it.

And that is the hard part: You will find two static methods in FileLocator that can help you:
FileLocator.resolve(URL)
and
FileLocator.toFileUrl(URL).

In most of the cases, both method will return the same correct path. But what is the difference about them? I am not sure so please do not take this info for the truth before looking for more information. From my viewpoint, the difference regards only the path you will get at the end. The first method will return URL with http, ftp, jar, etc.. protocols while the second one will only return file protocols which is, in most cases, what you desire. Having tried to explain all this, here is the code you will get to load a file from your RCP plug-in:


Bundle bundle = Activator.getDefault().getBundle();
Path path = new Path("path/to/your/file.extension"); //$NON-NLS-1$
URL url = FileLocator.find(bundle, path, Collections.EMPTY_MAP);
URL fileUrl = null;
try {
fileUrl = FileLocator.toFileURL(url);
}
catch (IOException e) {
// Will happen if the file cannot be read for some reason
e.printStackTrace();
}
File file = new File(fileUrl.getPath());


I hope this helped you guys and please feel free to ask any question if I wasn't clear on something. See you guys later.

Wednesday, May 2, 2007

Script errors & eRCP shortcuts

Well,
Let's see the good part of things: I'm posting a lot more on this blog (if that is somehow good). But as I started announcing good parts, it is quite obvious I did something wrong. Well, I screwed the script that generates Archimedes's installers. The result was that the generated zip file was all messed up with the path. Also, the installers were not adding most of the plugins with operations because I forgot to add the entries into the core. So I decided to add a package with those. I should probably enhance that system though. Too bad I won't do it so soon.

Anyway, back to what is important. Retaking that old series I promised about Eclipse Rich Client Platform. I'm going to talk a bit about the new shortcut system on eRCP. I thought this might be usefull because Archimedes' developers will have to do this a lot and a friend of mine was asking me about this and couldn't find anything around.

First thing people will notice when having to handle with shortcuts in eRCP is that all action has a wonderful "accelerator" field which seams to make this help useless. Unfortunatly, if you use that accelerator you friendly get a warning message and once you take a look at it, you'll find out that it is deprecated. Well, as you all should know, deprecated means that you can use it... for now! You have absolutely no guarantee that in a couple weeks it will still be there. Therefore we should try not to create new features with things that might disapear in a couple weeks. So we agree that we should find another solution to it. Great!

Make some research you find out that there is a new way to do accelerators that is much more flexible and powerful. The only problem is you hardly find any example or tip anywhere. After having suffered a lot to find how it should be done, I reached this not so simple way but indeed much more flexible and powerful. Here is an example from Archimedes:

<extension
point="org.eclipse.ui.commands">
<command
defaultHandler="br.org.archimedes.orto.OrtoHandler"
id="br.org.archimedes.orto.command"
name="orto"/>
</extension>
<extension
point="org.eclipse.ui.bindings">
<key
commandId="br.org.archimedes.orto.command"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="F8"/>
</extension>


What this xml does?
Basically defines two new extensions: commands and bindings.
The idea is that each command can have several bindings or diferent bindings for diferent languages or platforms, etc...

Why do you need those?

What you really want is the binding extension which defines a binding between a command and a key sequence. Of course, you need a command in order to have this binding. That's why you need the command. Now, if you pay attention I had to create a new class (OrtoHandler) to deal with the key match event. This class has to implement IHandler interface that is a publisher that allows subscribers to listen to that event and informs whether it is able to run or not and has a run method. In most cases, this will replace or be the same class you used in your Action.

There you go. Now it is easy to define accelerators for your eRCP applications.

Monday, April 2, 2007

Can't keep promisses

Okay! I admit it: I can not keep my promises regarding publication.
This is clear when you look at the blog's history and at the Archimedes' history.
So I'll try not to make any other promise. (Remark I am not making it a promise)

Anyway, regarding the automization process of Rich Client Applications: I found a nice article about using maven2 to make the whole build and testing process. You can find it here. My next mission is to take a deep look in that article and try to make archimedes use this.
It would deeply improve the build creation and maintenance and would allow me to use a continuum (or similar) server to deploy up to date sites with documentation.

Other then that, Archimedes is, at the moment, more or less like it was in version 0.6.0. This is aproximately the current status of features. The new atempt is to publish a "stable" version april 16th but I am pretty sure it will lack some of the most important features.

Anyway, that is about it. I'm using about 25% of my coding time to try and keep this blog and the sourceforge news up to date which means I am programming much less then I would like but since so many people pointed out that the projects infos should be always updated, I am doing what I can to keep this true.

I hope I'll be back next week with more news.

Wednesday, February 28, 2007

Creating a multiplatform installer (with IzPack)

Hello once again.
As promised, today I'll talk about how to create your multiplatform installer for your Eclipse Rich Client Application without having to add all the folders PDE (Plugin Development Environment) created.

First of all, understand that what I'll explain for IzPack can be used for any other installer you like. Just search for a feature similar to the one I quote in your installer and you should have no problem.
Now that this is explained, let's get started:
First of all, part of your jobs is already done thanks to the eRCP imposed architecture. I'm talking about having your project split in several parts that are almost completly independent. This is very useful since it'll allow your user to choose the plugins he wishes to install.
This reminds me of something: feature != plugins.
Your update site or your product uses a set of plugins and call it a feature if you followed most of the tutorials. This doesn't means your installer must care about your feature definitions.
The feature definition will allow your update system to know which updates it should look for and which features are considered "new features". This means that if your application is running without any feature and you ask for an update, it'll show you the core feature (which you obviously already have since you're running your application) as a "new feature" to be installed. That can be explained by the fact that sites only know about features and never look to plugins.

Therefore, a good practice is to have your core feature as a required package in your installer. Any other feature you would like the user to update through the update system should also be joined as a package in your installer. However, if you wish to offer the user the choice to install only one plugin regardless what is its feature, you can do it without further consequences. Your application will work without a problem and with this plugin activated.

So, you have decided what will be the packages available in your installer. You must know what license you'll use and you can have a couple shortcuts because it's always useful.

Now let's produce the XML file that will explain to IzPack how it should work.
Your first section of the IzPack XML should be the something like:

<info>
<appname>Your App</appname>
<appversion>@{version}</appversion>
<authors>
<author name="Tarantulus Corp." email="archimedesproject@googlegroups.com" />
</authors>
<url>http://www.archimedes.org.br/</url>
<webdir>http://arquimedes.sf.net/update</webdir>
</info>


No big secret on that. It defines mainly the first screen post language choose. Excepting 'webdir' all those fields are shown in that screen. The 'webdir' is the addressed used to search for the package if you are about to create an online installer. This is mainly the only thing that changes from a local installer to an online installer in IzPack.
The second part of your XML should be:

<guiprefs width="640" height="480" resizable="no">
<modifier key="useButtonIcons" value="yes" />
<modifier key="useLabelIcons" value="yes" />
<modifier key="langDisplayType" value="native" />
<modifier key="headingPanelCounter" value="progressbar" />
<modifier key="headingPanelCounterPos" value="inNavigationPanel" />
</guiprefs>

This is a bit more obscure. The first lines are quite easy to understand. 'landDisplayType' is not that easy however. It sets how the installer will show the options of language to the user on the first screen of your installer. In this case, native tells the software to use the system's locale to write the languages. 'headingPanelCounter' and 'headingPanelCounterPos' defines how the steps remaining and the current step should be shown to the user. If those lines are not present, nothing will be displayed.

Next you have:

<resources>
<res id="installer.langsel.img" src="installer.png" />
<res id="LicencePanel.licence" src="license.txt" />
<res id="shortcutSpec.xml" src="shortcutSpec.xml" />
<res id="packsLang.xml_eng" src="packsLang_eng.xml" />
</resources>


Okay. Now we're talking! First of all, the image to be shown in the first screen of the installer is the one on the first line. The license that will be displayed to the user and that he will be forced to accept unless it quites the install. Beware, this license should be in a text format because IzPack will display it as a text only file. The last lines regard the shortcut creation and the internationalization of this installer. Take a look on the official documentation and this should be enough.

The next part is what will define the flow of your IzPack installer:

<panels>
<panel classname="HelloPanel" />
<panel classname="LicencePanel" />
<panel classname="PacksPanel" />
<panel classname="TargetPanel" />
<panel classname="InstallPanel" />
<panel classname="ShortcutPanel" />
<panel classname="FinishPanel" />
</panels>

Those panels are available by default in IzPack. You can, however, create your own panels as well as install new ones created by the community and available mainly at IzPack's site (http://www.izforge.com/izpack).

At last, the last part is the most important one. The one that will specify each pack of your application:

<packs>
<pack name="Core" id="core" required="yes">
<description>The core of Your App.</description>
<fileset dir="@{deployDir}/win32.win32.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="startup.jar" />
<include name="configuration/config.ini" />
<include name="features/org.eclipse.rcp*/**/*" />
<include name="features/your.company.project.feature*/**/*" />
<include name="plugins/**/*" />
<exclude name="plugins/your.company.project.*.jar" />
<exclude name="plugins/org.eclipse.swt.*linux*.jar" />
<exclude name="plugins/org.eclipse.opengl.linux*/*" />
<exclude name="plugins/org.eclipse.opengl.linux*/**/*" />
</fileset>

<fileset dir="@{deployDir}/linux.gtk.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="icon.xpm" />
<include name="yourapp" />
<include name="about.html" />
<include name="libcairo-swt.so" />
<include name="about_files/**/*" />
<include name="plugins/org.eclipse.swt.*linux*.jar" />
<include name="plugins/org.eclipse.opengl.linux*/**/*" />
<os name="linux" />
</fileset>
<fileset dir="@{deployDir}/macosx.carbon.ppc/YourAppName/" targetdir="$INSTALL_PATH">
<include name="yourapp.app/**/*" />
<include name="plugins/org.eclipse.swt.*macos*.jar" />
<include name="plugins/org.eclipse.opengl.macos*/**/*" />
<os family="osx" />
</fileset>
<fileset dir="@{deployDir}/win32.win32.x86/YourAppName/" targetdir="$INSTALL_PATH">
<include name="yourapp.exe" />
<include name="plugins/org.eclipse.swt.*win32*.jar" />
<include name="plugins/org.eclipse.opengl.win32*/**/*" />
<os family="windows" />
</fileset>

<!-- The windows scripts -->
<executable targetfile="$INSTALL_PATH/yourapp.exe" stage="never">
<os family="windows" />
</executable>

<!-- The Linux scripts -->
<executable targetfile="$INSTALL_PATH/yourapp" stage="never">
<os name="linux" />
</executable>
</pack>
</packs>


Each <pack> must have one or more files registered. Those can be added using the file tag (when you want to work with one specific file) or the fileset tag (when you want to work with folders) as shown. The fileset accepts both <include> and <exclude> tags which allows you to easily create exceptions in your folders. Also, all those tags accept <os> that will be interepreted as a mark to tell the installer on which OSs those files should be unpacked. This is mainly how you separate things. The first fileset defined in the example above is the one that grabs all non-OS specific files from the RCP. The next 3 filesets are used to select os specific files as the 'os' tag shows.

At last, the <executable> tag marks the file you target as executable. This means a double click or a command will try to run those files. This is required because the installer will zip all the files in jars and loose all kind of permissions over the file on install. So it needs to know which files should be diferent from the read and write permissions.

All this should allow you to create a simple multi platform installer for your eRCP application. Once this is done, you'll probably want to add the <locale> tag to add internationalization support to your installer and then you'll need to create some language specific XML with pack descriptions translations and everything else.

A last tip, beware to export all of your features and plugins when you are in Eclipse. You'll need all the files available on your deployDir to make the installer work well.

The next post will discuss about how to create all the application, the installer and transfer all to a website using one simple script. This allows a much quicker and constant deploy of your software to your users. Expect it done for saturday or sunday.

See you guys soon. Bye bye.

Saturday, February 24, 2007

How to export multi-platform?

Well,
I hope that after those last two posts, you are already capable of adding your classes to your project and growing it without any further problems. Once this is done, I also expect that you can export your project and run it outside of Eclipse with no headache. You choose your deploy directory (which I'll call $DEPLOY_DIR) and you can run your executable software at $DEPLOY_DIR/yourapp(.exe). If this is not the case, feel free to contact me either by email or posting a comment.

So, now that you have your development environment set up and you can run your software in your platform, you probably want to export it into other operating systems (OS). For now, you don't even have this option anywhere you can find it. If you search a bit through the internet you'll discover you need the RCP-Delta-Pack to do so. Very good... but where the hell is that pack? If you search around the RCP download you'll eventually find it although it's not really very well exposed.

The way to find the up to date version is:
http://www.eclipse.org/downloads/
Choose "Other downloads for ..."
Get down to "RCP SDK" and the last file is the RCP delta pack.
For the 3.2.2 version, just click here.

Now that you have your delta-pack, it's really easy. Just unzip the file into $ECLIPSE_HOME/plugins and restart your eclipse. Now when you ask to export your application, you'll get a nice checkbox asking if you want to export to multiple platforms. If you select it, the "next" button will become active and if you click it, you'll have a list of supported OSs. Let's say you'll select macosx_ppc, linux_x86 and win32_x86 (like Archimedes does).
The export system will use the $DEPLOY_DIR and create in it, 3 folders (one for each system):
linux.gtk.x86
macosx.carbon.ppc
win32.win32.x86
And each of these folders will contain all files needed to run the software on these OSs with those graphical interfaces.

If you take a look, you'll find that much is common to all OSs and we hope so, since it should be a platform-independent software. I cared to take a deeper look and list what is common and what is not.
Mainly, the "configuration" and "features" folder are identical. The "plugins" is mainly identical, the only thing that may change is a couple of plugin fragments that are OS specific (like "org.eclipse.opengl.linux" and "org.eclipse.open.macosx"). If the fragments have requirements regarding the OS, they will be selected only by the OSs that support that requirements. Careful about that! If you depend on a plugin that has a fragment like that one and it doesn't get exported, you'll get the friendly "There was an error. Please check .metadata/.log for more details." message. If you check the log, you'll find the also friendly (but known already) "No application ID found" message.

The root folder, however, is quite diferent depending on the OS you look. The only file that is always available is "startup.jar" which contains the basic RCP plugin system which will activate whatever needs to be activated.
All the rest is quite diferent. For example:
Windows has only a "yourapp.exe" file.
MacOS X has a whole folder "yourapp.app" with a nice deep structure required to make your software run like a native Mac software.
Linux is the most poluated one. It has "youricon.xpm", a folder "about_files" and a page "about.html", "libcairo-swt.so" and a "yourapp" executable file.

Now why is that important? Because you will probably want to make an installer (like Archimedes does) or a common package that would allow your users to download once the core and add the OS specific files as they need it. In this case, you'll need to know what is core and what is OS specific.

I'll stay here for today but my next post will be about creating this installer. I'll use IzPack (http://www.izforge.com/izpack) to make the example because it's what Archimedes uses and it is very simple and powerful. You can probably, however, use the example in any installer you'd like just adapting the procedure.

Thursday, February 22, 2007

Your first problems with RCP

Well,
Now that we had a good start with RCP, we face a couple of problems upgrading our application. First of all, if you are a curious person (and this is a good thing), you might be facing a couple of problems while trying to run your application from outside of Eclipse.

Problem number 1:
You can run your application from within Eclipse but when you try it outside of Eclipse you get a: "No class definition found ...".
If you are having this problem and the class that can't be found is one of your own, you probably made the wrong move! Check on your MANIFEST.MF file if you have a line: "Bundle-ClassPath:".
If you don't, you have gone even further that I though. Add it quickly!
If you have it, check that the path '.' is there. You MUST have '.' as a class path for your application or else none of your classes will be found.

Okay! That was easy to solve now that you found the solution.
You move along and you get challenged again:

You probably created your first RCP application with a product that was based on plug ins, right? Now it's time to move it to feature based architecture. Great! That will enable your application to benefit from the update features.
Go ahead! Change your product file to be feature based. Once you done that, all works perfectly within Eclipse but, again, when you run it outside, it does not works.

Problem number 2:
You can run your application from within Eclipse but when you try it outside of Eclipse you get a: "No application id found ...".

Okay! First thing to do, check the plug in folder from your application. It should contain all plug ins that are necessary to run you application. If one plug in is missing, you get the "No application id found ..." message.
If this does not help you, try opening the file "$YOUR_APP_HOME/workspace/.metadata/.log" with the Error log view in Eclipse. Take a look at the most recent entries. You should see the "No application id found ..." message and some warnings surrounding it.
Take a good look over the warnings looking for one of them that says something about "Bundles missing". It should be extensible. Extend it twice, you'll get a list of missing bundles. Those are the plug ins that the RCP is trying to load and is not finding. Search for errors within those plug ins or if they are available. Once they do, it should restart working once more.

Wonderful! So now you are feature based and your application works perfectly well inside and outside of Eclipse. Time to create an extension point for your application. Eclipse really helps for that. It creates all the necessary files for you and you can focus on whatever you want.

Problem number 3:
You want to define your extension point and you would like it to have children. Like in:

<extension-point id="myapp.myext">
<myext id="ext3">
<status name="fileSystem" />
<status name="swap" />
</myext>
</extension-point>

First of all, when creating your extension point, you'll find out that PDE 3.2 won't let you create a new definition within the extension point element. Don't worry! That's normal. It just doesn't create the xml tree at definition it understands when you use it. Second thing, just like the extension point, you can't create a new definition within your extension-point. Again, same procedure: ignore it and create it after your extension point definition but use it inside and all will go fine.

Now you have your extension points created. Time to create a new project that will extend this point. Go ahead! It's a good idea. So you start and once you done the whole thing you get a warning: "Illegal child element ..." at your "plugin.xml".
Well, my tip: Ignore it! It's a know bug from PDE 3.2 that is already fixed at the repository.

Well, those must be the first problems you'll face with RCP and probably the once you'll loose more time. After this, you understand the errors a bit faster and starts not getting stucked for stupid reasons like I did. :)

If you have other problems with or without solution, please post them and I'll do my best to help or to spread the solution a bit more.

Enjoy yourselves!

Saturday, February 17, 2007

Why Eclipse's RCP?

Well, let's start producing something interesting:
First of all, there are two things that you may be thinking of doing that will make you choose to work over Eclipse's Rich Client Platform (eRCP from now on):
  1. You want to develop a plug in for Eclipse. In such case, you have absolutely no choice. You will have to work over eRCP. On the other hand, you will be doing a lot of things that other persons already did and you will find several tutorials and samples that can help you.
  2. You want to develop a standalone application of your own. This will be the focus because it's doing this that you will find most problems.
Okay then, you want to develop your standalone application.
Why should or shouldn't you work over eRCP?

Mainly, what you will gain from working over eRCP is a very strong extensibility for your application with a great architecture as well as a very decent internal update system and a nice help system. Wow! Wonderful right? And there is more! If you start now, you get a "native" cross-platform application for free!

Ok! I got a bit too far with that last sentence. So let's keep cool, not all applications are meant to be developed using eRCP. So what are the counters?

You will spend some time learning how eRCP works. And when I say some time, I mean something like 3 or 4 days totally lost doing things you don't really understand how they work.
You will also have some megabytes inserted into your software even before you have anything working. To get an idea, if you use all the features I quoted before, before you have any code of your own, your application will already have some 16 Mbs. If your application is meant to be light weight, forget it!
At last, you will have to adapt to eRCP's architecture and believe when I say it: It's a very very good architecture but it forces you to achieve, at least, a very good architecture level. This may take you some considerable time (I'm still trying to reach it).

So, okay, when should I use eRCP than?
When you want to develop a pluggable application, flexible, very strong.
When you want/need a very good Internet update system.
Let's say the help system is a bonus because it is not that hard to do in any standalone application.

And when shouldn't I use it?
When you want things to go quickly, you have little time to do your little application.
When you don't need plug ins.
When you have limited memory or processing.

Okay! But you don't like IBM/Eclipse... is there an alternative?
Yes. Sun Microsystems has the Netbeans Rich Client Platform (nRCP). It has almost all the features eRCP has but you'll loose a bit of community support since it's much less widely used and you'll win good documentation because Sun manages to have some very competent documentation writers.

Now that we are set about what is Eclipse Rich Client Platform, I'll leave you some links where you can have more insights about it:
http://wiki.eclipse.org/index.php/Rich_Client_Platform (RCP's faq and official RCP's site)
http://www.eclipse.org/articles/Article-RCP-1/tutorial1.html (The first part of a trilogy article from Ed Burnette. Very useful to start with RCP)
http://www.eclipse.org/articles/Article-Branding/branding-your-application.html (an article to read after Burnette's one by Andrew Eidsness and Pascal Rapicault)
http://eclipsercp.org/book/ (The best book I found for eRCP though it's not free)

Of course you can find much more looking over the Internet for "Rich Client Platform Eclipse" or "Rich Client Platform Netbeans" or just "RCP your-topic".

The next step is to start developing your own RCP application from scratch but you'll have to wait until I'm back from the Brazilian Carnival for that. See you next week!