字段辅助

通常,用户应该在简单字段(例如文本字段或组合框)中提供文本信息。虽然用来填充这些字段的应用程序代码通常比用来填充复杂窗口小部件(例如表或树)的代码简单得多,但这些“简单”字段通常会给用户带来更多负担。用户必须确定哪些字段需要内容、某个字段是否包含有效内容以及应该选择哪些选项。JFace 的字段辅助支持提供了一些类来帮助指导用户完成输入任务。

org.eclipse.jface.fieldassist 包通过两种方式提供辅助。带修饰字段支持允许您提供图像修饰,以便向用户提供有关特定字段状态的提示。内容建议支持允许您提供内容辅助弹出窗口,以便向用户提供内容选项。

带修饰字段

带修饰字段允许在窗口或对话框中定义的字段旁边放置图像修饰。可以将修饰放在字段四个角中某一个的旁边。与查看器很相似,带修饰字段旨在对 SWT 控件添加功能,同时仍提供对底层控件的访问。DecoratedField 的 API 允许在字段旁边添加修饰以及隐藏和显示那些修饰。提供了对底层控件的访问,因此,您可以使用现有 SWT API 来影响底层控件,例如设置其内容、颜色或字体。

创建带修饰字段

从外部看,带修饰字段的行为类似于单个控件。在内部,带修饰字段使用组合控件来管理字段及其修饰的布局。在大多数情况下,这应该不会对客户机应用程序产生影响。但是,这意味着带修饰字段必须执行控件的实际创建工作。例如,请研究以下片段,在此片段中,应用程序在它的其中一个对话框中创建了文本控件:

...
// Create a text field
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
...

为了修饰此字段,将以此方式创建此字段:

...
// Create a decorated field for a text control
DecoratedField field = new DecoratedField(parent, SWT.BORDER, new TextControlCreator());
Text text = (Text)field.getControl();
text.setText("some text");
...

用来创建基本控件的父代和样式位也用来创建带修饰字段。代码的主要差别是,提供了 IControlCreator 的实例,以便创建字段中所需的特定类型的控件。对于文本字段来说,可以使用 TextControlCreator 来控制控件。但是,也可以灵活地实现 IControlCreator, 以便在该字段中创建任何其他类型的控件(例如组合框或微调框)。

使用修饰

一旦创建了带修饰字段,就可以在四个位置中的某个位置对该字段添加修饰。请使用 SWT 位置常量来指定修饰的放置位置。要添加修饰,必须指定 FieldDecoration。这将定义修饰图像以及当用户将鼠标指针悬停在该修饰上时显示的可选描述文本。

...
// Create a field decoration and add it to the field
Image image = JFaceResources.getImage("myplugin.specialimage");
FieldDecoration mySpecialDecoration = new FieldDecoration(image, "This field is special");
field.addFieldDecoration(mySpecialDecoration, SWT.TOP | SWT.LEFT, false);
...

使用了布尔参数来指定是仅当控件具有焦点时才显示修饰还是应该始终显示修饰。如果是后者,修饰将一直显示。但是,可能还存在其他应该隐藏或显示修饰的情况。以下片段隐藏已创建的修饰。

...
// Something has occurred that makes me want to hide the decoration
field.hideDecoration(mySpecialDecoration);
...

如果更新了某个修饰的图像或描述,则应该通知该字段,以便重新显示该修饰。

...
// Something has made the field extra special
mySpecialDecoration.setDescription("This field is extra-special");
field.updateDecoration(mySpecialDecoration);
...

对带修饰字段和不带修饰字段进行布局

在对话框或窗口中对带修饰字段进行布局时,应该对字段的布局控件进行布局,而不是对底层简单控件进行布局。请再次研究用于创建文本控件的代码。在对文本控件进行布局时,应用程序将对该控件设置布局数据。

...
// Create a text field
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
// Set the layout data
GridData data = new GridData(IDialogConstants.ENTRY_FIELD_WIDTH, SWT.DEFAULT);
text.setLayoutData(data);
...

在对带修饰字段进行布局时,应用程序应该对字段的布局控件设置布局数据。根据所需布局的不同,可能必须根据修饰的大小来调整字段的大小。

...
// Create a decorated field for a text control
DecoratedField field = new DecoratedField(main, SWT.BORDER, new TextControlCreator());
Text text = (Text)field.getControl();
text.setText("some text");
// Set the layout data
GridData data = new GridData(IDialogConstants.ENTRY_FIELD_WIDTH +
   FieldDecorationRegistry.getDefault().getMaximumDecorationWidth(), SWT.DEFAULT);
field.getLayoutControl().setLayoutData(data);
...

字段辅助支持既未要求也未假定在特定对话框或窗口中只使用带修饰字段。但是,如果同时使用带修饰字段和简单控件,窗口布局就会变得有点复杂。为了使带修饰字段与不带修饰字段对齐,就必须考虑修饰宽度造成的缩进。修饰的宽度只是其图像的宽度。但是,如果使用的修饰具有不同的宽度,情况就会变得更复杂。在这种情况下,可以通过在 FieldDecorationRegistry 中注册所有修饰来简化操作。

字段修饰注册表

字段修饰注册表允许您注册字段修饰并使用字符串标识来访问这些修饰。这就使您能够方便地引用整个应用程序中使用的修饰。如果需要使修饰标识可供其他插件使用,则可以选择定义 API 以公布这些修饰标识。注意,注册修饰并不会管理那些修饰中的图像的生命周期。应用程序可以决定如何管理这些图像。例如,可使用 JFace 图像注册表来注册和管理图像的生命周期。此外,应用程序可能希望根据需要创建图像,并在不再需要该图像时将其废弃。FieldDecorationRegistry 中的注册方法的 Javadoc 说明了注册修饰时指定图像的不同方法。

通过在字段修饰注册表中注册修饰,还可以简化同时使用带修饰字段和不带修饰字段时的布局过程。缺省情况下,带修饰字段将查询字段修饰注册表,以确定修饰的最大宽度并确保所有修饰都使用此宽度。这意味着所有带修饰字段都将正确地对齐,而与任何特定修饰的宽度无关。为了使不带修饰字段对齐,可以使用 FieldDecorationRegistry 协议来获取最大修饰的宽度并进行必要的缩进。

...
// Create a text field
Text text = new Text(parent, SWT.BORDER);
text.setText("some text");
// Set the layout data
GridData data = new GridData();
data.horizontalAlignment = SWT.FILL;
data.horizontalIndent = FieldDecorationRegistry.getDefault().getMaximumDecorationWidth();
text.setLayoutData(data);
...

虽然字段辅助支持未指定应该如何使用修饰,但注册表还定义了标准修饰。因此,应用程序可以使用这些修饰来显示字段的某些状态。例如,以下片段将标准修饰用于必填字段:

...
// Create a decorated field with a required field decoration.
DecoratedField field = new DecoratedField(main, SWT.BORDER, new TextControlCreator());
FieldDecoration requiredFieldIndicator = FieldDecorationRegistry.getDefault().
   getFieldDecoration(FieldDecorationRegistry.DEC_REQUIRED);
field.addDecoratedField(requiredFieldIndicator, SWT.BOTTOM | SWT.LEFT, false);
...

内容建议

除了使用修饰来对字段添加注释以外,应用程序还可以提供内容建议辅助,以便为字段激活建议弹出窗口。可以在任意控件上安装 ContentProposalAdapter 以提供此行为。以下片段在文本控件上安装内容建议适配器。注意,此文本控件可以是由应用程序直接创建的控件,也可以是从带修饰字段中获取的控件。

...
autoActivationCharacters = new char[] { '#', '(' };
keyStroke = KeyStroke.getInstance("Alt+/");
// assume that myTextControl has already been created in some way
ContentProposalAdapter adapter = new ContentProposalAdapter(
	myTextControl, new TextContentAdapter(),
	new SimpleContentProposalProvider(new String [] {"ProposalOne", "ProposalTwo", "ProposalThree"}),
	keyStroke, autoActivationCharacters);

为了在用户从弹出窗口中选择建议时获取和设置控件内容,必须向适配器提供 IControlContentAdapter 实例,该实例可以检索和设置特定类型控件的内容。对于文本字段来说,可以使用 TextContentAdapter 类。但是,也可以灵活地实现 IControlContentAdapter,以便将内容建议适配器与任何其他类型的控件配合使用。

创建内容建议适配器时,还必须指定 IContentProposalProvider 的实例,以便从该实例中检索建议本身。此提供程序负责返回内容建议的数组。建议本身被指定成 IContentProposal 的实例。从这些实例中,可以获取建议的标签和内容以及其他信息(例如,建议的详细描述)。

在上面的示例中,使用了 SimpleContentProposalProvider。此提供程序是通过将一个简单的字符串数组指定成内容建议来定义的。这个简单的提供程序实现了必要的协议,以将每个字符串映射到所需的 IContentProposalIContentProposalProvider 的灵活性使您能够实现具有高级功能的建议提供程序,例如,根据控件内容对建议进行过滤、在弹出窗口而不是所插入的实际内容中提供说明性标签以及指定插入建议后的预期光标位置。请参阅字段辅助示例并搜索 IContentProposalProvider 的实现者以了解高级用法。

配置内容建议适配器

我们已经看到,内容建议适配器的基本定义包括要获取建议的控件、用来改变控件内容的内容适配器以及用于在弹出窗口中定义建议列表的建议提供程序。除这些基本内容以外,还可以通过许多方法来配置内容建议适配器:

字段辅助示例允许您在示例首选项中配置这些选项以及尝试不同的选项组合。例如,可以对适配器进行配置,以便通过击键显式地调用该适配器并将建议内容插入到控件中,从而使该适配器的行为类似于文本编辑器内容辅助。也可以将适配器配置成不使用具体的击键、自动激活字符和内容替换功能,这样,它的行为就更像 Web 浏览器 URL 或搜索字段中使用的提前补全输入风格。请参阅 Javadoc 以获取有关这些方法及其相互交互方式的具体细节。

工作台字段辅助

JFace 级的字段辅助支持使应用程序能够非常灵活地确定如何修饰字段以及显示字段内容建议。此支持非常适合于独立 JFace 应用程序或独立富客户机应用程序。 但是,如果应用程序打算与其他插件(例如,Eclipse SDK 或第三方插件)集成,则您可能想以一种与其他插件一致的方法来使用字段辅助支持。工作台定义了在进行特定类型交互时使用字段辅助的实用程序类。

例如,ContentAssistField 类创建了一个字段,该字段将提供灯泡修饰以提示用户有内容辅助可用。它还配置了以内容辅助样式插入内容的内容建议适配器。最后,它为工作台级内容辅助命令提供了处理程序,因此,当用户调用工作台键绑定中指定的击键或触发器序列时,将打开内容建议弹出窗口。请参阅 org.eclipse.ui.fieldassist 包以了解有关这些实用程序类的更多详细信息。

随着工作台中字段辅助应用范围的扩大以及修饰在特定字段状态下的用法的标准化,此包也会随之发展。