承接基礎篇,本文深入剖析 Common Navigator Framework (CNF) 的模型架構:從傳統 Tree/TreeNode 到 JFace ITreeContentProvider,再到 CNF 代理模式實現的多擴展點動態合成模型。
| 階段 | 模型介面 | 特點 |
|---|---|---|
| SWT 原生 | TreeItem 直接掛載子節點 | 模型與 UI 強耦合,難測試、難擴展 |
| Swing | TreeNode (含 userObject 持有資料) | 模型獨立,可作控制類也可作資料實體,靈活 |
| JFace | ITreeContentProvider (由 TreeViewer 驅動) | 純控制介面,資料存在 TreeItem.getData(),關注點分離 |
關鍵方法:getParent(Object element) 常被忽略直接回 null,但 CNF 的 LinkWithEditor (編輯器聯動定位) 依賴此方法尋找父節點路徑,必須正確實作。
CNF 自身不提供模型能力,而是透過 org.eclipse.ui.navigator.navigatorContent 擴展點,動態組合多個 ITreeContentProvider 實例:
triggerPoints/possibleChildren 運算式,篩選出能處理該節點的 Provider 集合。getChildren(Object parent),收集子節點至 Set 去重。TreeViewer 顯示。核心代理類:NavigatorContentServiceContentProvider 實作 ITreeContentProvider,封裝上述合成邏輯。
<extension point="org.eclipse.ui.navigator.navigatorContent">
<navigatorContent
id="com.example.myModel"
name="My Model"
contentProvider="com.example.MyContentProvider"
labelProvider="com.example.MyLabelProvider"
priority="normal">
<triggerPoints>
<instanceof value="org.eclipse.core.resources.IResource"/>
</triggerPoints>
<possibleChildren>
<instanceof value="org.eclipse.core.resources.IContainer"/>
</possibleChildren>
</navigatorContent>
</extension>
triggerPoints:何種節點觸發此 Provider (支援 instanceof, adapt, or, and 運算式)。possibleChildren:此 Provider 可能產生的子節點型別,供父節點查詢時優化。priority:高優先級 Provider 先產生子節點,影響顯示順序。這兩個介面將「模型物件」與「顯示屬性 (圖示、文字、動作)」綁定,違反純粹 MVC 分層,但大幅降低擴展門檻:模型類別直接實作介面即可獲得標籤、圖示、右鍵選單,無需額外 LabelProvider/ActionProvider 類別。設計時須在「純粹度」與「開發效率」間取得平衡。
getElements(Object input):回傳根層節點 (通常為工作區專案或自定義根模型)。getChildren(Object parent):回傳子節點陣列,null 或空陣列表示葉節點。getParent(Object child):回傳父節點,**必須正確實作**以支援 LinkWithEditor。hasChildren(Object element):快速判斷是否有子節點,避免呼叫 getChildren 開銷。ILabelProvider 提供文字/圖示,或讓模型實作 IWorkbenchAdapter。plugin.xml 註冊 navigatorContent 擴展點,綁定 Provider/LabelProvider/ActionProvider。-debug 參數,在 .options 開啟 org.eclipse.ui.navigator/debug=true,主控台輸出擴展點匹配、Provider 呼叫詳情。Plugin Spy (Alt+Shift+F1) 檢視 Navigator 當前使用的 Provider/LabelProvider。掌握 CNF 代理模型機制,即可輕鬆構建支援虛擬節點、多模型混合、動態擴展的企業級資源管理器。