打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Feeling - BlogJavaSWT 的易访问性(Accessibility)
SWT 的易访问性(Accessibility)
最近由于项目的需要,研究了一下SWT的Accessibility。关于Accessibility,这是一个很难缠的search,给残疾人用的东东,正常人基本上不会用到,网上文章少之又少。可以查阅到的一篇来自于IBM developerWorks的文章:使用 Eclipse 创建易访问的应用程序:介绍易访问性是一个总括的术语,它包括生成使具有各种残疾的人易用的产品所涉及的所有东西和人。美国已经立法,不符合Accessibility规范的软件不能够在政府部门销售。在美国,创建易访问的应用程序的主要商业(对比人道主义)驱动力是 Rehabilitation Act 1998年的修正法案,称为 Section 508。Section 508 要求联邦机构使他们的信息技术对带有残疾的人易于访问。
Eclipse拥有一个包含 API:org.eclipse.swt.accessibility 的易访问性包。Eclipse 3.0 易访问性特征是基于MSAA 1.3 程序设计模型所提供的功能。您可以将 Eclipse 中的 Accessible 对象联系到每个控件上,并且org.eclipse.swt.accessibility 接口中的方法集对应 MSAA 1.3 IAccessible 界面中的消息集。
org.eclipse.swt.accessibility 的接口:
Interface Summary
AccessibleControlListener Classes that implement this interface provide methods that deal with the events that are generated when an accessibility client sends a message to a control.
AccessibleListener Classes that implement this interface provide methods that deal with the events that are generated when an accessibility client sends a message to a control.
AccessibleTextListener Classes that implement this interface provide methods that deal with the events that are generated when an accessibility client sends a message to a control.
SWT 自身包含的控件中只有寥寥几个用到了Accessibility,JFace里也不多。看了所有的Accessibility相关代码,只能总结一部分规律:
一般的复杂控件是没有必要定义Accessibility的。
如果是模拟实现一个比较简单的基本控件,比如Combo,Label,Spinner等,有必要定义Accessibility。
所有的自定义控件都要实现AccessibleControlListener接口。
所有的包含文本框的控件都要实现AccessibleTextListener接口。
设置AccessibleListener的getHelp( )最好是给控件加上Tooltip,因为Wineyes这些屏幕阅读器阅读都是根据Tooltip,无视getHelp( )的设置。
设置AccessibleListener的getName( ),一般来说,可以设置为这个控件相关联的Label的Text或者该控件上的某部分文字,自己斟酌考虑设置。
getKeyboardShortcut( ),考虑控件的快捷操作方式,如果需要的话。
以下是CCombo的Accessibility代码:
void initAccessible() {
AccessibleAdapter accessibleAdapter = new AccessibleAdapter () {
publicvoid getName (AccessibleEvent e) {
String name = null;
Label label = getAssociatedLabel ();
if (label != null) {
name = stripMnemonic (label.getText());
}
e.result = name;
}
publicvoid getKeyboardShortcut(AccessibleEvent e) {
String shortcut = null;
Label label = getAssociatedLabel ();
if (label != null) {
String text = label.getText ();
if (text != null) {
char mnemonic = _findMnemonic (text);
if (mnemonic != '\0') {
shortcut = "Alt+"+mnemonic;
}
}
}
e.result = shortcut;
}
publicvoid getHelp (AccessibleEvent e) {
e.result = getToolTipText ();
}
};
getAccessible ().addAccessibleListener (accessibleAdapter);
text.getAccessible ().addAccessibleListener (accessibleAdapter);
list.getAccessible ().addAccessibleListener (accessibleAdapter);
arrow.getAccessible ().addAccessibleListener (new AccessibleAdapter() {
publicvoid getName (AccessibleEvent e) {
e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open");
}
publicvoid getKeyboardShortcut (AccessibleEvent e) {
e.result = "Alt+Down Arrow";
}
publicvoid getHelp (AccessibleEvent e) {
e.result = getToolTipText ();
}
});
getAccessible().addAccessibleTextListener (new AccessibleTextAdapter() {
publicvoid getCaretOffset (AccessibleTextEvent e) {
e.offset = text.getCaretPosition ();
}
publicvoid getSelectionRange(AccessibleTextEvent e) {
Point sel = text.getSelection();
e.offset = sel.x;
e.length = sel.y - sel.x;
}
});
getAccessible().addAccessibleControlListener (new AccessibleControlAdapter() {
publicvoid getChildAtPoint (AccessibleControlEvent e) {
Point testPoint = toControl (e.x, e.y);
if (getBounds ().contains (testPoint)) {
e.childID = ACC.CHILDID_SELF;
}
}
publicvoid getLocation (AccessibleControlEvent e) {
Rectangle location = getBounds ();
Point pt = toDisplay (location.x, location.y);
e.x = pt.x;
e.y = pt.y;
e.width = location.width;
e.height = location.height;
}
publicvoid getChildCount (AccessibleControlEvent e) {
e.detail = 0;
}
publicvoid getRole (AccessibleControlEvent e) {
e.detail = ACC.ROLE_COMBOBOX;
}
publicvoid getState (AccessibleControlEvent e) {
e.detail = ACC.STATE_NORMAL;
}
publicvoid getValue (AccessibleControlEvent e) {
e.result = getText ();
}
});
text.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter () {
publicvoid getRole (AccessibleControlEvent e) {
e.detail = text.getEditable () ? ACC.ROLE_TEXT : ACC.ROLE_LABEL;
}
});
arrow.getAccessible ().addAccessibleControlListener (new AccessibleControlAdapter() {
publicvoid getDefaultAction (AccessibleControlEvent e) {
e.result = isDropped () ? SWT.getMessage ("SWT_Close") : SWT.getMessage ("SWT_Open");
}
});
}
在SWT控件中,包含Accessibility功能的控件有:CCombo,CLabel,CTableFolder,StyledText。
posted @2006-06-19 17:38 三人行,必有我师焉 阅读(1171) |评论 (4)编辑 收藏
扩展Eclipse视图弹出菜单(二)
上一篇文章我们知道了Eclipse弹出菜单的基本用法。其实Eclipse的弹出菜单可以用来做很多文章,简单一点的根据文件类别,我们可以进行不同的文件操作,比如Ant的build.xml我们可以用来build,Java文件我们可以用JavaEditor打开,这些基于文件类型的操作我们都可以很容易的实现。但是还有一种情况,如果文件类型一样,我们想进行不同的操作,该怎么实现呢?实际上这样的应用很多,比如同样是Java文件,含有main方法的Java文件有Run和Debug的选项,其它的都没有。还有现在的框架都是基于XML文件进行配置的,如果一个项目使用了多个框架,我们怎么根据不同的XML文件进行框架的区分呢?答案就是enablement的test。
<!ELEMENT EMPTY>
<!ATTLIST test
property CDATA #REQUIRED
args     CDATA #IMPLIED
value    CDATA #IMPLIED>
This element is used to evaluatethe property state of the object in focus. The set of testableproperties can be extended using the propery tester extension point. Thetest expression returns EvaluationResult.NOT_LOADED if teh propertytester doing the actual testing isn't loaded yet.
property - the name of an object's property to test.
args - additional arguments passed to the property tester. Multiple arguments are seperated by commas. Each individual argument is converted into a Java base type using the same rules as defined for the value attribute of the test expression.
value - the expected value of the property. Can be omitted if the property is a boolean property. The test expression is supposed to return EvaluationResult.TRUE if the property matches the value and EvaluationResult.FALSE otherwise. The value attribute is converted into a Java base type using the following rules: the string "true" is converted into Boolean.TRUE
the string "false" is converted into Boolean.FALSE
if the string contains a dot then the interpreter tries to convert the value into a Float object. If this fails the string is treated as a java.lang.String
if the string only consists of numbers then the interpreter converts the value in an Integer object.
in all other cases the string is treated as a java.lang.String
the conversion of the string into a Boolean, Float, or Integer can be suppressed by surrounding the string with single quotes. For example, the attribute value="'true'" is converted into the string "true"
比如我们要让含有main方法的Java文件它的右键弹出菜单包含一个额外的选项“This is main class”,需要编写如下的Plugin.xml:
<plugin>
<extension
point="org.eclipse.ui.popupMenus">
<objectContribution
id="Advanced.PopupMenus"
objectClass="java.lang.Object">
<action id="Advanced.PopupMenus.Action"
label="AdvancedPopupMenus"
style="pulldown"
menubarPath="additions"
class="advancedpopupmenus.popup.actions.AdvancedPopupMenusAction"
enablesFor="+">
</action>
<enablement>
<test property="advancedpopupmenus.popup.visable"/>
</enablement>
</objectContribution>
</extension>
<extension point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
namespace="advancedpopupmenus.popup"
properties="visable"
type="java.lang.Object"
class="advancedpopupmenus.popup.actions.VisablePropertyTester"
id="advancedpopupmenus.popup.propertyTesters.visable">
</propertyTester>
</extension>
</plugin>
我们需要检测在当前情况下是否需要显示这个菜单项,使用扩展点org.eclipse.core.expressions.propertyTesters:
<!ELEMENT propertyTester EMPTY>
<!ATTLIST propertyTester
id         CDATA #REQUIRED
type       CDATA #REQUIRED
namespace  CDATA #REQUIRED
properties CDATA #REQUIRED
class      CDATA #REQUIRED>
id - unique identifier for the property tester
type - the type to be extended by this property tester
namespace - a unique id determining the name space the properties are added to
properties - a comma separated list of properties provided by this property tester
class - the name of the class that implements the testing methods. The class must be public and extend org.eclipse.core.expressions.PropertyTester with a public 0-argument constructor.
这里只须注意propertyTester的namespace和properties正好对应test的property。
至于检测的逻辑我们在advancedpopupmenus.popup.actions.VisablePropertyTester中实现,这个类必须继承自org.eclipse.core.expressions.PropertyTester。
package advancedpopupmenus.popup.actions;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.CompilationUnit;
public class VisablePropertyTester extends PropertyTester
{
public boolean test( Object receiver, String property, Object[] args,
Object expectedValue )
{
if ( !( receiver instanceof CompilationUnit ) )
return false;
CompilationUnit unit = (CompilationUnit) receiver;
try
{
IType[] types = unit.getTypes( );
if ( types == null )
return false;
for ( int i = 0; i < types.length; i++ )
{
IMethod[] methods = types[i].getMethods( );
if ( methods == null )
return false;
for ( int j = 0; j < methods.length; j++ )
{
if ( methods[j].isMainMethod( ) )
return true;
}
}
}
catch ( JavaModelException e )
{
e.printStackTrace( );
}
return false;
}
}
我们只要判断接受的Java文件中是否含有main方法,如果有,则返回True,没有则返回False。
如果我们是要接受一个Web开发的配置文件,我们可以这样写:
<plugin>
<extension
point="org.eclipse.ui.popupMenus">
<objectContribution
id="Advanced.PopupMenus"
objectClass="org.eclipse.core.resources.IFile"
nameFilter="*.xml">
<action id="Advanced.PopupMenus.Action"
label="This is web xml"
style="pulldown"
menubarPath="additions"
class="advancedpopupmenus.popup.actions.AdvancedPopupMenusAction"
enablesFor="+">
</action>
<enablement>
<test property="advancedpopupmenus.popup.visable"/>
</enablement>
</objectContribution>
</extension>
<extension point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
namespace="advancedpopupmenus.popup"
properties="visable"
type="org.eclipse.core.resources.IFile"
class="advancedpopupmenus.popup.actions.VisablePropertyTester"
id="advancedpopupmenus.popup.propertyTesters.visable">
</propertyTester>
</extension>
</plugin>
注意和上一个例子不同的地方,objectClass,nameFileter和type(在上一个例子中,我们也可以使用objectClass="org.eclipse.core.resources.IFile" nameFilter="*.java"),相应的我们的VisablePropertyTester类也要做一些改动:
package advancedpopupmenus.popup.actions;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.core.resources.IFile;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
public class VisablePropertyTester extends PropertyTester
{
public boolean test( Object receiver, String property, Object[] args,
Object expectedValue )
{
if ( !( receiver instanceof IFile ) )
return false;
IFile xml = (IFile) receiver;
try
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance( );
DocumentBuilder db = dbf.newDocumentBuilder( );
Document doc = db.parse( xml.getContents( ) );
DocumentType type = doc.getDoctype( );
if(type.getSystemId( ).equalsIgnoreCase( "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd" ))return true;
}
catch ( Exception e )
{
e.printStackTrace( );
}
return false;
}
}
这样根据不同的xml SystemID,我们就能够知道到底这是哪一种框架的配置文件了
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
在awt/swing程序中添加swt (Browser控件的使用)【转】 - Picses...
SWT实现弹出日历控件
Swt常用控件中文教程
JAVA.SWT/JFace: SWT高级控件之SWT的高级应用
SWT 和 JFace, 第 2 部分: 简介
Eclicpse3.1.1下配置SWT,打包发布SWT程序,转EXE
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服