背景
Eclipse 從推出到現在一直非常成功,並且大部分成功源自構成 Eclipse 平 台的各個項目。其中包括的一個項目名為 Plug-in Development Environment( PDE)。如果您曾經在 Eclipse 中創建過插件,那麼一定使用過 PDE。PDE 是一 組用於幫助創建、打包和管理插件的工具。
我們將集中精力研究 PDE 中提供的模板功能。如果您還記得在 Eclipse 中 嘗試創建第一個插件時的情景,則知道一切都是從 New Plug-in Project 向導 開始的。
圖 1. PDE 插件向導
然後,在創建第一個插件的過程中,您無意中發現了很有價值的東西。
圖 2. PDE 插件向導模板
噢,我的 —— 模板!PDE 提供了各種模板讓您開始 Eclipse 插件創建之旅 。本文的目的是討論如何創建這些模板,從而簡化最終用戶使用擴展點或代碼時 面臨的學習曲線。
創建模板
目標
我發現學習知識的最佳方法是通過一個良好的簡單示例。那麼,猜猜是什麼 ?那就是我們今天將要做的事情。我們將開發一個用於創建單純視圖的簡單模板 。我希望通過本文可以為將來的模板創建工作打下基礎。
創建插件
本次旅程的第一站是創建新插件項目(File > New > Project > Plug-in Project)。請使用模板。確保項目與 org.eclipse.pde.ui 之間存在 依賴性。此操作完成後,可以轉至插件編輯器的 Extensions 選項卡,然後開始 創建模板。
模板向導
用於創建模板的最重要的擴展點是 org.eclipse.pde.ui.pluginContent。此 擴展點能夠貢獻用於為 PDE 插件項目創建附加內容的向導。創建了插件列表和 關鍵文件後,可以使用這些向導來將更多文件和擴展添加到初始架構中。此向導 的實現將根據用戶在向導中的選擇基於自定義的參數化模板添加內容。現在,讓 我們開始使用此擴展點。
圖 3. 示例擴展頁面
在圖 3 中,我們定義了一個帶有 ID (com.ibm.pde.simple.template.wizard)、名稱(Simple View Wizard)圖標 和類定義的新向導(參見以下代碼)。類定義的重要方法是 createTemplateSections(),該方法負責返回驅動內容創建的模板部分。下一節 將討論如何創建模板文件以及創建之後究竟有哪些內容駐留在模板部分中。
清單 1. SimpleViewTemplateWizard.java
package com.ibm.pde.simple.template;
import org.eclipse.pde.ui.IFieldData;
import org.eclipse.pde.ui.templates.ITemplateSection;
import org.eclipse.pde.ui.templates.NewPluginTemplateWizard;
public class SimpleViewTemplateWizard extends NewPluginTemplateWizard {
protected IFieldData fData;
public void init(IFieldData data) {
super.init(data);
fData = data;
setWindowTitle("Simple View Wizard");
public ITemplateSection[] createTemplateSections() {
return new ITemplateSection[] {new SimpleViewTemplateSection()};
}
}
模板文件
圖 4. 模板項目結構
本次旅程的下一站是創建用於生成代碼的模板。為此,必須正確設置項目。 如果看一看圖 4,則會發現有一個 templates_3.2 文件夾。此文件夾的名稱十 分重要,因為它將指示 PDE 此模板適用於哪些版本的 Eclipse。如果希望模板 可以在 V3.1 及更高版本上運行,請將文件夾命名為 templates_3.1。此模板文 件夾的子文件夾是 viewtemplate 並且表示需要與模板關聯起來的文件分組,稱 為 分區。可以將此文件夾命名為任意名稱。
在分區文件夾下,有兩個文件夾:bin 和 java。這兩個文件夾包含創建模板 時將復制的內容。java 文件夾中的內容非常重要,因為這是表示視圖的類。由 於模板系統將為用戶需要的名稱自動換出變量 $className$,因此將其命名為 $className$.java。
在此類文件內,還有一些需要用戶自定義的變量替換。這些變量替換的名稱 十分靈活,將在下一節中討論,討論的主要內容集中在模板分區上。
清單 2. $className$.java
package $packageName$;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.part.ViewPart;
public class $className$ extends ViewPart {
public void createPartControl(Composite parent) {
Label label = new Label(parent, SWT.CENTER);
%if importantMessage
String message = new String("$message$!!!");
%else
String message = new String("$message$");
%endif
label.setText(message);
}
public void setFocus() {}
}
模板分區
模板分區是包含驅動模板輸入的 UI 和控制邏輯的 Java 類。模板分區必須 實現 ITemplateSection 接口。為方便起見,PDE 提供了一個抽象類 OptionTemplateSection,使用它可以為您節省大量時間。可以對模板分區執行 的操作有很多(我將把這些內容給您留作練習以研究附帶的代碼樣例),我們將 去關注更重要的內容。第一步是確保通過 addPages(...) 方法添加向導頁面。 在這個簡單的例子中,我們只在第一個頁面中添加一個頁面。
清單 3. SimpleViewTemplateSection.java
...
public void addPages(Wizard wizard) {
WizardPage page = createPage(0, IHelpContextIds.TEMPLATE_INTRO);
page.setTitle("Simple View Template");
page.setDescription("Creates a simple view");
wizard.addPage(page);
markPagesAdded();
}
...
下一步是為客戶提供 UI 以便他們可以使用模板。通過聲明模板所使用的變 量,也可以通過使用 addOption(...) 方法添加選項來完成。在我們的類中,有 一種方便的方法 createOptions(),構造函數將調用此方法來創建選項。
清單 4. SimpleViewTemplateSection.java
...
private static final String KEY_CLASS_NAME = "className";
private static final String KEY_VIEW_NAME = "viewName";
private static final String KEY_MESSAGE_NAME = "message";
private static final String KEY_IMP_MESSAGE_NAME = "importantMessage";
...
private void createOptions() {
addOption(KEY_CLASS_NAME, "Class Name ", "SimpleView", 0);
addOption(KEY_VIEW_NAME, "View Name", "SimpleView", 0);
addOption(KEY_MESSAGE_NAME, "Message", "Hello World", 0);
addOption(KEY_IMP_MESSAGE_NAME, "Important?", false, 0);
}
...
圖 5. 簡單的視圖選項向導頁面
模板系統提供了若干種方法幫助添加選項;在 BaseOptionTemplateSection 類中可以看到這些方法的實現。但是,如果需要比模板系統提供的更大的靈活性 ,建議使用 registerOption(...) 方法。可以創建一組自己的選項,例如,如 果需要使用組合框選項,則需要將 ComboChoiceOption 實例化並調用 registerOption(...) 方法(有關選項的說明,請參見表 1;有關完整的類型層 次結構,請參見圖 6)。
表 1. PDE 模板選項
選項(類名) 說明 BlankField 用於在模板分區向導頁面中創建空白空間 StringOption 用於在模板分區向導頁面中收集來自用戶的字符串 BooleanOption 用於在模板分區向導頁面中收集來自用戶的布爾型選項 RadioChoiceOption 用於在模板分區向導頁面中收集來自用戶的一組單選選項 ComboChoiceOption 用於在模板分區向導頁面中收集來自用戶的一組組合選項 ChoiceOption 不建議使用 —— 請使用 RadioChoiceOption 或 ComboChoiceOption
圖 6. 選項層次結構
最後一步是編寫創建和填充感興趣的擴展點的代碼。在我們的簡單示例中, 我們只關注了 org.eclipse.ui.views 擴展點。在 PDE 模板系統中,創建模板 時將調用 updateModel(...) 方法,並且在這裡希望您以模板創建者的身份創建 擴展以及其他內容。另請注意,還可以創建多個擴展點,即使下面的代碼清單顯 示只創建一個擴展點。
清單 5. SimpleViewTemplateSection.java
...
protected void updateModel(IProgressMonitor monitor) throws CoreException {
IPluginBase plugin = model.getPluginBase();
IPluginModelFactory factory = model.getPluginFactory();
// org.eclipse.core.runtime.applications
IPluginExtension extension = \
createExtension("org.eclipse.ui.views", true);
IPluginElement element = factory.createElement (extension);
element.setName("view");
element.setAttribute("id", getStringOption (KEY_CLASS_NAME));
element.setAttribute("name", getStringOption (KEY_VIEW_NAME));
element.setAttribute("icon", "icons/sample.gif");
String fullClassName =
getStringOption(KEY_PACKAGE_NAME)\
+"."+getStringOption (KEY_CLASS_NAME);
element.setAttribute("class", fullClassName);
extension.add(element);
plugin.add(extension);
}
...
org.eclipse.pde.ui.templates
在結束之前,需要注意的是 org.eclipse.pde.ui.templates 擴展點非常重 要。此擴展點提供了通向自定義插件向導的入口。如果有要創建模板的特定擴展 點,建議擴展該擴展點,因為它允許客戶使用模板以及其他內容(參見圖 7)。 在本例中,只重用了 OptionTemplateSection implementation (SimpleViewTemplateSection)。我想強調的是如果創建了自定義擴展點並且 提供了模板,則它將對用戶起到幫助作用。
記得當您第一次學習 Eclipse 時必須創建一個視圖麼?視圖模板在理解工作 原理時具有極高的價值。現在,這種實惠您的用戶也將感受得到。
清單 6. plugin.xml
<extension
point="org.eclipse.pde.ui.templates">
<template
class="com.ibm.pde.simple.template.SimpleViewTemplateSection"
contributingId="org.eclipse.ui.views"
id="com.ibm.pde.simple.template"
name="Simple View"/>
</extension>
圖 7. 自定義插件向導
結束語
在完成這項艱巨的工作之後,保佑我們能夠創建項目並且讓它能夠使用簡單 的模板。創建了此項目後,我們可以輕松地查看代碼並且開始了解錯綜復雜的模 板。還可以啟動一個運行時工作區環境並查看模板的結果。
圖 8. 簡單的視圖
我們的目標是向您介紹 PDE 的模板系統,而這一目標通過一個親手實踐的示 例實現了。鼓勵您下載下面列出的示例來查看其工作原理。希望它向您證明了 PDE 的模板系統為最終用戶提供了一種強大的方法可以快速地引導創建項目,或 者可能使自定義擴展點的示例實現很顯眼。如果您覺得 PDE 模板系統缺少某些 區域,我們十分樂意收到 Bugzilla 條目 形式的反饋。我們一直在不斷地尋找 改進 PDE 的方法。
本文配套源碼