實現編輯器與導航器視圖雙向同步選中:
• 編輯器切換文件 → 導航器自動定位並選中對應節點
• 導航器點擊節點 → 編輯器打開/切換到對應文件
無需寫 Java 代碼,通過 navigatorContent 復用 Project Explorer 行為。但業務模型若非簡單文件樹(如 Java Package 合並顯示、JAR 內部結構),則需自定義模型層。
優勢:
• UI 操作先更新域模型,再持久化到 IResource,邏輯更清晰
• 同一資源可構建多種視角(Package Explorer vs Resource Explorer)

// 核心接口
public abstract class VirtualNode {
protected IResource resource; // 關聯底層資源
protected VirtualNode parent; // 父節點,關鍵:支撐向上回溯
public static final int PROJECT=1, FOLDER=2, FILE=3;
public abstract Image getImage();
public String getText() { return resource.getName(); }
// getter/setter
}
// 三種具體節點
public class ProjectNode extends VirtualNode { ... }
public class FolderNode extends VirtualNode { ... }
public class FileNode extends VirtualNode { ... }
public class MyCustomLabelProvider extends LabelProvider {
public Image getImage(Object element) {
return element instanceof VirtualNode ? ((VirtualNode)element).getImage() : super.getImage(element);
}
public String getText(Object element) {
return element instanceof VirtualNode ? ((VirtualNode)element).getText() : super.getText(element);
}
}
public class MyCustomContentProvider extends ... {
// 關鍵:IResource → VirtualNode 映射表,支撐 Link Helper 反向查找
private Map resources2NodesMap = new HashMap<>();
public Object[] getChildren(Object element) {
List children = new ArrayList<>();
if (element instanceof IWorkspaceRoot) {
// 根節點 → 專案節點
} else if (element instanceof VirtualNode) {
// 虛擬節點 → 子文件夾/文件節點
// 過濾 . 開頭隱藏文件
// 創建並 register 到 map
}
return children.toArray();
}
// hasChildren 避免過早註冊 N+1 級節點
private boolean register = true;
public boolean hasChildren(Object element) {
register = false;
boolean flag = super.hasChildren(element);
register = true;
return flag;
}
}
public class MyLinkHelper implements ILinkHelper {
public IStructuredSelection findSelection(IEditorInput input) {
IFile file = ResourceUtil.getFile(input);
if (file == null) return StructuredSelection.EMPTY;
VirtualNode node = MyCustomContentProvider.INSTANCE.getResources2NodesMap().get(file);
if (node == null) {
// 地圖未初始化,模擬樹展開路徑構建映射
IProject project = file.getProject();
// 1. 展開專案節點
getChildren(resources2NodesMap.get(project));
// 2. 逐層向上收集父資源入棧
Stack stack = new Stack<>();
IResource parent = file.getParent();
while (parent != project) { stack.push(parent); parent = parent.getParent(); }
// 3. 逐層出棧展開
while (!stack.isEmpty()) { getChildren(resources2NodesMap.get(stack.pop())); }
// 4. 獲取最終節點
node = resources2NodesMap.get(file);
}
return node != null ? new StructuredSelection(node) : StructuredSelection.EMPTY;
}
public void activateEditor(IWorkbenchPage page, IStructuredSelection selection) {
if (selection.getFirstElement() instanceof FileNode) {
IFile file = ((FileNode)selection.getFirstElement()).getResource();
IEditorInput input = new FileEditorInput(file);
IEditorPart editor = page.findEditor(input);
if (editor != null) page.bringToTop(editor);
}
}
}


Ctrl+Shift+R/T 打開文件後自動定位導航器Link With Editor 實現需理解 CNF 框架設計,核心在於業務模型與 IResource 的雙向映射表,配合父節點引用支撐樹路徑回溯。掌握此模式,可為任何自定義導航器添加專業級聯動體驗。