Skip to main content

Working XML: Use Eclipse to build a user interface for XM

Making improvements based on experience and user feedback

Benoit Marchal (bmarchal@pineapplesoft.com), Consultant, Pineapplesoft
Benoît Marchal is a consultant and writer based in Namur, Belgium. He has just released the second edition of XML by Example. More details on this topic are at marchal.com. You can contact Benoît at bmarchal@pineapplesoft.com.

Summary:  Anyone familiar with XM -- the low-cost, open-source content management solution based on XSLT -- knows that for all its good points, it still lacks a decent user interface. In this article, columnist Benoît Marchal uses the Eclipse platform's open universal framework to build a user interface for XM.

View more content in this series

Date:  01 Oct 2002
Level:  Introductory
Activity:  4615 views

After wrapping up my discussion of XI in my previous column, I decided it was time to revisit XM, the simple XML content management and publishing solution with which I kicked off this column. In the last year, I have been using XM for various projects and I have heard from readers as well. Throughout the year, I collected suggestions on what should be improved. In this article, I will show you how to create a user interface for XM. I chose to use Eclipse, an open-source project, to build an adaptable programming environment. I believe this article provides useful information for any would-be Eclipse developers, even if they have no interest in XML.

Work areas

Here's what I learned about XM and how it should develop: The user interface is the most urgent problem. As discussed in last month's article, I realized I made a mistake releasing XM without some sort of graphical user interface. This decision proved incoherent with the user-friendly features such as no configuration files.

Directory walking needs improvement as well. The simple solution that treats one file at a time limits the ability to manage links and makes content generation (when XM compiles a file list automatically) more complex than it needs to be. I have ideas for improvements in that area, too.

Other useful improvements would include the ability to:

  • Publish JSP or ASP pages (it's easy to generate pages that include Java or Visual Basic scripts, but there's no solution for the file extension)
  • Split or group files (I came across this limitation recently when publishing a photo gallery)
  • FTP automatically

Last but not least, users have complained about the lack of user documentation. While I can't address all these issues in one article, I will try to take them one at a time. For the next few articles, I'll work on user interface issues.

To IDE or not

At first, I considered using a variation of the user interface I introduced last month for XI: a simple window with drag-and-drop capabilities. However, I realized that it is more valuable to offer the ability to edit the files as well. As the feature list grew, I ended up with an integrated development environment (IDE).

Building an IDE from scratch is a lot of work but, fortunately, there are two Java open source projects to help -- netBeans and Eclipse. Both projects aim to develop a flexible Java IDE, and both benefit from large industry support. The most visible difference is that netBeans is Swing-based, while Eclipse builds on the Standard Widget Toolkit (SWT). If you have read past columns, you know that I am no fan of Swing.

Now that I have gained some experience with SWT, I think it is Swing done right. Indeed, both Swing and SWT aim to offer a rich, portable set of Java widgets. Swing achieves portability by drawing all the widgets in Java, including buttons, drop-down lists, and tree views. This seemingly great idea guarantees unlimited portability, but in practice it does not deliver. Swing widgets do not behave like their native counterparts, and, in my experience, this confuses users.

In contrast, SWT relies on native widgets as much as possible. The buttons and drop-down lists are native to the platform. SWT may draw a widget in Java, but only if there are no native counterparts. For example, SWT uses the native tree view on the Windows platform, but there are no native tree views for Unix platforms. So on Unix, SWT draws its own tree view. As a result, you get the best of both worlds: good portability (SWT has been ported to the most popular platforms except Macintosh -- and a Mac port is in development), good performance, and user satisfaction. I only wish that SWT were incorporated into the core Java platform.

Eclipse plug-ins

In a nutshell, Eclipse is a modern version of Emacs, the popular programmer's editor. Emacs is popular because it has been customized for just about any programming language on earth. However, with all due respect, the Emacs user interface is a relic from the past that never adapted to GUI. Eclipse aims to be as flexible as Emacs while offering a more modern user interface. Figure 1 shows the main Eclipse window.


Figure 1. The main Eclipse window
Eclipse

In addition, Eclipse is more than an editor. This highly modular and extensible IDE integrates all the tools developers need. It offers project wizards, an integrated compiler, a debugger, and more. The standard distribution ships with Java tailoring, but other languages such as C/C++ and even COBOL are supported through plug-ins, which guarantee portability. (In fact, Eclipse IDE uses plug-ins -- including the Java editor, compiler, project wizards, and class browsers -- to create most of what you see. I could easily write similar plug-ins for XM to put together an XM IDE.)


Understanding Eclipse

Eclipse is the most ambitious editor API I have ever used. If you have used customized programmer editors before, the breadth of the Eclipse API may surprise you. Unfortunately, I have found that the documentation available is not always on par with the excellent tools. While several good articles have described how to write for Eclipse, most assume too much familiarity with the platform. In particular, they fail to warn against potential pitfalls. Fortunately, this article (and those that follow) helps to address this issue.

I have loosely divided the API into two parts: the platform API and the editor API. The platform API deals with plug-ins. Plug-ins are Java libraries that the platform loads in response to user requests (for example, when the user opens a Java class file, the runtime loads the Java editor), or to offer services to other plug-ins (for example, SWT -- the widget toolkit -- is a plug-in).

Plug-ins implement most of the editor (that is, most of what you see on-screen), which means that:

  • Any aspect of the platform can be customized through plug-ins
  • The editor API is a set of plug-ins

Note, again, that this setup is similar to an operating system, where the kernel offers the most basic services and most other services are implemented through libraries.

Platform API

Let's start with the platform API. For Eclipse, a plug-in consists of a Java library and a manifest to describe it. The manifest is an XML file called plugin.xml.

Upon startup, the platform loads the manifests of all installed plug-ins and compiles a registry. It does not load the plug-ins themselves until they are needed (such as when the user edits a file). Plug-ins that are installed but not used have minimal impact on performance. For example, the core user interface plug-ins are loaded at startup to draw the main windows. If the user loads a Java class, the platform then (and only then) loads the Java editor plug-in.

If one class in the plug-in extends the Plugin abstract class, the runtime calls its startup() and shutdown() methods when the plug-in is loaded and unloaded. At this point, the platform can initialize the plug-in or free up resources. Most plug-ins won't need this class.

The second important concept is the extension point. Think of extension points as events that cause a plug-in to be loaded. A plug-in registers the extension points of interest into its manifest. When the event is fired (again, they are not actual events but I have found it helpful to think of them as events), the platform loads the plug-in to handle it. For example, the Java editor plug-in registers extension points when a Java document is loaded.

Editor API

Besides the platform, most of Eclipse is distributed as plug-ins. You could refer to these plug-ins as system plug-ins since they are essential to Eclipse's operation. These system plug-ins have their own API that regular plug-ins (such as the plug-ins you might write) can call. For example, in the next section, I write a plug-in to display information. To draw itself on screen and to interact with the other windows, my plug-in calls the system plug-ins. (These concepts will become clearer in the next section.)

Identifiers

There's one last aspect in the Eclipse API that has caused me many problems: identifiers. Plug-ins and extension points have identifiers, which are used by the platform to manage the plug-ins and extension points. Identifiers are unique strings. So far, so good. Confusion arises because Eclipse constructs its identifiers with the same rules as Java package names.

For example, the editor defines an extension point called org.eclipse.ui.views, which I will use in the next section. Because Eclipse is written in Java, the extension point is implemented through an interface called org.eclipse.ui.IViewPart. I confess it took me a while to realize that one was an identifier and the other an interface. To further confuse you, there are several packages starting with org.eclipse.ui.views in the documentation!

To avoid this confusion, remember this: Identifiers appear in the manifest (plugin.xml). As the name implies, the runtime uses them to identify elements. However, Java classes (or interfaces whose names may be similar to the indentifier) implement most of the concepts worth identifying.


Writing a plug-in

I learn best by experimenting, so to understand the Eclipse platform (and the aspects discussed in the previous two sections) better, I wrote a plug-in. As you will see, it does not do much, but it proved invaluable in deciphering the Eclipse documentation. See Resources to download a working version of this code.

View plug-in

The View plug-in I created, which is illustrated in Figure 2, defines a view in the Eclipse jargon. A view is a window that displays some information. In this case, the plug-in displays the name of the file selected in the navigator window. Granted, it's totally useless except as a learning exercise, but it does deserve some respect -- it summarizes several days of my time spent searching through the documentation!


Figure 2. The plug-in in Eclipse
plug-in

The view in Java interface

Like almost everything else in Eclipse, views are declared in a system plug-in. My plug-in registers its view through the org.eclipse.ui.views extension point. Note that, as explained above, org.eclipse.ui.views is an identifier, not a Java class. The corresponding Java interface is org.eclipse.ui.IViewPart.

Listing 1 contains the view implementation in the TestView class, which extends ViewPart. The ViewPart class represents a default implementation of the IViewPart interface. I could have implemented IViewPart, but ViewPart saves some coding.

The createPartControl() method, defined in IViewPart, creates the user interface for the view. The editor calls it when the window appears on screen. For TestView, the user interface is just a label.

TestView also implements the ISelectionListener interface. This interface, also defined by the Eclipse editor, listens for selection events. The navigator view (on the left side of the screen in Figure 2) fires this event when the user selects a different document. When it intercepts the event, the plug-in retrieves the file name and changes its label.


Listing 1. ViewTest.java
package org.ananas.test.plugin;

import org.eclipse.ui.*;
import org.eclipse.swt.*;
import org.eclipse.ui.part.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jface.viewers.*;
import org.eclipse.ui.texteditor.*;
import org.eclipse.core.resources.*;

/**
 * @author Benoit Marchal
 */

public class TestView
   extends ViewPart
   implements ISelectionListener
{
   private Label label;

   public TestView()
   {
   	  super();
   }

   public void createPartControl(Composite parent)
   {
      label = new Label(parent,SWT.WRAP);
      label.setText("None.");
      getViewSite().getPage().addSelectionListener(this);
      selectionChanged(null,getSite().getPage().getSelection());
   }

   public void setFocus()
   {
   	  label.setFocus();   // not very useful...
   }

   public void selectionChanged(IWorkbenchPart part,
                                ISelection selection)
   {
      if(selection != null
         && selection instanceof IStructuredSelection)
      {
         IStructuredSelection structured =
            (IStructuredSelection)selection;
         Object o = structured.getFirstElement();
         if(o != null
            && o instanceof IFile)
         {
         	IFile file = (IFile)o;
            label.setText("From navigator:" + file.getName());
            return;
         }
      }
      label.setText("None.");
   }
}

A few additional comments on this class: Label, an SWT widget, implements a non-editable field of text. The editor API also defines ISelectionListener, IWorkbenchPart, ISelection, and the other "I" interfaces. Notice the difference between these interfaces and extension points. Extension points control when a plug-in should be loaded. In contrast, ISelectionListener and the other interfaces come into play after the plug-in has been loaded.

The manifest

Listing 2 is the manifest or plugin.xml. Let's review it line by line. The plugin tag declares the plug-in itself and takes the following attributes:

  • id is the plug-in identifier. Again this is not a class name but it is constructed like a Java package name to guarantee uniqueness.
  • name is a human-friendly name.
  • version is the plug-in version.
  • provider is the plug-in developer.
  • class is the plug-in class. Do not confuse this class with the view. The platform calls this class to perform initialization and cleanup. Most plug-ins don't need a plug-in class, and, indeed, there's none in Listing 2.

Listing 2. plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<plugin id="org.ananas.eclipse.test"
        name="Test Plugin"
        version="1.0.0"
        provider-name="ananas.org"
        class="">
   <runtime>
      <library name="test-plugin.jar"/>
   </runtime>
   <requires>
      <import plugin="org.eclipse.core.boot"/>
      <import plugin="org.eclipse.core.runtime"/>
      <import plugin="org.eclipse.core.resources"/>
      <import plugin="org.eclipse.swt"/>
      <import plugin="org.eclipse.ui"/>
   </requires>
   <extension point="org.eclipse.ui.views">
      <category name="ananas.org"
                id="org.ananas.eclipse.view">
      </category>
      <view
            name="Name"
            icon="icons/default.gif"
            category="org.ananas.eclipse.view"
            class="org.ananas.test.plugin.TestView"
            id="org.ananas.eclipse.view.test">
      </view>
   </extension>
</plugin>

Next comes the runtime tag, which points to one or more JAR files. Following runtime is the requires tag with the import statements. Those are the plug-ins that must be brought into memory before this plug-in. Listing 2 references various system plug-ins such as SWT, the basic user interface, and others.

Finally, the manifest declares the extension point it is interested in. Listing 2 registers for views, declaring a new view category, called ananas.org, and then registering our view.


Testing and future work

To test this plug-in, download Eclipse 2.01 (I have not tested the plug-in with other versions of Eclipse), then download the test plug-in or compile the code presented in this article. Place everything in the plugins directory under Eclipse, then complete the following steps:

  • Launch Eclipse
  • Select Show View from the Window menu
  • Select Other
  • Expand the ananas.org category (the category we defined in the manifest), then choose Name (our plug-in, as defined in the manifest). The platform fires the extension point, which loads our plug-in and opens a new Name window.

As you can see, this is just the beginning. I believe that Eclipse offers a promising framework on which to build the UI. It suffers from a lack of documentation, so learning took more time than I would have liked. In upcoming articles, I will write more useful plug-ins for XM.

I hope this series proves helpful not only to XML developers but also to anybody interested in the Eclipse platform.


Resources

About the author

Benoit Marchal

Benoît Marchal is a consultant and writer based in Namur, Belgium. He has just released the second edition of XML by Example. More details on this topic are at marchal.com. You can contact Benoît at bmarchal@pineapplesoft.com.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology, Linux, Open source
ArticleID=10712
ArticleTitle=Working XML: Use Eclipse to build a user interface for XM
publish-date=10012002
author1-email=bmarchal@pineapplesoft.com
author1-email-cc=dwxed@us.ibm.com

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers