XSWT is an XML-based GUI-description language for SWT. The XSWT engine uses Java reflection to actually construct a user interface, so it is automatically compatible with current and future SWT controls. An [url=http://www.eclipse.org][url=http://www.eclipse.org]eclipse editor for XSWT files is included.
现在开发的产品中用户界面也是用XML定义的,但是界面定义很不灵活。XSWT网站上介绍说XSWT是和SWT元素一一对应的,应该有很大的灵活性。
xswt的下载地址是:http://xswt.sourceforge.net/cgi-bin/xswt/download
也可以使用Eclipse的Update Manager从http://xswt.sourceforge.net/updates 在线更新。
下载了一个试用了一下,总体感觉还好。但是好像项目还没有开发完,文档没有。而且官方网站上说支持Groovy脚本语言的功能好像还没有提供。期待中。。。。
以下是一个我写的示例代码,演示了在XSWT中如何处理事件。
/*******************************************************************************
* $Header$
* $Revision$
* $Date$
*
*==============================================================================
*
* Copyright (c) 2001-2004 XYZ Technologies, Ltd.
* All rights reserved.
*
* Created on 2004-11-27
*******************************************************************************/
import java.io.InputStream;
import java.util.Map;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.swtworkbench.community.xswt.XSWT;
/**
* TODO此处填写 class 信息
*
* @author Yanfei (mailto:yanfei@hotmail.com)
*/
/*
* 修改历史
* $Log$
*/
public class XSWTDialogTest {
/**
*
*/
public XSWTDialogTest() {
super();
}
public static void main(String[] args) throws Exception{
Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
InputStream in = XSWTDialogTest.class.getResource("JavaEditorPreferencePage.xswt").openStream();
Map controls = XSWT.create(shell, in);
Button button1 = (Button) controls.get("button1");
button1.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
MessageDialog.openInformation(shell, "Message", "button1 selected");
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
shell.setSize(600, 600);
shell.open();
while(!shell.isDisposed())
if(!display.readAndDispatch())
display.sleep();
display.dispose();
}
}
以下是定义界面的XSWT文件:
<?xml version="1.0" encoding="UTF-8"?>
<xswt xmlns:x="http://sweet_swt.sf.net/xswt">
<import xmlns="http://sweet_swt.sf.net/xswt">
<package name="java.lang"/>
<package name="org.eclipse.swt.widgets"/>
<package name="org.eclipse.swt.layout"/>
</import>
<x:children>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0"/>
<x:children>
<label text="Java Editor settingx:"/>
<tabFolder>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
<x:children>
<composite x:id="appearance">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<label text="Displayed &tab width:"/>
<text x:style="BORDER" text="4" textLimit="3"><layoutData x:class="gridData" widthHint="20"/></text>
<label text="Print margin col&umn:"/>
<text x:style="BORDER" text="80" textLimit="3"><layoutData x:class="gridData" widthHint="20"/></text>
<button x:id="button1" x:style="CHECK" text="Synchroni&ze outline selection on cursor move (editor must be reopened)"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Show overview &ruler"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button x:style="CHECK" text="Show lin&e numbers"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Highlight &matching brackets"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Hi&ghlight current line"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button x:style="CHECK" text="Sho&w print margin"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<composite><layoutData x:class="gridData" heightHint="5"/></composite>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="Appearance color optionx:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<list selection="0" x:style="BORDER|SINGLE">
<layoutData x:class="gridData" heightHint="100" widthHint="220"/>
<!-- x:p0 specifies the 0th constructor argument for the String passed to add() (ie: the string's value). -->
<add x:p0="Line number foreground"/>
<add x:p0="Matching brackets highlight"/>
<add x:p0="Current line highlight"/>
<add x:p0="Print margin"/>
<add x:p0="Find scope"/>
<add x:p0="Linked position"/>
<add x:p0="Link"/>
</list>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.BEGINNING"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="C&olor:"/>
<button><layoutData x:class="gridData" widthHint="40"/></button>
</x:children>
</composite>
</x:children>
</composite>
</x:children>
</composite>
<tabItem text="Appeara&nce" control="appearance"/>
<composite x:id="syntax">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<group text="Background color:">
<layoutData x:class="gridData"/>
<layout x:class="gridLayout" numColumns="3"/>
<x:children>
<button selection="true" x:style="RADIO" text="S&ystem default"><layoutData x:class="gridData" verticalAlignment="GridData.BEGINNING"/></button>
<button x:style="RADIO" text="C&ustom:"><layoutData x:class="gridData" verticalAlignment="GridData.BEGINNING"/></button>
<button><layoutData x:class="gridData" widthHint="40"/></button>
</x:children>
</group>
<composite><layoutData x:class="gridData" heightHint="0" widthHint="0"/></composite>
<label text="Fo&reground:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<list x:style="BORDER|SINGLE">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
<add x:p0="Multi-line comment"/>
<add x:p0="Single-line comment"/>
<add x:p0="Keywords"/>
<add x:p0="Strings"/>
<add x:p0="Others"/>
<add x:p0="Task Tags"/>
<add x:p0="Javadoc keywords"/>
<add x:p0="Javadoc HTML tags"/>
<add x:p0="Javadoc links"/>
<add x:p0="Javadoc others"/>
</list>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.BEGINNING"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="C&olor:"/>
<button><layoutData x:class="gridData" widthHint="40"/></button>
<button x:style="CHECK" text="&Bold"><layoutData x:class="gridData" horizontalSpan="2"/></button>
</x:children>
</composite>
<label text="Preview:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<text x:style="BORDER"><layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2" verticalAlignment="GridData.FILL"/></text>
</x:children>
</composite>
<tabItem text="Synta&x" control="syntax"/>
<composite x:id="code_assist">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" marginWidth="0" numColumns="2"/>
<x:children>
<button selection="true" x:style="RADIO" text="Completion inser&ts"/>
<button x:style="RADIO" text="Completion over&writes"/>
</x:children>
</composite>
<button selection="true" x:style="CHECK" text="Insert single &proposals automatically"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Show only proposals &visible in the invocation context"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button x:style="CHECK" text="Present proposals in a&lphabetical order"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Automatically add import instead of &qualified name"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button x:style="CHECK" text="&Fill argument names on method completion"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button enabled="false" selection="true" x:style="CHECK" text="&Guess filled argument names"><layoutData x:class="gridData" horizontalIndent="20"/></button>
<button selection="true" x:style="CHECK" text="&Enable auto activation"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<label text="Auto activation dela&y:"/>
<text x:style="BORDER" text="500" textLimit="4"><layoutData x:class="gridData" widthHint="30"/></text>
<label text="Auto activation &triggers for Java:"/>
<text x:style="BORDER" text="." textLimit="4"><layoutData x:class="gridData" widthHint="30"/></text>
<label text="Auto activation triggers for &Javadoc:"/>
<text x:style="BORDER" text="@" textLimit="4"><layoutData x:class="gridData" widthHint="30"/></text>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="Code assist colo&r optionx:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<list x:style="BORDER|SINGLE">
<layoutData x:class="gridData" heightHint="100" widthHint="180"/>
<add x:p0="Completion proposal background"/>
<add x:p0="Completion proposal foreground"/>
<add x:p0="Method parameter background"/>
<add x:p0="Method parameter foreground"/>
<add x:p0="Completion overwrite background"/>
<add x:p0="Completion overwrite foreground"/>
</list>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.BEGINNING"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="C&olor:"/>
<button><layoutData x:class="gridData" widthHint="40"/></button>
</x:children>
</composite>
</x:children>
</composite>
</x:children>
</composite>
<tabItem text="&Code Assist" control="code_assist"/>
<composite x:id="annotations">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<button selection="true" x:style="CHECK" text="Analyze annotations &while typing"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Indicate annotations solvable with &Quick Fix in vertical ruler"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<composite><layoutData x:class="gridData" heightHint="5"/></composite>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<label text="Annotation &presentation:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<list x:style="BORDER|SINGLE">
<layoutData x:class="gridData" heightHint="100" widthHint="150"/>
<add x:p0="Errors"/>
<add x:p0="Warnings"/>
<add x:p0="Tasks"/>
<add x:p0="Search Results"/>
<add x:p0="Bookmarks"/>
<add x:p0="Others"/>
</list>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.BEGINNING"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<button selection="true" x:style="CHECK" text="Show in &text"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<button selection="true" x:style="CHECK" text="Show in overview &ruler"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<label text="C&olor:"/>
<button><layoutData x:class="gridData" widthHint="40"/></button>
</x:children>
</composite>
</x:children>
</composite>
</x:children>
</composite>
<tabItem text="Annotation&s" control="annotations"/>
<composite x:id="typing">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout"/>
<x:children>
<button selection="true" x:style="CHECK" text="S&mart cursor positioning at line start and end"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<composite><layoutData x:class="gridData" heightHint="5"/></composite>
<group text="Select options for automatic text modifications">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout"/>
<x:children>
<button selection="true" x:style="CHECK" text="&Wrap Java strings"/>
<button selection="true" x:style="CHECK" text="Pasting fo&r correct indentation"/>
<button x:style="CHECK" text="Ins&ert space for tabs (see Code Formatter preference page)"/>
<button selection="true" x:style="CHECK" text="Close strin&gs"/>
<button selection="true" x:style="CHECK" text="Close &brackets and parenthesis"/>
<button selection="true" x:style="CHECK" text="Cl&ose braces"/>
<button selection="true" x:style="CHECK" text="Close Java&docs and comments"/>
<button selection="true" x:style="CHECK" text="Add Javadoc &tags"><layoutData x:class="gridData" horizontalIndent="20"/></button>
</x:children>
</group>
</x:children>
</composite>
<tabItem text="T&yping" control="typing"/>
<composite x:id="hovers">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" horizontalSpan="2"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<label text="&Hover key modifier preferencex:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<list x:style="BORDER|SINGLE">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.FILL"/>
<add x:p0="Best Match"/>
<add x:p0="Javadoc"/>
<add x:p0="Problems"/>
<add x:p0="Source"/>
<add x:p0="Variable Values"/>
</list>
<composite>
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL" verticalAlignment="GridData.BEGINNING"/>
<layout x:class="gridLayout" marginHeight="0" marginWidth="0" numColumns="2"/>
<x:children>
<button selection="true" x:style="CHECK" text="&Enabled"><layoutData x:class="gridData" horizontalSpan="2"/></button>
<label text="Key &Modifier:"></label>
<text x:style="BORDER"><layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/></text>
<label text="Description:"><layoutData x:class="gridData" horizontalSpan="2"/></label>
<text x:style="BORDER|READ_ONLY" text=""><layoutData x:class="gridData" grabExcessHorizontalSpace="true" grabExcessVerticalSpace="true" heightHint="60" horizontalAlignment="GridData.FILL" horizontalSpan="2" verticalAlignment="GridData.FILL"/></text>
</x:children>
</composite>
</x:children>
</composite>
<tabItem text="Ho&vers" control="hovers"/>
<composite x:id="navigation">
<layoutData x:class="gridData" grabExcessHorizontalSpace="true" horizontalAlignment="GridData.FILL"/>
<layout x:class="gridLayout" numColumns="2"/>
<x:children>
<button selection="true" x:style="CHECK" text="S&upport hyperlink style navigation for "Open Declaration""><layoutData x:class="gridData" horizontalSpan="2"/></button>
<label text="Hyperlink style navigation key &modifier:"/>
<text x:style="BORDER" text="Ctrl"><layoutData x:class="gridData" widthHint="100"/></text>
</x:children>
</composite>
<tabItem text="Nav&igation" control="navigation"/>
</x:children>
</tabFolder>
</x:children>
</composite>
</x:children>
</xswt>
以下付上XSWT邮件列表中关于event handling的对话:
From: ted stockwell <emorning@ya...>
2004-11-16 05:07
Hi all,
I just now downloaded XSWT and took a quick look around.
One thing that is not obvious to me is how to handle events.
For instance, how do I handle a button selection?
TIA,
ted stockwell
From: Jan Petersen <jpetersen@in...>
2004-11-16 05:34
On Tue, 16 Nov 2004 07:07:46 -0600
"ted stockwell" <emorning@ya...> wrote:
> Hi all,
>
> I just now downloaded XSWT and took a quick look around.
> One thing that is not obvious to me is how to handle
> events.
> For instance, how do I handle a button selection?
Ted,
This is not _really_ part of XSWT, but it"s relatively easy
to set up. One of the many nice features in XSWT is that
you can do:
<button x:id="myButton" x:id.event="myEvent" text=...
Then, when you reference your id"d widgets in your java
code, you can do something like:
String eventString = (String)widget.getData("event");
Now you have the string value of the attribute
"x:id.event". The remaining part is to convert the string
value to an SWT event (via reflection for instance) and to
do a addListener(...) on the widget.
Hope this helps
Jan
From: David J. Orme <djo@co...>
2004-11-16 07:37
Nice to see you here, Ted!
On Tuesday 16 November 2004 07:07 am, ted stockwell wrote:
> I just now downloaded XSWT and took a quick look around.
> One thing that is not obvious to me is how to handle events.
> For instance, how do I handle a button selection?
Right now, here"s how this works:
In the XSWT file:
<button x:id="buttonName" text="Click me"/>
In your Java code:
InputStream in = getClass().getResource("bounds_example.xswt").openStream();
Map controls = XSWT.create(shell, in);
Button aButton = (Button) controls.get("buttonName");
aButton.addSelectionListener(new MySelectionListener());
In other words, any SWT control with an x:id will be in the Map that
XSWT.create() returns, indexed by the ID string. Then you can do whatever
you want with it.
This is very workable, if a bit cumbersome. There have been several proposals
floated to improve this.
1) Have XSWT generate an interface with getter methods corresponding to every
x:ID attribute. Have a version of XSWT.create() that returns a dynamic proxy
implementing this interface that looks at the name of the method, does the
Map lookup for you, and returns the appropriate object.
This would eliminate the typecast and would enable the compiler to catch
coding errors more effectively.
2) Something along the lines of what Jan mentioned (originally suggested by Ed
Burnette in the XSWT bug report), where you have an engine that looks up
event names based on the x:id or possibly based on an extended attribute
initialized using x:id.eventhandlername="value" and automatically sets the
event handler using Java reflection. So you could write:
Map controls = XSWT.create(shell, in);
EventManager.hookup(controls, aControllerObject);
and have it all just done for you.
3) And then you have the XSWT to Java compiler, which provides even more
interesting possibilities for event hookup because you can just generate code
that does it and bypass Java reflection entirely...
Again, welcome to XSWT, Ted!
Best regards,
Dave Orme
--
Got Java? Use SWTworkbench! </" target=_NEWhttp://www.swtworkbench.com>
PGP Public Key (for confidential communications):
http://www.coconut-palm-software.com/~djo/public_key.txt
XSWT Screen Shot