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 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:[email protected])
*/
/*
* 修改歷史
* $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...> Event Handling? 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...> Re: Event Handling? 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...> Re: Event Handling? 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! <http://www.swtworkbench.com> PGP Public Key (for confidential communications): http://www.coconut-palm-software.com/~djo/public_key.txt |
XSWT Screen Shot