I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Nebula: Providing More for Your SWT Applications

12.22.2009
| 11351 views |
  • submit to reddit

The Standard Widget Toolkit (SWT) gives Java developers an alternative to Swing, with native access to widgets. However, sometimes the widgets provided in SWT are not enough, especially if you want to create a more modern application. Your options are to extend the SWT widgets yourself, or to take advantage of the Nebula project.

Led by Tom Schindl, the project is currently in incubation (and has been for quite some time). The project is full of easy-to-use components such as calendar, gallery and shelf. In this article I'll give a quick run through the calendar and gallery widgets with some examples.

Setting Up An Application

We'll use the Nebula widgets in a simple view of an Eclipse RCP application. To get an application running quickly, just use the New/Project.../Plug-in Project wizard and use one of the templates to create an RCP application. 

We'll be modifying the View class that is generated in this project template, so that it will contain our Nebula widgets.

We don't need the table viewer that is provided by default here, so you'll need to comment out the code provided in the setFocus() and createPartControl() methods.

The basis our of new createPartControl() method will look as follows, forcing the view to take up the screen.

	public void createPartControl(Composite parent) 
{
parent.setLayout(new FillLayout())
//our widget code will go here
}

Each of the widgets that we will be using here is available as a seperate download - for this set of examples we'll be using Gallery and CDateTime. Once you have downloaded these, save them to your plugins directory. 

Don't forget that when you run the application after changing dependencies, you'll need to ensure that the plug-ins you need are in the run configuration. You can just use the "Add Required Plug-ins" button in the Plug-ins tab of the Run Configuration dialog to fix any dependency issues. 

Calendar and Time Selectors

We'll start with a simple example of a Nebula widget - the date and time selector. If you've downloaded the CDateTimeplugin, you should be able to add it as a dependency through your RCP application's plugin.xml as org.eclipse.nebula.widgets.cdatatime

 

Using the component is very simple, we just need to add it to our createPartControl() method. First let's just add a Date selector, using the CDT.SIMPLE style:

CDateTime cdt = new CDateTime(parent, CDT.BORDER | CDT.SIMPLE);
cdt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));

This code will produce the following:

Next lets create a more complex version that includes time selection, by using the CDT.TIME_MEDIUM style:

CDateTime cdt = new CDateTime(parent, CDT.BORDER | CDT.COMPACT | CDT.DROP_DOWN 
| CDT.DATE_LONG | CDT.TIME_MEDIUM);
cdt.setSelection(new Date());
cdt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));

This allows date selection as follows:

If you click on the clock icon that is provided as part of the dialog, you'll be able to choose the time from a clock widget: 

 

 

Gallery 

Once again, you'll need to add the relevant plug-in to your dependencies, in this case it will be org.eclipse.nebula.widgets.gallery.

First we need to create the Gallery widget itself. 

final Gallery gallery = new Gallery(parent, SWT.V_SCROLL | SWT.VIRTUAL);
gallery.setVirtualGroups(true);

Note that I have used SWT.VIRTUAL rather than SWT.MULTI here. We're displaying our gallery as a virtual table, which give use performance benefits compared with standard tables. Virtual tables restrict the creation of TableItem's to only those items which the user can see at the time. For something like a gallery, this is essential.

The next step is to create a renderers for both the group and the items. Each item can have a specified size within a group - here we set it to 64x64. 

		// Group Renderer
DefaultGalleryGroupRenderer gr = new DefaultGalleryGroupRenderer();
gr.setItemSize(64, 64);
gr.setMinMargin(3);
//Item Renderer
DefaultGalleryItemRenderer ir = new DefaultGalleryItemRenderer();

gallery.setGroupRenderer(gr);
gallery.setItemRenderer(ir);

Next we can set how many groups belong in the gallery: 

gallery.setItemCount(1);

Finally, let's populate the gallery, using a single folder's contents:

GalleryItem parentItem = gallery.getItem(0);
//use a folder name
if(parentItem.getParentItem() == null)
{
parentItem.setText("C:\\Images");
//add the contents of the folder
File f = new File("C:\\Images");
File[] contents = f.listFiles();

//set number of items in this group
parentItem.setItemCount(contents.length);

for(int i =0; i < contents.length; i++)
{
String imgFilePath = contents[i].getAbsolutePath();

ImageLoader loader = new ImageLoader();
GalleryItem subItem = parentItem.getItem(i);
Image img = new Image(parent.getDisplay(), loader.load(imgFilePath)[0]);
subItem.setImage(img);

}


}

Initially, all groups display as contracted. When you expand it, you should see something like this: 

 

 

Conclusion 

As you can see there's a lot that Nebula provides, and there's a lot that you can do yourself with basic SWT widgets. With e4 there will be even more configurability available, but for users of the 3.x stream of Eclipse and SWT, there's still a lot of scope for innovation.

 

 

 

Comments

Nicolas Richeton replied on Wed, 2010/03/10 - 9:40am

Thanks for this post. It will be very usefull to new users. I'll just add a few things about Gallery.

In this example, you are populating items in a way which don't need or use SWT.VIRTUAL : by using getItem(), you are forcing item creation. Populating a Gallery should be done this way : 

Non virtual : The code creates all items right away.

// Create gallery
final Gallery gallery = new Gallery(parent, SWT.V_SCROLL);

// Add Group
GalleryItem group = new GalleryItem( parent, SWT.NONE );
group.setText("C:\\Images");

//add the contents of the folder
File f = new File("C:\\Images");
File[] contents = f.listFiles();


// Create all items
for(int i =0; i < contents.length; i++) {
   String imgFilePath = contents[i].getAbsolutePath();
   ImageLoader loader = new ImageLoader();
   GalleryItem subItem = new GalleryItem( group, SWT.NONE) ;
   Image img = new Image(parent.getDisplay(), loader.load(imgFilePath)[0]);
   subItem.setImage(img);
}

Virtual: The code adds a callback method to the gallery. This method is able to set content for any item. Gallery will create Items only when they become visible.

final Gallery gallery = new Gallery(parent, SWT.V_SCROLL | SWT.VIRTUAL);

// Open Directory
final File f = new File("C:\\Images");
final File[] contents = f.listFiles();

// SetData is called when Gallery creates an item.
gallery.addListener(SWT.SetData, new Listener() {
   public void handleEvent(Event event) {
      GalleryItem item = (GalleryItem) event.item;
      if (item.getParentItem() == null) {
         // It's a group
         int index = gallery.indexOf(item);
         if( index == 0 ) {
            // This is group 1
            item.setText("C:\\Images");
            item.setItemCount(contents.length);
            item.setExpanded(true);
        } else {
           // Should never be used
           item.setItemCount(0);
        }
     } else {
       // It's an item
       GalleryItem parentItem = item.getParentItem();
      
       // Get item index
       int index = parentItem.indexOf(item);

       // Load corresponding items
       String imgFilePath = contents[index].getAbsolutePath();
       ImageLoader loader = new ImageLoader();
       Image img = new Image(parent.getDisplay(), loader.load(imgFilePath)[0]);
       item.setImage(img);
     }
   }
});

// Create one group (will call SetData)
gallery.setItemCount( 1 );

 

Virtual Groups

About gallery.setVirtualGroups() :   This flag is not required in most cases. This is intended only when you work with a VERY large number of groups and when it takes time to compute the number of item in a group, because Gallery creates groups right away to be able to display the scrollbar.

In that case, you can use virtualgroups to automatically set the number of items in a group to a fixed number (say 100). When the group becomes visible, SetData will be called and scrollbar will be updated with the new size.

This feature is quite new and is still a little buggy (see Javadoc). Don't use it unless you really need it.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.