配置 DLTK 首选项
前面的讨论显示了用户首选项如何决定文本显示。现在我们更进一步,演示如何创建接收用户首选项的页面。您可以通过单击 Eclipse 中的 Window > Preferences 来访问这些首选项。在讨论的最后,我将解释用户首选项如何将脚本解释器集成到 IDE 中。
首选项存储
Eclipse 的首选项存储 就像一个属性文件:它包含用于识别用户首选项设置的名称-值对。但它们之间有两处重要区别。除了当前值之外,每个首选项都包含一个默认值,并且首选项值必须是以下 6 中基本类型之一:
Boolean
int
long
float
double
String
通过调用由 IPreferenceStore 接口定义的方法来存储和获取首选项。setValue 和 setDefaultValue 方法添加并更新首选项。要获取首选项的值,可以调用 getBoolean、getInt、getLong、getFloat、getDouble 或 getString 之一。有一些类似的方法可以访问默认值,比如 getDefaultDouble。
要访问与 SWT 对象有关的首选项(尤其是 RGB、Rectangle、FontData 和 FontData[] 对象),可以调用 PreferenceConverter 类中的方法。
在初始化期间,DLTK ScriptEditor 创建了一个包含 4 个 IPreferenceStore 对象的 ArrayList:
-
ScopedPreferenceStore,是为 Octave 插件(org.dworks.octaveide)创建的
-
ScopedPreferenceStore,是为 Eclipse 文本编辑器插件(org.eclipse.ui.editors.text)创建的
- 一个提供与项目有关的首选项的
EclipsePreferencesAdapter,包含需要编辑的脚本
- 一个
PreferencesAdapter,包含与 DLTK 核心相关联的首选项
这些存储被合并成一个 ChainedPreferenceStore。如果两个或两个以上的首选项存储包含相同的首选项,则由先添加的存储提供值。
初始化首选项
Eclipse 允许初始化期间使用扩展点 org.eclipse.core.runtime.preferences 设置首选项。Octave IDE 扩展这个点并将 OctavePreferenceInitializer 类标识为为 IDE 首选项提供默认值。反过来,OctavePreferenceInitializer 类又扩展抽象类 AbstractPreferenceInitializer,后者惟一要求的方法是 initializeDefaultPreferences。IDE 在初始化期间调用这个方法。清单 8 显示了如何通过代码实现它。
清单 8. 初始化默认首选项
public void initializeDefaultPreferences() {
IPreferenceStore store = OctavePlugin.getDefault().getPreferenceStore();
OctavePreferenceConstants.initializeDefaultValues(store);
}
|
这个简单的例程访问 Octave 插件的首选项存储,并调用 OctavePreferenceConstants 类来初始化存储的值。它是 DLTK 的 PreferenceConstants 类的子类,PreferenceConstants 类能够定义并初始化各种常见的脚本首选项。在本教程中,仅初始化用于处理语法颜色的首选项。清单 9 展示如何实现初始化。
清单 9. 设置语法颜色首选项
public static void initializeDefaultValues(IPreferenceStore store) {
// Set default preferences for the editor
PreferenceConstants.initializeDefaultValues(store);
// Make keywords blue and bold
PreferenceConverter.setDefault(store, DLTKColorConstants.DLTK_KEYWORD,
new RGB(40, 0, 200));
store.setDefault(DLTKColorConstants.DLTK_KEYWORD +
PreferenceConstants.EDITOR_BOLD_SUFFIX, true);
// Set default values for other preferences
PreferenceConverter.setDefault(store,
DLTKColorConstants.DLTK_SINGLE_LINE_COMMENT, new RGB(25, 200, 25));
PreferenceConverter.setDefault(store, DLTKColorConstants.DLTK_NUMBER,
new RGB(255, 25, 25));
PreferenceConverter.setDefault(store, DLTKColorConstants.DLTK_STRING,
new RGB(50, 100, 100));
}
|
Octave 首选项的第一个选项用于处理关键字。它的代码通过两个步骤在 IDE 中配置关键字的颜色和样式(bold/italics/strikethrough)。首先,调用 PreferenceConverter 将 DLTKColorConstants.DLTK_KEYWORD 与蓝色关联起来。其次,调用 store.setDefault 方法将 DLTKColorConstants.DLTK_KEYWORD + PreferenceConstants.EDITOR_BOLD_SUFFIX 和 true 关联起来。这两行代码确保在使用 DLTKColorConstants.DLTK_KEYWORD 初始化任何 Token 时,相应的文本就显示为粗体蓝色。
Preference pages 和 configuration blocks
现在您已经知道如何初始化首选项,那么也应该为用户提供配置首选项的机会。Eclipse 通过 preference pages 来实现这个功能。DLTK 使用称为 configuration blocks 的对象简化了这些页面的配置过程。这个小节将描述这两个类,以及它们如何协作以在 Octave IDE 中提供用户首选项。
Eclipse preference pages
单击 Eclipse 中的 Window > Preferences 时,Preferences 窗口的左边面板将以层次结构的方式显示用户可配置的选项。对于 Octave IDE,您需要使用一个称为 Octave 并带有子首选项的顶级首选项,用于处理语法颜色和 Octave 解释器。图 4 显示了这个窗口。
图 4. Octave 首选项窗口
在 Octave 项目中,plugin.xml 通过扩展 org.eclipse.ui.preferencePages 定义 3 个首选项主题。每个扩展都需要具有 id、name 和 class 属性。两个子首选项具有一个额外属性 category,它命名父首选项的 id。清单 10 给出了这些扩展。
清单 10. Octave 首选项扩展
<extension point="org.eclipse.ui.preferencePages">
<page
class="org.dworks.octaveide.preferences.OctaveMainPreferencePage"
id="org.dworks.octaveide.preferences.OctaveMainPreferencePage"
name="%MainPreferencePage.name"/>
<page
category="org.dworks.octaveide.preferences.OctaveMainPreferencePage"
class="org.dworks.octaveide.preferences.OctaveSyntaxColorPage"
id="org.dworks.octaveide.preferences.OctaveSyntaxColorPage"
name="%SyntaxColorPreferencePage.name"/>
<page
category="org.dworks.octaveide.preferences.OctaveMainPreferencePage"
class="org.dworks.octaveide.preferences.OctaveInterpreterPreferencePage"
id="org.dworks.octaveide.preferences.OctaveInterpreterPreferencePage"
name="%InterpreterPreferencePage.name"/>
</extension>
|
class 属性命名一个实现 IWorkbenchPreferencePage(IPreferencePage 的子接口)的类。DLTK 提供它自己的 IWorkbenchPreferencePage 实现,称为 AbstractConfigurationBlockPreferencePage。DLTK 还提供几个有其他用途的子类。图 5 描述了这些类接口的关系。
图 5. Preference page 类的层次结构
清单 10 中的 3 个类都是 AbstractConfigurationBlockPreferencePage 的直接子类。查看它们的 Java 文件时,可以看到它们包含的代码很少。每个类提供一个 ID、一个标签,以及到插件的首选项存储的访问。此外,每个 AbstractConfigurationBlockPreferencePage 必须实现方法 createConfigurationBlock(),该方法构造提供页面图形元素的对象。这个对象必须实现 DLTK 接口 IPreferenceConfigurationBlock。下一小节将讨论这个重要的接口。
DLTK configuration blocks
对呈现 IDE 首选项而言,最难的部分就是构建 UI。例如,Octave 语法着色首选项页面不仅允许用户选择颜色和样式,并且还提供一个用于显示实际效果的嵌入式文本编辑器。从头构建这些图形控件非常耗费时间,不过 DLTK 的 IPreferenceConfigurationBlock 能够帮上大忙。图 6 显示了 configuration block 类的层次结构。
图 6. Configuration block 类的层次结构
语法着色 configuration block 类
相关的第一个类是 AbstractScriptEditorColoringConfigurationBlock,它为用户提供语法着色首选项。由 createSyntaxPage 方法完成主要工作,即创建图形首选项页面。具体来讲,它构造了一个 TreeViewer,以显示语法类型和一组用于表示颜色和样式首选项的按钮。然后,它调用 createPreviewer 构建嵌入式文本编辑器。
Octave 插件代码包含 AbstractScriptEditorColoringConfigurationBlock 的一个子类,称为 OctaveSyntaxColorConfigurationBlock。除了构造器之外,还实现了 4 个方法:
createPreviewViewer
- 返回一个包围嵌入式文本编辑器的查看器
createSimpleSourceViewerConfiguration
- 返回一个在嵌入式文本编辑器中配置查看器的基本对象
setDocumentPartitioning
- 调用
IDocumentSetupParticipant 来设置文档的分区
getSyntaxColorListModel
- 返回一个 2-D 数组,它识别可以添加颜色的不同语法类型,以及首选项存储中的对应键
前 3 个方法很好理解,因为嵌入式文本编辑器不需要复杂的查看器、查看器配置对象或文档设置参与者。然而最后一个方法 getSyntaxColorListModel 需要解释一下。这个方法提供一个 2-D 数组,它的元素对应于页面的 TreeViewer 中的语法类型。每个元素需要具有 3 个信息:名称、类别和页面首选项存储中的对应键。
回过头来看看这个例子,图 4 表明 Octave 语法颜色模型包含 4 个语法类型:keywords、numbers、strings 和 single-line comments。前 3 个语法类型属于 General 范围,而最后一个语法类型属于 Comment 范围。清单 11 中的代码显示了如何在 OctaveSyntaxColorConfigurationBlock.getSyntaxColorListModel 中配置这些类型。
清单 11. 创建语法颜色列表模型
protected String[][] getSyntaxColorListModel() {
return new String[][] {
{ "Single-Line Comments", DLTKColorConstants.DLTK_SINGLE_LINE_COMMENT,
sCommentsCategory },
{ "Keywords", DLTKColorConstants.DLTK_KEYWORD, sCoreCategory },
{ "Strings", DLTKColorConstants.DLTK_STRING, sCoreCategory },
{ "Numbers", DLTKColorConstants.DLTK_NUMBER, sCoreCategory }};
}
|
当用户在页面中更改首选项设置并单击 OK 时,页面将更新首选项存储中相应的值。编辑器通过更新文本的表示来响应首选项更改。
解释器首选项
图 4 中的最后一个首选项选项用于设置 IDE 的脚本解释器。DLTK 提供两个类来实现这个功能:ScriptInterpreterPreferencePage 和 InterpretersBlock。InterpretersBlock 创建页面的图形控件,其中包含一个提供说明的 Label;一个列出所有可用解释器的 CheckboxTableViewer;以及一组允许用户添加、编辑、复制、删除和搜索解释器的按钮。图 7 显示了这个页面,以及用户单击 Add 时出现的窗口。
图 7. 解释器首选项页面和窗口
抽象类 InterpretersBlock 要求子类实现两个方法:getCurrentNature 和 createInterpreterDialog。第一个方法返回一个表示解释器、源代码语言和其他相关对象的 String。通常在 DLTK 扩展点中使用这种特征,它非常重要。如果您的 Eclipse 为不同的动态语言包含多个基于 DLTK 的特性,就很容易根据各自的特征区分它们。
第二个方法 createInterpreterDialog 构造一个窗口,当用户在首选项页面上单击 Add 时弹出。这个窗口(见图 7)必须至少包含 4 个信息之一:可执行解释器的位置、解释器的名称、解释器的类型,以及解释器需要执行的库的位置。要构造这个窗口,createInterpreterDialog 方法需要 DLTK 类 AddScriptInterpreterDialog 的一个实例。
AddScriptInterpreterDialog 构造器接受一个解释器类型的数组和一个实现 IInterpreterInstall 的对象。具有多个解释器类型使 IDE 能够支持同一语言的多个解释器。Octave IDE 仅支持一种安装类型,并且使用 org.eclipse.dltk.launching.interpreterInstallTypes 的一个扩展在 plugin.xml 中标识该类型。这些首选项扩展如清单 12 所示。
清单 12. Octave 首选项扩展
<extension point="org.eclipse.dltk.launching.interpreterInstallTypes">
<interpreterInstallType
class="org.dworks.octaveide.launch.OctaveInterpreterInstallType"
id="org.dworks.octaveide.launch.OctaveInterpreterInstallType">
</interpreterInstallType>
</extension>
|
class 属性标识一个实现 IInterpreterInstallType 的对象。每个安装类型都有一个名称、ID 和特征(一个用于标识解释器和源类型的 String),以及解释器和所有必需库的位置。另外,每个 IInterpreterInstallType 必须创建一个以上的 IInterpreterInstall 对象。
尽管 IInterpreterInstallType 对象定义了解释器安装的一个类,但还必须为每个特定安装创建一个 IInterpreterInstall 对象。这个对象用作解释器的主数据存储对象,它包含以下信息:
- 名称
- 解释器安装的标签
- ID
- 解释器安装的逻辑标识符
- 特征
- IDE 的逻辑标识符(解释器和源文件等)
- 安装位置
- 解释器安装的路径
- 库的位置
- 解释器所需的库的路径
- 执行环境
- 环境变量和进程配置
- 解释器参数
- 指向解释器的参数
最后,每个 IInterpreterInstall 必须提供对 IInterpreterRunner 对象的访问。这个对象负责实际启动解释器,下一小节不仅讨论它的工作方式,还讨论它如何融入到解释器-IDE 交互中。
|