Eclipse 外掛開發 -- 深入理解選單(Menu)功能及其擴充套件點
選單是各種軟體及開發平臺會提供的必備功能,Eclipse 也不例外,提供了豐富的選單,包括主選單(Main Menu),檢視 / 編輯器選單(ViewPart/Editor Menu)和上下文選單(Context Menu)。在 Eclipse 中,幾乎所有的 Workbench Part 提供了人性化的選單,大大方便了使用者的操作。因此,如何擴充套件 Eclipse 的選單功能,並實現特定於我們自己外掛的選單,是外掛開發者必須掌握的重要技能,同時,Eclipse 提供了豐富的擴充套件點供開發人員使用。本文將首先介紹 Eclipse 中的選單,然後詳細說明如何進行擴充套件,最後以一個例項的形式引導讀者深入理解 Eclipse 的選單功能。
引言
Eclipse 具有豐富的選單功能,給開發人員提供了很好的使用者體驗。總體而言,Eclipse 選單種類包括檢視 / 編輯器選單,主選單(Main Menu),檢視 / 編輯器選單(ViewPart/EditorPart Menu)和上下文選單(Context Menu)。外掛開發人員通過靈活應用這些選單,可以給使用者提供很好的體驗。由於檢視和編輯器選單功能類似,因此本文重點講述檢視選單(檢視下拉選單及其工具欄選單),除此之外,還將講述主選單和上下文選單。
如圖 1 所示為 Project Explorer 檢視的選單,包括檢視下拉選單和工具欄選單(摺疊樹節點)。通常而言,出現在檢視工具欄的選單都會出現在檢視的下拉選單,也就是說,比較常用的檢視選單放在檢視的工具欄。
圖 1. Project Explorer 檢視的選單
如圖 2 所示為 Project Explorer 檢視中的上下文選單,只有當我們右鍵點選時才會出現。通常而言,出現頻率較高的選單項才會出現在選單中。上下文選單具有很強的靈活項,它可以隨著我們點選的物件不同,彈出的選單也會有相應的變化。
圖 2. Project Explorer 檢視中的上下文選單
如圖 3 所示為 Eclipse 的主選單,包括最上面的主選單項(不可移動)及其下面的工具欄選單(可以移動,並且 Eclipse 提供了顯示 / 不顯示這些選單的功能),Eclipse 並不建議我們為每一個外掛都新增新的主選單,這樣容易造成冗餘,而且不方便使用者操作。通常,我們可以把選單項新增到 Eclipse 已有的選單,如外掛的查詢功能可以新增一個查詢選單項到 Eclipse 的 Search 主選單上。
圖 3. Eclipse 的主選單
前面講到 Eclipse 的各種選單,那麼,如何在開發外掛或 RCP 應用程式的時候新增這些選單?本文下面的篇幅將詳細介紹如何擴充套件 Eclipse 的選單功能,使讀者深入瞭解 Eclipse 的選單功能,並能夠開發具有這些選單的應用程式。因此,必須掌握三方面的內容:選單種類,選單的擴充套件點,選單控制(顯示 / 隱藏或啟用 / 禁用選單項)。下面從概念上介紹這三方面內容,下一小節將會進行詳細介紹。
選單種類
正如前面所講到的,Eclipse 的選單包括檢視選單,主選單及上下文選單三個種類。
選單項的擴充套件點
Eclipse 提供了兩種擴充套件點供使用者新增選單項到相應的位置。這兩種擴充套件點為 org.eclipse.ui.commands(本文簡稱為 Commands 方式)和 org.eclipse.ui.actionSets(本文簡稱為 Actions 方式)。Actions 方式為介面上不同區域的表現方式提供了相應的擴充套件點,並且沒有分離其介面表現和內在實現。恰恰相反,Commands 方式通過三步有效的達到介面表現和內部實現的分離:首先,通過 org.eclipse.ui.commands 擴充套件點建立命令和類別(Category),並且可以把某些命令放在一個類別(Category)中;然後,通過 org.eclipse.ui.menus 指定命令出現在介面的哪個區域(檢視選單 / 主選單 / 上下文選單);最後通過 org.eclipse.ui.handlers 指定命令的實現。因此,Eclipse 推薦新開發的外掛使用 Commands 來建立您的介面選單。當然,由於 Actions 在現有的外掛中用得比較多,如果我們需要擴充套件或基於之前的外掛開發,也需要對其進行了解。除此之外,針對上下文選單,雖然 Commands 和 Actions 方式均可以建立上下文選單,但是 Eclipse 還提供了另外一種建立上下文選單的擴充套件點 org.eclipse.ui.popupMenus(本文簡稱為 popupMenus 方式),本文將就這三種擴充套件點做詳細的介紹。
選單控制
選單控制是一個非常常見的功能,例如,隨著選定的內容或當前視窗的不同,選單中的選單項會有相應的變化(顯示 / 隱藏或啟用 / 禁用選單項),因此,如何控制選單是外掛開發人員必須掌握的知識。Eclipse 為選單控制提供了兩種方法,一種是通過擴充套件點;另一種是通過 API 的方式編寫程式控制。
Eclipse 選單功能及其擴充套件點
至此,我們對 Eclipse 選單有了感觀的認識。由上一節我們可知,要深入理解 Eclipse 選單功能,我們需要從三個方面去掌握:選單種類,選單的擴充套件點和選單控制。下面將進行詳細講述。
選單種類
針對各種選單,Eclipse 提供了相應的擴充套件點,因此,開發人員可以通過這些擴充套件點把選單放到介面的不同區域,詳細內容請參考 2.2 小節。
選單的擴充套件點
檢視選單的擴充套件點
採用 Commands 方式建立檢視選單,需要引入 org.eclipse.ui.menus 擴充套件點;而 Actions 方式需要引入 org.eclipse.ui.actionSets.
1、檢視選單(Commands 方式):
MenuContribution locationURI = “[Scheme]:[id]?[argument-list]”
其中,Scheme 為該選單項出現的區域,menu 為檢視的下拉選單,toolbar 為檢視的工具欄選單;id 為選單區域 ID;argument-list 為該選單項出現在指定選單的位置。
例如:在 ProbelmView 的下拉選單加一個選單項,其 MenuContribution 的 locationURI 應為:menu:org.eclipse.ui.views.ProblemView?after=additions;在 ProblemView 的工具欄選單中加入一個選單項,其 locationURI 應為:toolbar:org.eclipse.ui.views.ProblemView?after=additions。
2、檢視選單(Actions 方式):
採用 Actions 方式建立選單,需要引入 org.eclipse.ui.actionSets 擴充套件點,並通過設定 action 的 menubarPath 指定下拉選單 / 選單項出現的位置;通過設定 action 的 toolbarPath 設定工具欄選單 / 選單項出現的位置。
例如,新增一個下拉選單項到 Problems 檢視中,其 menubarPath 應為:
org.eclipse.ui.views.ProblemView/additions
主選單的擴充套件點
1、主選單(Commands 方式)
通過 Commands 方式把選單項新增到主選單及其工具欄上,和檢視選單一樣,也是通過擴充套件點 org.eclipse.ui.menus 實現,需要設定其 menuContribution 的 locationURI。
例如,新增一個選單(選單可以包含若干個選單項)到主選單一欄中,其 locationURI 為:
menu:org.eclipse.ui.main.menu?after=additions
新增一個選單到工具欄之中,其 locationURI 為:
toolbar:org.eclipse.ui.main.toolbar?after=additions
當然,我們也可以把選單項新增到已經存在的選單當中,例如新增一個選單項到 Eclipse 的 Search 主選單當中,其 locationURI 為:
menu:org.eclipse.search.menu?dialogGroup
2、主選單(Actions 方式)
通過 Actions 方式把選單項新增到主選單及其工具欄上,和檢視選單一樣,也是通過擴充套件點 org.eclipse.ui.actionSets 實現,需要設定 action 的 menubarPath 和 toolbarPath 實現。
例如,新增一個選單項到 Eclipse 的 Search 主選單中,其 menubarPath 應為:
org.eclipse.search.menu/dialogGroup
注意:如果採用上述方式新增一個選單項到 Search 主選單,當我們執行時並沒有出現新增的選單項,這時候需要換一個 workspace,其原因是 Eclipse 快取了與其相關的某些資訊在 workspace 當中。
上下文選單的擴充套件點
上下文選單除了通過 Commands 和 Actions 方式新增,還可以使用擴充套件點 org.eclipse.ui.popupMenus 方式新增,下面分別進行介紹。
1、上下文選單(Commands 方式)
Commands 方式與新增檢視選單和主選單的方式一樣,通過設定其 menuContribution 的 locationURI 來實現。
例如,新增一個上下文選單到 Problems 檢視中,其 locationURI 為:
popup:org.eclipse.ui.views.ProblemView?after=additions。
如果我們想讓某個上下文選單項出現在任何區域,則可以使用下面的 locationURI:
popup:org.eclipse.ui.popup.any?after=additions
2、上下文選單(Actions 方式)
Actions 方式沒有直接提供擴充套件點新增上下文選單,但是我們可以通過程式設計的方式實現,如下程式碼清單 1 為 TreeViewer 新增上下文選單,通過 IMenuManager 的 add 方法新增 actions。
清單 1. 通過 Actions 方式程式設計實現新增上下文選單
private void hookContextMenu() { IMenuManager fMenuMgr = new MenuManager(“#PopupMenu”); fMenuMgr.setRemoveAllWhenShown(true); // 新增 Actions fMenuMgr.add(action … ) fMenuMgr.createContextMenu(treeViewer.getControl()); treeViewer.getControl().setMenu(fMenu); getSite().registerContextMenu(fMenuMgr, treeViewer); }
3、上下文選單(popupMenus 方式)
通過 popupMenus 擴充套件點實現上下文選單,需要設定 objectContribution 的 objectClass 屬性把上下文選單新增到相應的區域。
例如,如果我們想當用戶點選 Eclipse 中的資源時,彈出的上下文選單包括某個選單項,我們可以設定 objectClass 屬性為:
org.eclipse.core.resources.IResource
通過 Commands 方式建立選單項
通過 Commands 方式建立選單項,首先需要建立 Command,通過擴充套件點 org.eclipse.ui.commands,然後我們可以把這個 Command 放到任何區域,上一小節已經講到,通過 org.eclipse.ui.menus 擴充套件點確定選單建立的區域,最後通過擴充套件點 org.eclipse.ui.handlers 定義這個 command 的具體行為。
在建立 Command 時,我們可以先建立一個 Category,並把相關的一些命令放到這個 Category 中,這樣有利於管理。程式碼清單 2 建立一個 Command(“Show in Glossary Explorer”),並放到一個 Category 中,然後把該 Command 放到 BGSearchResultView 檢視的上下文選單中,最後通過擴充套件 org.eclipse.ui.handlers 定義該 Command 的實現類。
清單 2. 通過 Commands 方式新增選單項
<!-- 新增 command --> <extension point="org.eclipse.ui.commands"> <category description="Business Glossary" id="com.ibm.bg.ui.commands.category" name="%category.BusinessGlossary.name"> </category> <command categoryId="com.ibm.bg.ui.commands.category" description="Show in Glossary Explorer" id="com.ibm.bg.ui.commands.BGShowInBrowser" name="%command.ShowInGE.name"> </command> </extension> <!-- 把 Command 放到介面的對應區域 --> <extension point="org.eclipse.ui.menus"> <menuContribution locationURI= "popup:com.ibm.bg.internal.ui.search.BGSearchResultView?after=additions"> <command commandId="com.ibm.bg.ui.commands.BGShowInBrowser" style="push" tooltip="%command.ShowInGE.tooltip"> </command> </menuContribution> </extension> <!-- 定義 command 的實現類 --> <extension point="org.eclipse.ui.handlers"> <handler class="com.ibm.bg.internal.ui.handlers.BGShowInBrowser" commandId="com.ibm.bg.ui.commands.BGShowInBrowser"> </handler> </extension>
通過 Actions 方式建立選單項
正如前面講到,Actions 方式沒有分離介面的表現和內部實現,因此,所有這些均通過 action 來完成。如下程式碼清單 3 為新增一個 Search 選單項到 Eclipse 的 Search 主選單(通過 action 的 menubarPath 指定)中,其中 class 對應的值為該 Action 的實現類,該類需要實現介面 IWorkbenchWindowActionDelegate。
清單 3. 通過 Actions 方式新增選單項
<extension point="org.eclipse.ui.actionSets"> <actionSet id="com.ibm.bg.ui.workbenchActionSet" label="%category.name.0" visible="true"> <action class="com.ibm.bg.internal.ui.handlers.BGSearchHandler" definitionId="com.ibm.bg.ui.commands.BGSearch" icon="icons/search.png" id="com.ibm.bg.ui.commands.BGSearch" label="%action.searchGlossayInMainMenu.label" menubarPath="org.eclipse.search.menu/dialogGroup" style="push"> </action> </actionSet> </extension>
通過 popupMenus 方式建立選單項
popupMenus 方式建立上下文選單項也是通過 action 來實現,下面例子為新增一個選單項到使用者右擊 IGraphicalEditPart 物件時彈出的上下文選單,通過 menubarPath 指定該 Action 出現的區域,通過 class 指定該 action 的實現類,該類需要實現介面 IObjectActionDelegate。
清單 4. 通過 popupMenus 方式新增選單項
<extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="false" id="com.ibm.bg.uml.objectContributions.BGAssignToGlossary" objectClass="org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart"> <action class="com.ibm.bg.internal.uml.actions.BGAssignToGlossary" enablesFor="+" icon="icons/assign.png" id="com.ibm.bg.internal.uml.actions.BGAssignToGlossary" label="%BGAssignToGlossary.item" menubarPath="com.ibm.bg.uml.popupMenuGroup"> </action> </objectContribution> </extension>
選單控制
檢視選單的控制主要包括啟用 / 禁用,顯示 / 隱藏選單。
通過 Command 方式建立的選單,可以通過 org.eclipse.ui.commands 的 visibleWhen 屬性控制選單的隱藏和顯示,通過 org.eclipse.ui.handlers 的 activewhen 或 enabledWhen 控制選單的啟用或禁用。
通過 Actions 方式建立的選單,可以通過 action 的 enablement 屬性控制選單的啟用 / 禁用。
通過 popupMenus 方式建立的選單,可以通過 objectContribution 的 visibility 和 enablement 來設定該 objectContribution 下的 action 的顯示 / 隱藏和啟用 / 禁用,我們也可以設定 action 的 enablement 來控制該選單的啟用 / 禁用。
這裡不詳細講述 enablement,visibleWhen 和 enabledWhen 的引數及如何設定,讀者可以參考第三節的例子和本文的參考文獻。
程式設計實踐
本文將結合前兩節講到的知識,以例子的形式說明如何建立並且控制選單。首先建立一個檢視(Menu Example),然後分別通過 Commands,Actions 和 popupMenus 方式建立若干個選單,並新增相應的選單控制點。
建立 Menu Example 檢視
擴充套件 org.eclipse.views 建立“Menu Example”檢視,如下程式碼清單 5 為建立檢視的 xml 程式碼。
清單 5. 擴充套件 org.eclipse.ui.views 建立檢視
<extension point="org.eclipse.ui.views"> <category id="com.free.menu.category" name="Menu Example View"> </category> <view category="com.free.menu.category" class="com.free.menu.view.MenuExplorer" id="com.free.menu.view.MenuExplorer" name="Menu Explorer" restorable="true"> </view> </extension>
建立 Commands
採用 Command 方式建立“Menu Example”主選單(包含 AngryCommand 和 JokeCommand 兩個選單項),並且基於這兩個選單項建立了 Menu Example 檢視的下拉選單和工具欄選單,及其 TreeViewer 的上下文選單。
如下程式碼清單 6 為擴充套件 org.eclipse.ui.commands 建立 Menu Example 命令和類別,並且包含兩個命令:Joke Command 和 Angry Command。
清單 6. 擴充套件 org.eclipse.ui.commands 建立命令
<extension point="org.eclipse.ui.commands"> <category id="com.free.menu.category" name="Menu Example"> </category> <command categoryId="com.free.menu.category" id="com.free.menu.commands.jokeCommand" name="Joke Command"> </command> <command categoryId="com.free.menu.category" id="com.free.menu.commands.angryCommand" name="Angry Command"> </command> </extension>
關聯 Commands 到主選單
如下程式碼清單 7 為擴充套件 org.eclipse.ui.menus,並基於前面建立的 Comands,新增一個主選單 Menu Example,並且包含 Joke Command 和 Angry Command 選單項。
清單 7. 建立 Menu Example 主選單
<menuContribution locationURI="menu:org.eclipse.ui.main.menu?after=additions"> <menu id="com.free.menu.MenuExample" label="Menu Example"> <command commandId="com.free.menu.commands.jokeCommand" style="push"> </command> <command commandId="com.free.menu.commands.angryCommand" style="push"> </command> </menu> </menuContribution>
關聯 Commands 到檢視選單
如下程式碼清單 8 為擴充套件 org.eclipse.ui.menus,並基於 Commands 方式建立 Menu Example 檢視的下拉選單,工具欄選單和上下文選單,通過 locationURI 來設定。Joke Command 即為下拉選單也是工具欄選單,只有當我們選擇了 TreeViewer 中的節點時該選單項才是可見的,參考下面的 visibleWhen->with->iterate->or->instanceof。
清單 8. 通過 Commands 方式建立檢視選單
<extension point="org.eclipse.ui.menus"> <menuContribution locationURI="menu:com.free.menu.view.MenuExplorer?after=additions"> <command commandId="com.free.menu.commands.jokeCommand" icon="icons/searchres.gif" style="push"> <visibleWhen checkEnabled="false"> <with variable="selection"> <iterate ifEmpty="true" operator="or"> <or> <instanceof value="com.free.menu.model.Person"> </instanceof> </or> </iterate> </with> </visibleWhen> </command> </menuContribution> <menuContribution locationURI="toolbar:com.free.menu.view.MenuExplorer?after=additions"> <command commandId="com.free.menu.commands.jokeCommand" icon="icons/searchres.gif" style="push"> <visibleWhen checkEnabled="false"> <with variable="selection"> <iterate ifEmpty="true" operator="or"> <or> <instanceof value="com.free.menu.model.Person"> </instanceof> </or> </iterate> </with> </visibleWhen> </command> </menuContribution> <menuContribution locationURI="popup:com.free.menu.view.MenuExplorer?after=additions"> <command commandId="com.free.menu.commands.jokeCommand" icon="icons/searchres.gif" style="push"> </command> <command commandId="com.free.menu.commands.angryCommand" style="push"> </command> </menuContribution> </extension>
Commands 的實現類
如下程式碼清單 9 所示擴充套件 org.eclipse.ui.handlers 為 Joke Command 和 Angry Command 建立事件處理類,其中 Joke Command 通過 enabledWhen 屬性控制該選單項是否啟用,當我們同時選擇了兩個物件時 Joke Command 處於啟用狀態,否則為禁用。
清單 9. 擴充套件 org.eclipse.ui.handlers 為 Commands 建立實現類
<extension point="org.eclipse.ui.handlers"> <handler class="com.free.menu.actions.JokeCommand" commandId="com.free.menu.commands.jokeCommand"> <enabledWhen> <count value="2"> </count> </enabledWhen> </handler> <handler class="com.free.menu.actions.AngryCommand" commandId="com.free.menu.commands.angryCommand"> </handler> </extension>
建立 Action 並關聯到 Eclipse 的 Search 主選單
採用 Actions 方式在 Eclipse 的主選單 Search 中新增建立選單項 SmileAction。擴充套件 org.eclipse.ui.actionSets 在 Eclipse 的主選單 Search 中新增一個選單項 Smile Action。如下程式碼清單 10 所示建立該 action 並新增到 search 主選單,只有當我們選擇至少一個物件時(設定 enablesFor 屬性為“+”),該選單項才處於啟用狀態。
清單 10. 通過 Actions 方式建立選單項
<extension point="org.eclipse.ui.actionSets"> <actionSet id="com.free.menu.actionSet.MenuExample" label="Menu Example" visible="true"> <action class="com.free.menu.actions.SmileAction" enablesFor="+" icon="icons/searchres.gif" id="com.free.menu.actions.smileAction" label="Smile Action" menubarPath="org.eclipse.search.menu/dialogGroup" style="push"> </action> </actionSet> </extension>
pupupMenus 方式建立 Action 並關聯到 IResource 資源的上下文選單
擴充套件 org.eclipse.ui.popupMenus 建立選單“Menu Example”,該選單包含一個選單項 HelloAction。當我們在 Eclipse 任何區域右擊 org.eclipse.core.resources.IResource 資源時彈出的上下文選單中會出現“Menu Example”選單。如下程式碼清單 11 為建立該上下文選單的 xml 程式碼。
清單 11. popupMenus 方式建立上下文選單
<extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="true" id="com.free.menu.popupMenu" objectClass="org.eclipse.core.resources.IResource"> <menu label="Menu Example" path="additions" id="com.free.menu.popupSubMenu"> <separator name="additions"> </separator> </menu> <action label="Hello Action" class="com.free.menu.popup.actions.HelloAction" menubarPath="com.free.menu.popupSubMenu/additions" enablesFor="1" id="com.free.menu.newAction"> </action> </objectContribution> </extension>
pupupMenus 方式建立 Action 並關聯到 IResource 資源的上下文選單
擴充套件 org.eclipse.ui.popupMenus 建立選單項 GreetAction 和 CryAction,當我們右擊 Menu Example 檢視中的 TreeViewer 節點時彈出。如下程式碼清單 12 所示擴充套件 org.eclipse.ui.popupMenus 為 Menu Example 檢視建立 GreetAction 和 CryAction 上下文選單項。使用 visiblity 的 objectState 屬性控制選單項的可見狀態,使用該屬性要求其選擇的物件實現了 org.eclipse.ui.IActionFilter 介面,具體可參見 Person 類的實現。
清單 12. 擴充套件 org.eclipse.ui.popupMenus 建立選單
<extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="false" id="com.free.menu.views.popupMenu" objectClass="com.free.menu.model.Person"> <action class="com.free.menu.actions.GreetAction" enablesFor="+" id="com.free.menu.actions.greetAction" label="Greet Action" menubarPath="additions"> </action> <visibility> <objectState name="firstName" value="Dan"> </objectState> </visibility> </objectContribution> </extension> <extension point="org.eclipse.ui.popupMenus"> <objectContribution adaptable="false" id="com.free.menu.views.popupMenu2" objectClass="com.free.menu.model.Person"> <action class="com.free.menu.actions.CryAction" enablesFor="+" id="com.free.menu.actions.cryAction" label="Cry Action" menubarPath="additions"> <enablement> <objectState name="firstName" value="David"> </objectState> </enablement> </action> <visibility> <objectState name="lastName" value="Rubel"> </objectState> </visibility> </objectContribution> </extension>
Menu Example 檢視的程式碼實現類
如下程式碼清單 13 所示為 Menu Example 檢視的程式碼,該檢視中有一個 TreeViewer,並通過函式 hookContextMenu 把上下文選單關聯到 TreeViewer。其中函式 viewMenuAction 用於更新選單的狀態,它首先獲取檢視選單,然後呼叫 IMenuManager 的 update 方法更新對應選單項的狀態,從而達到控制選單的目的。
清單 13. Menu Example 檢視程式碼
public class MenuExplorer extends ViewPart { private TreeViewer treeViewer; private MenuManager fMenuMgr; private Menu fMenu; private static MenuExplorer fInstance = null; public MenuExplorer() { fInstance = this; } public static MenuExplorer getInstance(){ return fInstance; } public void createPartControl(Composite parent) { treeViewer = new TreeViewer (parent, SWT.MULTI); treeViewer.setLabelProvider(new PersonListLabelProvider()); treeViewer.setContentProvider(new PersonTreeContentProvider()); treeViewer.setInput(Person.example()); this.getSite().setSelectionProvider(treeViewer); hookContextMenu(); fInstance = this; } public void setViewMenuActionState(boolean state){ JokeCommand.setState(state); viewMenuAction(); } private void viewMenuAction() { IActionBars bars= getViewSite().getActionBars(); final IMenuManager menu= bars.getMenuManager(); UIOperation.asyncExecCommand(new Runnable(){ public void run() { menu.update("com.free.menu.commands.jokeAction"); } }); } private void hookContextMenu() { fMenuMgr = new MenuManager("#PopupMenu"); fMenuMgr.setRemoveAllWhenShown(true); fMenuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { } }); fMenu = fMenuMgr.createContextMenu(treeViewer.getControl()); treeViewer.getControl().setMenu(fMenu); getSite().registerContextMenu(fMenuMgr, treeViewer); } public void setFocus() { treeViewer.getTree().setFocus(); } }
Person 類的實現
如下程式碼清單 14 為 Person 類的實現,用於表示 MenuExample 檢視中 TreeViewer 的一個節點,它實現了 IActionFilter 介面,通過 testAttribute 來確定是否顯示 / 隱藏選單(其中 target 表示使用者選擇的物件,name/value 對應於 plugin.xml 檔案中 objectState 的 name/value).
清單 14. Person 類實現
public class Person implements IActionFilter { private String firstName = "John"; private String lastName = "Doe"; protected int age = 37; public Person[] children = new Person[0]; public Person parent = null; public Person(String firstName, String lastName, int age) { this.firstName = firstName; this.lastName = lastName; this.age = age; } public Person(String firstName, String lastName, int age, Person[] children) { this(firstName, lastName, age); this.children = children; for (int i = 0; i < children.length; i++) { children[i].parent = this; } } public String getFirstName() { return this.firstName; } public String getLastName() { return this.lastName; } public static Person[] example() { return new Person[] { new Person("Dan", "Rubel", 38, new Person[] { new Person("Beth", "Rubel", 8), new Person("David", "Rubel", 3) }), new Person("Eric", "Clayberg", 39, new Person[] { new Person("Lauren", "Clayberg", 6), new Person("Lee", "Clayberg", 4) }), new Person("Mike", "Taylor", 52) }; } public String toString() { return firstName + " " + lastName; } public boolean testAttribute(Object target, String name, String value) { if (target instanceof Person) { Person person = (Person) target; if (name.equals("firstName") && value.equals(person.getFirstName())) { return true; } if (name.equals("lastName") && value.equals(person.getLastName())) { return true; } } return false; } }
總結
至此為止,已經把 Eclipse 選單功能及其擴充套件點涉及到的類 / 介面 /API 進行了詳細的說明,相信讀者已經有清晰的認識了。對於前面提到 popupMenus 方式建立上下文選單,要求選擇的物件實現 IActionFilter 介面,但是,如果開發人員正在使用 gmf 進行開發,那麼我們可以不必要求選擇的物件實現 IActionFilter,我們可以通過擴充套件 org.eclipse.gmf.runtime.common.ui.services.action.actionFilterProviders 對選單項進行控制,如下程式碼清單 15 為擴充套件該 extension point 的 xml 程式碼,我們可以定義多個屬性(<Attribute> … </Attribute),其中 Attribute 的 name 和 value 對應於 visibility 的 objectState 中的 name 和 value。
清單 15. 通過 actionFilterProviders 擴充套件點實現對選單的控制
<extension point="org.eclipse.gmf.runtime.common.ui.services.action.actionFilterProviders"> <ActionFilterProvider class="com.free.menu.PopupActionFilterProvider"> <Priority name="Medium"> </Priority> <Attribute name="com.ibm.bg.uml.search.isSupportedType" value="supported"> </Attribute> </ActionFilterProvider> </extension>
如下程式碼清單 16 所示 PopupActionFilterProvider 的實現,它繼承 AbstractActionFilterProvider,只需要實現其中的 testAttribute 和 provides 方法,當 testAttribute 返回 true 時,那麼該選單項被啟用,否則禁用。其中 target 對應於我們選擇的物件,name 和 value 引數對應於 visiblity 中 objectState 的 name 和 value 的指定值 ( 與前面提到的 Person 類中的 testAttribute 方法類似 )。
清單 16. actionFilterProviders 擴充套件點實現類
public class PopupActionFilterProvider extends AbstractActionFilterProvider { public PopupActionFilterProvider() { } public boolean testAttribute(Object target, String name, String value) { } public boolean provides(IOperation operation) { return false; } }