User Tools

Site Tools


Sidebar

Dave Orme muses about agile and functional programming.

My current work emphasizes SOA applications using Scala, Kubernetes, and AWS with a React-based SPA front-end. I'm also interested in progressive web applications and developer tools.


Blog

Scala, Clojure, and FP

Agile

The Cloud

Data-First Development

Older work

Coconut Palm Software home


Donate Bitcoin:

1Ecnr9vtkC8b9FvmQjQaJ9ZsHB127UzVD6

Keywords:

Kubernetes, Docker, Streaming Data, Spark, Scala, Clojure, OSGi, Karaf, GCP, AWS, SQL

Disclaimer:

Everything I say here is my own opinion and not necessarily that of my employer.

xswt:tutorial

XSWT Mini-Tutorial

This mini-tutorial will walk you through getting started with XSWT.

Getting started

To download XSWT, use the XSWT update site:

To create a new XSWT file:

  • File | New | Other… | XSWT | XSWT file

To display the XSWT preview pane:

  • Window | Show view | Other… | XSWT | XSWT Preview

First steps

Writing XSWT is just like writing SWT, but with a more convenient syntax.

If you want a Label:

Label myLabel = new Label(parentComposite, SWT.NULL);

Just write:

<label> </label>

Or more simply:

<label />

To set a property value, if the value is a simple data type (not an object itself with multiple fields that need to be initialized), just set the attribute with the same name:

<!-- call the setText() method, passing "Hello, world" -->
<label text="Hello, world"/>

To set a property value where the new property value object itself also needs properties set, create a subnode:

<composite>
    <layout x:class="gridLayout" numColumns="2"/>
</composite>

This translates to the following Java code:

Composite composite1 = new Composite(parent, SWT.NULL);
GridLayout layout1 = new GridLayout();
layout1.numColumns = 2;
composite1.setLayout(layout1);

To say the same thing in English:

  • We will call setLayout() on the parent Composite.
  • The parameter type to the setter, in this case, setLayout, is of the abstract type Layout, so XSWT does not know the type of the object to construct. Consequently, we use the x:class attribute to tell XSWT what type to construct.
  • We can set properties on the new object that was constructed (in this case the GridLayout) just by supplying attributes.
  • Note that XSWT automatically capitalizes the first letter of property names and x:classes, allowing you to write ideomatic XML code.

You can add further children by adding an:

<x:children>

node. For example:

<composite>
    <layout x:class="fillLayout"/>
    <x:children>
       <label text="Push this button:"/>
       <button text="Punch me!"/>
    </x:children>
</composite>

In the latest version of XSWT, x:children nodes are optional in most cases:

<composite>
    <layout x:class="fillLayout"/>
 
    <label text="Push this button:"/>
    <button text="Punch me!"/>
</composite>

When are you required to use x:children nodes? If the parent class has a property of the same name as a child control.

For example, if the parent class is a Group object, Group has a setText() method, so you have to use an x:children node in order to place a Text object inside a Group.

You can pass style bits to an object’s constructor using the x:style attribute.

<composite x:style="SWT.BORDER"/>

If the style bit is defined in the SWT class, you can omit the SWT part and XSWT will automatically add it back:

<composite x:style="BORDER"/>

Colors are automatically cached and the HTML CSS color constants are available:

<composite x:style="BORDER" background="Red"/>

Inter-object references and object IDs

Inter-object references are handled by creating IDs:

<tabfolder>
    <composite x:id="First">
       <layout x:class="fillLayout"/>
       <label text="First page"/>
    </composite>
 
    <tabitem text="one" control="First"/>
</tabfolder>

In this example, the ID “First” is defined on the Composite. It is then used as a parameter to the setControl() method on the TabItem.

Operating on the XSWT parent container

Nodes outside the top-level x:children node act as setters on the XSWT parent container. This lets you write:

<?xml version="1.0" encoding="UTF-8"?>
<xswt xmlns:x="http://xswt.sf.net/xswt">
   <import xmlns="http://xswt.sf.net/xswt">
      <package name="java.lang"/>
      <package name="org.eclipse.swt.widgets"/>
      <package name="org.eclipse.swt.layout"/>
   </import>
 
   <!-- Set the parent's layout manager -->
   <layout x:class="gridLayout" numColumns="2"/>
 
   <!-- More stuff here... -->
</xswt>

This lets you keep the layout data for the top-level widgets with the code that sets the layout manager that they affect.

Any XSWT node (including the xswt node) can call 0-arg methods to return an object and then call methods on it or add children to it.

Notes

  • In order to call a 0-arg method and operate on its result, you have to use the literal method name. Otherwise, we will get naming collisions. ie: does <shell> mean to call getShell() or mean to construct a new Shell?
  • Since you can use regular XSWT syntax inside the 0-arg method, you can also nest these things if you need to get the effect of writing:
getSomething().getSomethingElse().add("whatever");

Using an XSWT file

Here’s an SWT Snippet that loads and displays an XSWT file:

Display display = new Display();
Shell shell = new Shell(display);
Map results = null;
 
try { 
   results = XSWT.create(getClass().getResourceAsStream("HelloWorld.xswt")) .parse(shell); 
} catch (XSWTException e) {
   e.printStackTrace(); 
}
 
shell.setSize(600, 600);
shell.open();
while (!shell.isDisposed()) {
   if (!display.readAndDispatch())
      display.sleep(); 
}
display.dispose();

Notice that the call to XSWT.parse() returns a Map. The keys of this map are the IDs that were defined in the XSWT file. The values are the objects that defined the IDs. Using these IDs, one can retrieve the objects in order to further manipulate them in Java code, add event handlers to them, etc.

This is nice, but it would be nicer to have a type-safe way of accessing one’s controls. XSWT can do this too:

Given the following line inside an appropriate XSWT file:

<label x:id="HelloLabel" text="Hello, world"/>

we can define the following interface with methods corresponding to the IDs in the XSWT snippet:

public interface IHelloWorld {
   public Label getHelloLabel();
}

Now we can change the code that loads the XSWT file to read:

IHelloWorld results = null;
// ... more initialization

results = (IHelloWorld) XSWT.create(getClass().getResourceAsStream("HelloWorld.xswt"))
           .parse(shell, IHelloWorld.class);

XSWT will automatically return an object that implements your IHelloWorld interface and that references all the right objects created by loading the XSWT file.

For example, calling getHelloLabel() will return the label that defined the “HelloLabel” ID.

This gives you type-safe access to all the controls in your XSWT layout.

Getting the XSWT source

In order to get the XSWT source code, which contains numerous examples, follow the normal method of setting up a CVS repository pointing to xswt.cvs.sourceforge.net:/cvsroot/xswt. Then do the following:

  • Check out com.swtworkbench.community.xswt and org.kxml
  • Right-click on the plugin.xml file of com.swtworkbench.community.xswt, select PDE Tools, and Update Classpath.
xswt/tutorial.txt · Last modified: 2014/10/17 22:08 (external edit)