Building SWT User Interfaces with Xtend
Xtend is a programming language that compiles to Java, but adds new features, such as closures. This article applies Xtend to implement SWT UIs and shows how the resulting code can be more readable and concise compared to Java.
When you’ve been programming desktop applications with Eclipse before, you probably have used the Standard Widget Toolkit (SWT), since it provides the fundamental UI elements (aka Widgets), such as windows, buttons, edit fields, checkboxes, etc.
The first thing you probably did was to create a window with several nicely arranged widgets. This task includes choosing the proper parent widget for all widgets, configuring layouts, etc. Then, the next step usually is to implement behavior for some widgets, so that the user can interact with the UI. This includes for example implementing selection listeners for buttons.
These two tasks have different characteristics:
- To arrange widgets nicely, the developer's code needs to creates trees of objects. In such trees, windows are the root nodes, composites etc. the intermediate nodes and buttons, text fields, etc. are the leaf nodes. In the context of the web and HTML, an equivalent tree is the DOM (Document Object Model). For SWT, this tree becomes very visible in the XML-based approaches to specify UIs, such as CookSwt and swtxml.
- To implement behavior, the developer usually creates anonymous or nested classes in Java. These classes implement event handlers and are registered as event listeners.
SWT User Interfaces are usually implemented using Java. However, the way to implement both patterns in Java bears room for improvement, because:
- Java doesn’t have a special pattern to create trees. The standard pattern is to imperatively create objects and establish references between them. Whether the resulting objects form a tree or a graph is not obvious to the reader of the code, since for him/her it is just a linear sequence of statements.
- Anonymous classes in Java have a particularly noisy syntax. The extreme scenario (which is fairly common) is when the actual code that handles the event is only a single Java statement. In this scenario, the majority of the code is not the execution logic of the handler, but the declaration of the class and the handlers method.
Designing User Interfaces using Trees: Builder Syntax
Xtend offers to improve the situation due to its support for a builder syntax and its support for closures.
- Builder syntax is a pattern that creates an object tree and allows the code to be formatted like a tree (using indentation an brackets).
- Closures allow to define instructions that can be executed later. You may perceive it as similar to an anonymous class with a single method, but without the syntactic overhead of a method declaration.
The following snippet illustrates the builder syntax in Xtend. As indicated already, the style of the code reflects the tree structure of the SWT widgets. This example creates a shell with one label, one text filed and one button. Additionally, it arranges them using a GridLayout.
val shell = newShell(display) [
layout = new GridLayout(3, false)
newLabel(SWT::NONE) [
text = "To:"
]
newText(SWT::BORDER) [
layoutData = newGridData() [
grabExcessHorizontalSpace = true
horizontalAlignment = SWT::FILL
]
]
newButton(SWT::PUSH) [
text = "Send"
]
]
To understand the code from the Xtend code snippet above and to compare it with Java, the following things may be noteworthy:
- All referenced elements in the snippet are Java elements from SWT,
except for the
new*()
-methods. Those are methods implemented in a custom Java factory class. They all conform to the following pattern illustrated in the next code snippet.public static Button newButton(Composite parent, int style, Procedure1<Button> init) {
Button btn = new Button(parent, style);
init.apply(btn);
return btn;
}
new*()
-methods can be invoked from the snippet like member methods since they have been imported as extension methods. Extension methods are methods defined in a different class which can be invoked like member methods on any kind of object that the method accepts as its first parameter. In the snippet, the extension methods are invoked on the implicit variableit
. - You probably have noticed that all invocations of
new*()
-methods are followed by a code block surrounded by brackets "[]
". This code block defines a closure which is passed as the last parameter to thenew*()
-method. You could as well pass in the closure explicitly as the last parameter to the method. However, this syntax can improve readability of the code. Since the closure has one parameter and no return value, its class implements interfaceProcedure1
(src). - No closures in this example declare parameters. However, they
do have one implicit parameter. An example of a closure with
parameters is
[param | param.doSomething() ]
. Xtend supports an implicit variable namedit
. If a closure has a parameter but does not declare the parameter, the parameters' value can be accessed through the variableit
. Usage of the variableit
is implicit in the same way as you know it fromthis
, with the difference that you can not assign new values tothis
. When accessing members ofit
(e.g.horizontalAlignment
), stating the nameit
is optional. Furthermore, you can invoke extension methods onit
: In the code snippet, the methodnewText(Composite, int)
has two parameters. The value forComposite
is the value ofit
from the surrounding closure, which is in fact the shell (the window). - Xtend allows to use Getter/Setter-pairs
like properties: Instead of
setText("Send")
you may writetext = "Send"
Using Closures to make User Interfaces Interactive
To implement event handlers it is common in Java to use anonymous or nested classes. The snippet below uses Xtends closures to do the same in a syntactically more concise way.
newButton(SWT::PUSH) [
text = "Send"
addListener(SWT::Selection) [
newMessageBox((widget as Control).shell, SWT::OK) [
message = "Hello World"
].open()
]
]
The snippet above uses the Builder Syntax (as described in the last section) to create a Button. When the button is clicked, a MessageBox will be created and shown to the user.
The interesting part here is
addListener(int, Listener)
. This method accepts two parameters with the second parameter being
an instance of interface
Listener
(src)
. In the snippet the second parameter for
addListener
is a closure (the code block surrounded with
[]
in
addListener(SWT::Selection) [ ... ]
). When the Xtend code is compiled to Java, the closure is compiled
into an anonymous Java class which implements the interface
Listener
. This, however, is only possible for interfaces that have just a
single method.
A Comprehensive Example
package blog_001_xtend_and_swt
import org.eclipse.swt.SWT
import org.eclipse.swt.layout.GridLayout
import org.eclipse.swt.widgets.Display
import static extension blog_001_xtend_and_swt.XtendSWTLib.*
class MessageForm {
def static void main(String[] args) {
new MessageForm().run(args)
}
def void run(String[] args) {
val display = new Display()
val shell = newShell(display) [
setSize(400, 400)
layout = new GridLayout(3, false)
newLabel(SWT::NONE) [
text = "To:"
]
val to = newText(SWT::BORDER) [
layoutData = newGridData() [
grabExcessHorizontalSpace = true
horizontalAlignment = SWT::FILL
]
]
val send = newButton(SWT::PUSH) [
text = "Send"
]
val msg = newText(SWT::BORDER) [
layoutData = newGridData() [
grabExcessHorizontalSpace = true
grabExcessVerticalSpace = true
horizontalSpan = 3
horizontalAlignment = SWT::FILL
verticalAlignment = SWT::FILL
]
]
send.addListener(SWT::Selection) [
newMessageBox(send.shell, SWT::OK) [
message = to.text + "\n" + msg.text
].open()
]
]
shell.open()
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep()
}
display.dispose()
}
}
17 comments:
still to much code to achive one small window .
Nice - I'm working on a DSL for JavaFX 2.0 using xText (http://www.efxclipse.org/fxgraph.html). What I'm not sure it is a good idea is if one should mix UI-Construction and Behavior in the same code
55 lines isn't that much (try a gui generator), more important is that the code is readable.
Besides this, the example is more about showing how the closures work in Xtend.
If was wondering what this line does:
import static extension blog_001_xtend_and_swt.XtendSWTLib.*
Also when swt properties are left out, does this give sane defaults. Can Xtend change this?
I also tried to make a simpler approach without the closures. Could some of it applied to default code:
class userinterface {
def main(){
gui = swtGui(layout = grid)
button1 = swtButton(text = "Send")
field1 = swtTextField(size = 20,400
label = "To:")
area1 = swtTextArea(size = 400,400)
while(gui)
if(button1.clicked)
swtBox()'''
Sender: field1.read
Message:
area1.read
'''
}
}
}
@tomsondev:
What I'm not sure it is a good idea is if one should mix UI-Construction and Behavior in the same code
Yes, that's reasonable for larger applications. I didn't do it for my example because I wanted to keep it as simple as possible.
@skin27:
If was wondering what this line does:
import static extension blog_001_xtend_and_swt.XtendSWTLib.*
This line makes all static methods from Java Class XtendSWTLib available as extension methods. In the example that are methods such as newLabel(...), newShell(...), etc.
Also when swt properties are left out, does this give sane defaults. Can Xtend change this?
Since this approach uses self-defined library methods (defined in XtendSWTLib), you can introduce any defaults you like. Xtend itself is agnostic of SWT.
About your code example:
You're avoiding closures by implementing the behavior directly inside the applications message-loop. This approach may lead to bloated code once the application gets larger because there is only one message loop per UI-thread. Event handler (independently of whether they are implemented with closures or java classes) solve this elegantly since they are registered on the widgets and since they don't require you to modify the thread's message loop.
Nice. Have you looked at Glimmer?
Very informative article.Thank you author for posting this kind of article .
http://www.wikitechy.com/view-article/nested-classes-in-java-with-example
Both are really good,.
Cheers,
Venkat
very nice and Quality of the Leather Jackets are Avalible at very Affordable rates with
Nice and Comfortable touch and Quality..
Thanks Alot.
Shield Security Solutions Offers Security Guard License Training across the province of Ontario. Get Started Today!
Security Guard License | Security License | Ontario Security license | Security License Ontario | Ontario Security Guard License | Security Guard License Ontario
Thank you for this post! I want to follow you on facebook, but I don't see the link. If you have few followers, visit this site https://soclikes.com/ to get facebook followers
An deiner Stelle würde ich ein YouTube Video dazu veröffentlichen und YouTube Likes von hier https://viplikes.de für dieses Video erhalten. Möchtest Du das tun?
So informative. I was searching like this for a few days. Thank you for sharing this information.classified ads platform in Bangladesh
What a fantabulous post this has been. Never seen this kind of useful post.
I am grateful to you and expect more number of posts like these. Thank you very much.
MY homepage :::: 휴게텔
(freaky)
Best 5 merit casino bonus codes - xn--o80b910a26eepc81il5g.online
Best 5 merit casino bonus codes · 1. 3. 5. 5. 5. 5. 5. 카지노사이트 5. 5. 5. 5. 5. 5. dafabet link 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 메리트카지노 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5. 5.
Top-Down Casino - DRMCD
Top-Down Casino is a 남원 출장샵 casino that's a 안양 출장마사지 licensed and regulated gambling site. It was established 군포 출장샵 in 2006, when the casino was first Rating: 이천 출장샵 4.1 고양 출장샵 · 3 votes
This very informative and interesting blog.
eavestrough installation
Teilnehmer dieses Tutorials werden in Vorträgen die relevanten Konzepte kennenlernen sowie eigene Erfahrung mit Xtext anhand von Übungsaufgaben sammeln. Ziel des Tutorials ist es, die Teilnehmer zur eigenständigen Entwicklung von domänenspezifischen Sprachen und Codegeneratoren zu befähigen.
I was searching like this for a few days.
waplus.win
projectfreetv.onl
Post a Comment