如何擴展 JDT 的特定元素的用戶界面(象 Outline 視圖中的成員)?擴展視圖還是它們的底層模型? 簡單的
Hello
World
示例顯示了添加菜單選項只需要在插件清單文件中添加幾行 XML()以及一個處理實際操作的類(com
ibm
lab
helloworld
SampleAction)
向視圖的下拉菜單
公共編輯器的工具欄以及彈出菜單添加操作基本上很簡單
所提供的彈出菜單歸結為兩類
一類只與視圖相關而與所選的對象無關(也就是
對視圖的
空白處
單擊鼠標右鍵通常會顯示的
缺省
彈出菜單)
另一類則更常見
它們與應用於所選對象的選項相關
在我們的例子中
我們希望目標只是具體選擇的對象
所以通過在插件清單文件中定義一個擴展
我們將提供的操作對象提供給這些對象的彈出菜單(對下面幾個標識符進行了縮寫
以獲得更佳的格式
用
…
表示)
如清單
所示
清單
修飾符操作
<extension point=
org
eclipse
ui
popupMenus
>
<objectContribution
objectClass=
re
IMember
id=
imember
>
<menu
label=
Soln: Modifiers
path=
group
reorganize
id=
imember
modifiers
>
<separator name=
group
/>
<separator name=
group
/>
</menu>
<action
label=
Private
menubarPath=
imember
modifiers/group
class=
jdt
excerpt
MakeIMemberPrivateAction
id=
imember
makeprivate
>
</action>
<action
label=
Protected
menubarPath=
imember
modifiers/group
class=
jdt
excerpt
MakeIMemberProtectedAction
id=
imember
makeprotected
>
</action>
all menu choices not shown
</objectContribution>
</extension>
擴展點命名為 org
eclipse
ui
popupMenus
顧名思義
它定義了向出現在工作台中的彈出菜單提供的對象
這個特殊示例只提供給明確選擇的對象
即實現 IMember 接口的對象(請回憶一下 Java 語言規范中的定義
成員包含方法和字段)
我們的研究沒有白費
我們得到了當前問題的答案
我們差不多准備好回答下一個問題了
在這樣做之前
此時請注意
我們找到的用於簡單
Hello
World
操作示例的模式將對所提供的其它菜單操作進行重復
即
將把選擇更改告知 class 屬性中指定的類(通過其 selectionChanged 方法)
並還將告知它用戶何時選擇菜單選項(通過其 run 方法)
我們
旅行
的用戶界面部分快要結束了
更困難的部分
也是影響我們所期望更改的部分還在前面
正如下一個問題所說的那樣
在繼續之前只要做一兩次觀察
Package Explorer 中顯示的元素和其它視圖(如 Outline 視圖)中顯示的相同元素之間有什麼關系?我們的擴展是否需要知道它們之間的任何區別?
您可能已經注意到
當您在 Outline 視圖和 Hierarchy 視圖中選擇了一個方法時
所選對象的類並非總是相同的
例如
如果您在 Package Explorer 中展開一個庫(JAR 文件)的內容
隨後選擇了一個類(或方法)
那麼它也不會是 Java 編輯器的 Outline 視圖中同一選擇的那個類
到底怎麼回事?
這裡
我們正在觀察 JDT 的 Java 模型中
可編輯的
部分和始終為只讀的部分之間的差別
這兩部分 Java 模型都實現了公共接口(象 IMember)
但是它們擁有用來理解底層限制的實現類是不同的
另一個示例是
有一個表示 Java 編譯單元的實現類
它派生自 Package Explorer 所顯示的 JAR 文件的
class 文件
還有另一個類表示直接派生自
java 文件的編譯單元
後一個實現將允許進行一些前者所不允許的修改
而它們 API 的共享部分是由接口 ICompilationUnit 表示的
您以前在編輯 Java 源代碼時
一定會觀察到
在您輸入方法特征符時 Outline 視圖進行了更新(如果您沒有注意到
那就試一下!)
這個示例說明了 JDT 如何在不同的區域暫放其
未提交的更改
這與處理那些已保存
編譯和集成到 Java 模型中的更改不同
有些視圖(象 Java 編輯器的 Outline 視圖)知道未提交的更改和已提交的更改
而其它象 Navigator 這樣的視圖只關心已保存到文件系統的已提交更改
隨後
我們所提供的用來修改 Java 成員的操作必須(至少在某種程度上)知道在什麼上下文中調用它
即
它必須識別出某些所選成員是可修改的(那些位於 Java 編輯器的 Outline 視圖中的成員)
而另一些成員是不可以修改的(存儲在 JAR 文件中以及顯示在 Package Explorer 中的
class 文件中的成員)
記住這一點
讓我們繼續下一個問題
如何通過編程更改 JDT 模型? 如果您在前面的
旅行
中稍作了研究
那麼可能已經注意到 IMember
IJavaElement 以及我們的操作所看到的由所選的與 Java 相關的項實現的作為大部分接口的那部分都沒有 setXXX 方法
那麼如何修改這些接口呢?
您將發現這出奇地簡單
不過可能在直覺上不那麼明顯
JDT 的 Java 模型在大多數實踐情況下都是
只讀
的
通過與 Java 編譯器的集成協作
給定元素的底層 Java 源代碼進行的更改就與 Java 模型的其余部分的更改同步了
實際上
您要做的就是更新 Java 源代碼
而對模型所作的其余必要更改就傳送給任何依賴它們的元素中
例如
每當 Java 源代碼/Java 模型發生更改時
JDT 的索引會自動更新
所以仍舊可以快速執行搜索
重新編譯從屬類(按照項目特性中指定的 Java 構建路徑所指示的)
等等
可以大松一口氣了!以下就是 Java 模型是插件集成之關鍵的原因所在
Java 模型提供了整個 Java 環境的常見的內存中共享的模型
它的范圍從一個項目
一直到其所有被引用的庫
所有這些都不要您費心去操作文件系統中的
java 文件
class 文件以及
jar 文件
您可以將精力集中於高級模型
而讓 JDT 處理這其中的許多雜亂細節
還不能確信它很容易?清單
包含了這個解決方案的核心代碼的一小部分
它是從提供操作的 run 方法上抽取出的
並出於可讀性考慮
稍作了簡化
清單
selectionChanged 方法
小型解決方案
public void selectionChanged(IAction action
ISelection selection) {
IMember member = (IMember)
((IStructuredSelection) selection)
getFirstElement();
ICompilationUnit cu = member
getCompilationUnit();
if (cu
isWorkingCopy()) {
IBuffer buffer = cu
getBuffer();
buffer
replace(
);
cu
reconcile();
}
}
似乎有點虎頭蛇尾
不是嗎?對您提供的操作提供了選中的成員
向它請求其父容器(Java
class 或
java 文件的模型
用 JDT 的說法
全都稱為編譯單元)
因為其父容器管理底層源代碼
驗證該成員是否屬於
未提交的
Java 模型(換句話說
它目前在編輯器中是打開的)
然後修改作為緩沖器返回的源代碼
IBuffer 接口類似於 StringBuffer
其原理不同之處在於
更改與編譯單元相關的緩沖區更新了 Java 模型的對應元素
對 reconcile 的最終調用告知 JDT 去通知其它相關各方(象 Package Explorer 視圖)
您的模型更新已准備好作為公共消費品
您一定注意到上述代碼中的省略號
在那裡
您必須分析源代碼本身以進行修改
同樣
JDT 會提供幫助
正如我們將在下一個問題中看到的
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28006.html