Editor中嵌入Editor,最大的问题就是Action的问题。
我们知道,通过每个Editor都有自己对应的Action组,我们通过提供Editor的Contributor来提供该Editor对应的Actions。但是这在内嵌Editor中就会有问题了。例如,我有一个GEF的Editor:ZillionaireEditor。这个Editor嵌套在另一个Editor中:ZillionaireComboEditor。
假如在我的ZillionaireComboEditor中,需要支持ZillionaireEditor的redo、undo和delete动作。
那么首先,我们在我们的ZillionaireComboEditor对应的Contributor里追加用于支持GEF command的这三个动作:
@Override
protected void buildActions() {
addRetargetAction(new UndoRetargetAction());
addRetargetAction(new RedoRetargetAction());
addRetargetAction(new DeleteRetargetAction());
}
@Override
public void contributeToToolBar(IToolBarManager toolBarManager) {
toolBarManager.add(getAction(ActionFactory.UNDO.getId()));
toolBarManager.add(getAction(ActionFactory.REDO.getId()));
toolBarManager.add(getAction(ActionFactory.DELETE.getId()));
}
这个很简单,不过只是这样,也会有问题,看看error view就知道,会在ActionBarContributor.setActiveEditor(ActionBarContributor.java:142)有一个空指针的异常。
简单的修正方法如下:
@Override
public void setActiveEditor(IEditorPart editor) {
if (editor instanceof ZillionaireComboEditor) {
super.setActiveEditor(((ZillionaireComboEditor) editor)
.getZillionaireEditor());
} else {
super.setActiveEditor(editor);
}
}
重写它的setActiveEditor()方法,代理到ZillionaireEditor上去。
这时redo和undo的支持就实现了。不过delete操作会有问题:没反应。
实际中,我们选择任一editPart,delete操作都应该被更新,以判断是否可以招待该操作。
所以显示,会有一个选择监听来做这件事。看看GraphicalEditor里的selectionChange()方法:
/**
* @see org.eclipse.ui.ISelectionListener#selectionChanged(IWorkbenchPart, ISelection)
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
// If not the active editor, ignore selection changed.
if (this.equals(getSite().getPage().getActiveEditor()))
updateActions(selectionActions);
}
因为我们用外层的editor包装了内部的editor,所以此时判断条件:this.equals(getSite().getPage().getActiveEditor()返回值为false,因此updateActions()方法无法被调用。
显然,我们不应该想着通过修改ZillionaireEditor来实现,因为通常被包装的Editor都不能被你所修改。
所以看来,我们只有通过其他的方法来修改了。
例如,我们在ZillionaireComboEditor中也增加一个selectionListener:
getSite().getPage().addSelectionListener(this);
然后实现selectionChange()方法:
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
if (this.equals(getSite().getPage().getActiveEditor())) {
ZillionaireEditorContributor actionBarContributor = (ZillionaireEditorContributor) getEditorSite()
.getActionBarContributor();
DeleteRetargetAction action = (DeleteRetargetAction) actionBarContributor
.getAction(ActionFactory.DELETE.getId());
if (action.getActionHandler() instanceof UpdateAction)
((UpdateAction) action.getActionHandler()).update();
}
}
然后delete操作就可用了。
后记:
这只是我自己的一个理解,不知是否有其他好的方法去解决这个问题!