如果 Eclipse 中的默認插件模板能夠滿足用戶的需要,它們會非常有幫助。但是,如果需求超出了默認模板的範圍,就需要定製模板。本文討論如何定製 Eclipse 中的插件項目模板,調整模板中的多區段實現和控制,通過定製 UI 組件提高易用性,在 UI 端添加輸入檢驗功能,解釋如何自動地組織插件項目的目錄結構。
如果您曾經在 Eclipse 中創建過插件項目,那麼應該熟悉現有的插件項目模板,這些模板可以為新項目提供方便的起點。現有的插件模板可以節省大量時間,但是它們並不是萬能的。
使用插件模板的一個難題是找到滿足用戶需求的模板。但是,模板只提供數量有限的功能,而用戶的需求各不相同,創建模板的開發人員幾乎不可能事先預測出所有需求。在這種情況下,定製模板是一種簡便的方法,這可以為用戶提供所需的插件,又能夠避免從頭編寫插件。
在本文中,學習:
先決條件
本文是為熟悉 Eclipse 並對構建插件感興趣的 Java™ 開發人員撰寫的。本文假設讀者基本了解插件和基於 Eclipse 的開發工具。為了構建插件示例,您的計算機上需要安裝 Eclipse(V3.4 或更高版本)和 Java Runtime Environment (JRE)。
這裡的內容基於 developerWorks 文章 “使用 Eclipse 插件開發環境構建模板”。如果您沒有使用過插件模板,建議您先閱讀這篇文章,它介紹了如何創建模板。因為這篇文章是入門級的,它介紹的模板缺少本文討論的高級特性,包括:
這些擴展特性可以提高插件模板的可伸縮性、易用性和效率。在下面幾節中,我們要提供一個使用這些特性的模板示例。
示例研究:深入討論插件模板
假設我們需要一組插件項目。它們用來構造各種 Eclipse 透視圖,比如 Java 和 Web 透視圖。一個項目用於一個透視圖的開發。每個透視圖可以有幾個視圖。每個視圖有相關的資源,比如圖像和自動生成的 Java 源代碼文件,需要把這些資源複製到項目中。透視圖中的視圖數量和每個視圖的名稱由各個透視圖決定。
定製插件模板是生成這些目標項目的好方法。
創建一個簡單的模板
首先,創建一個新的插件項目(File > New > Project > Plug-in Project)。一定要選擇 This plug-in will make contribution to the UI 複選框。這是因為此示例中的目標項目都用於透視圖開發,都要使用 UI。創建新項目之後,還應該在 plugin.xml 中添加一個擴展 org.eclipse.pde.ui.plugin.Content 的模板嚮導擴展。
新特性 A:多區段實現和控制
仔細研究此示例的需求,就會發現在定製模板方面的一個問題。因為每個透視圖的視圖數量是可變的,所以在視圖數量確定之前,不可能生成相關資源並複製到目標項目中。
為了解決此問題,我們來考慮兩個解決方案。一種常用的方法是為每個透視圖類別創建一個模板,一個透視圖類別中的所有透視圖包含相同數量的視圖。另一種方法更高效更高級。只為所有透視圖類別創建一個模板。通過區段控制管理視圖和透視圖之間的鏈接。
添加用於透視圖和視圖區段的擴展
在此示例中,把所有資源分為兩個部分。使用透視圖區段管理透視圖資源,使用視圖區段管理視圖資源。如果用戶需要沒有視圖的透視圖,就不會把視圖資源複製到目標項目中。同樣,如果用戶需要包含 9 個視圖的透視圖,那麼在透視圖中註冊 9 個視圖,重複生成視圖資源並把資源複製到目標項目中。
為了生成這兩個區段,需要在 Manifest Editor 的 Extensions 選項卡中添加擴展。
區段實現
圖 3 給出模板項目的結構。在此示例中,創建 5 個新文件(SampleWizard.java、PerspectiveSection.java、ViewSection.java、$perspectiveClassName$.java 和 $viewClassName$.java)。它們構成項目的主要部分。
PerspectiveSection 和 ViewSection 是 OptionTemplateSection 的子類,這個類代表模板嚮導的一個區段。它們有三個主要功能:創建模板的 UI、保存從 UI 輸入的變數和更新模板模型。表 1 解釋區段類的各個方法。
方法名 | 功能說明 |
---|---|
initializeFields | 使用輸入參數初始化嚮導頁面上的選項。一些選項可能取決於用戶在前面的嚮導步驟中做出的選擇。 |
addPages | 把與模板相關的頁面添加到嚮導中。 |
getStringOption | 獲取選項名。 |
getSectionId | 返回區段 ID。 |
updateModel | 把必需的條目添加到插件模型中。 |
$perspectiveClassName$.java 和 $viewClassName$.java 是模板文件,它們會自動轉換為目標項目的 Java 源代碼文件。此示例中的模板文件非常簡單。我們僅僅創建所有視圖的列表,然後把這些視圖添加到透視圖中。
接下來,在嚮導行為中添加區段控制。SampleWizard 類是 NewPluginTemplateWizard 類的子類,這個類作為插件的嚮導模板。可以通過 SampleWizard 類把指定的區段分配給目標插件項目。performFinish 方法是從超類繼承的。可以使用它在嚮導中執行特殊的最終處理,包括循環處理模板區段並依次執行它們,從而為目標項目生成文件。清單 1 顯示如何在嚮導中註冊區段和 performFinish 方法中的主要操作。
//register all related sections in wizard public ITemplateSection[] createTemplateSections() { return new ITemplateSection[] { new PerspectiveSection(), new ViewSection() }; } public boolean performFinish(final IProject project, IPluginModelBase model, IProgressMonitor monitor) { ... ITemplateSection[] sections = super.getTemplateSections(); //monitor finish action in this wizard monitor.beginTask("perform finish", sections.length); ... //get sections for (int i = 0; i <sections.length; i++) { if (sections[i].getClass().equals(PerspectiveSection.class)) { perspectiveSection = (PerspectiveSection) sections[i]; } else if (sections[i].getClass().equals(ViewSection.class)) { viewSection = (ViewSection) sections[i]; } } ... //set variables to sections and manage sections ... viewSection.setViewClassName(values[j]); viewSection.setSourcePath(sourceFolderName); viewSection.execute(project, model, new SubProgressMonitor(monitor, 1)); perspectiveSection.setSourcePath(sourceFolderName); perspectiveSection.setViewNames(viewNames); perspectiveSection.execute(project, model, new SubProgressMonitor(monitor, 1)); } |
新特性 B:UI 組件定製
正如前面提到的,透視圖可以包含用戶所需的任意數量的視圖,用戶可以設置每個視圖的名稱。為了收集一個透視圖中的所有視圖,我們設計了下面的輸入面板。它有一個 View Class Name 框和一個 View List 框。用戶可以輸入視圖類名,然後通過單擊 Add 把它添加到視圖列表中。用戶還可以使?? Remove 按鈕刪除視圖。
為了創建這個面板,在模板項目中添加 ViewOption,它擴展 TemplateOption(見圖 3)。我們使用它設置 UI 組件並存儲用戶的輸入。清單 2 演示如何用一個視圖列表和兩個按鈕定製 UI 組件。
//add UI components in this panel public void createControl(Composite parent, int span) { ... //create View List listLabel = new Label(parent, SWT.LEFT); listLabel.setText("View List:"); listViewerField = new ListViewer(parent); listField = (List) listViewerField.getControl(); GridData listGridData = new GridData(GridData.FILL_HORIZONTAL); listGridData.heightHint = 100; listField.setLayoutData(listGridData); ... //create add button addButton = new Button(parent, SWT.PUSH); addButton.setText("Add"); ... addButton.setLayoutData(addBtnData); addButton.addSelectionListener(...); //create remove button removeButton = new Button(parent, SWT.PUSH); ... removeButton.addSelectionListener(...); } |
新特性 C:輸入檢驗功能
輸入檢驗功能是指在使用所有用戶輸入之前對它們進行檢驗的過程。輸入檢驗功能對於應用程序的安全性是極其重要的。在我們的示例中,定義一條檢驗規則:對於一個透視圖中的所有視圖,視圖類名必須是惟一的。如果違反此規則,就會在面板頂部顯示一條錯誤消息。
可以通過調用相應區段類中的 validateOptions 方法實現輸入檢驗功能。這個方法是從超類繼承的,可以通過覆蓋它實現自己的檢驗功能。清單 3 給出此示例中的 validateOptions 方法。
public void validateOptions(TemplateOption source) { this.getPage(0).setErrorMessage(null); ViewOption viewOption = (ViewOption) source; Text textField = viewOption.getTextField(); List listField = viewOption.getListField(); String[] items = listField.getItems(); if (items != null && items.length > 0) { //validation rule check for (int i = 0; i < items.length; i++) { if (items[i].equals(textField.getText())) { this.getPage(0).setErrorMessage("Class name '" + textField.getText() + "' already exists in View List."); break; } } } } |
新特性 D:自動地組織插件項目的目錄結構
我們的目標之一是讓模板自動地組織目標插件項目的目錄結構。我們通過三個步驟實現此目標:
實現
<?xml version="1.0"?> <project name="template project" default="clean" basedir="."> <property name="package" value=".\$sourcePath$\$packagePath___FCKpd___3quot;></property> <target name="create"> <mkdir dir="$dollarMark${package}"/> </target> <target name="move" depends="create"> <move todir="$dollarMark${package}"> <fileset dir="."> <include name="*.java"/> </fileset> </move> </target> <target name="clean" depends="move"> <delete dir="."> <include name="CreatePackage.xml"/> </delete> </target> </project> |
public boolean performFinish(final IProject project, IPluginModelBase model, IProgressMonitor monitor) { ... //get workspace final IWorkspace workspace = ResourcesPlugin.getWorkspace(); //get Ant file String antFilePath = "CreatePackage.xml"; final IFile file = project.getFile(antFilePath); //add Listener to monitor resource changing IResourceChangeListener listener = new IResourceChangeListener() { public void resourceChanged(IResourceChangeEvent event) { try { if (event.getType() == IResourceChangeEvent.POST_CHANGE) { IResourceDelta rootDelta = event.getDelta(); IPath filePath = file.getFullPath(); IResourceDelta targetDelta = rootDelta.findMember(filePath); if (targetDelta != null) { URI uri = file.getLocationURI(); File antFile = new File(uri); //run Ant script Project project = new Project(); project.fireBuildStarted(); project.init(); ProjectHelper helper = ProjectHelper.getProjectHelper(); helper.parse(project, antFile); project.executeTarget(project.getDefaultTarget()); project.fireBuildFinished(null); workspace.removeResourceChangeListener(this); } } } catch (Exception e) { e.printStackTrace(); } } }; workspace.addResourceChangeListener(listener); ... } |
使用模板
創建了新的模板項目之後,需要刷新此項目。右鍵單擊此項目並選擇 Refresh 菜單項。這是因為我們的 Ant 腳本是在生成項目之後執行的。我們需要在 Eclipse IDE 中手工刷新此項目。圖 6 是通過 “示例研究:深入討論插件模板” 中討論的模板示例生成的插件項目。
需要把這個新項目導出到 [eclipse_home]\plugins 目錄,然後用 -clean 參數重新啟動 Eclipse。在 Eclipse 啟動之後,檢查我們的透視圖是否已經添加到透視圖列表中(見圖 7)。選擇 myplugin perspective,然後單擊 OK。這個透視圖就會打開。
結束語
讀完本文之後,您應該對 Eclipse 插件模板有了更深入的認識。您學習了如何創建定製的輸入組件、如何控制模板文件的生成以及如何用一個模板生成具有不同目錄結構的插件項目。通過使用這些模板特性,可以更輕鬆地創建插件項目。(責任編輯:A6)
[火星人 ] 創建自己的 Eclipse 插件模板已經有830次圍觀