我的应用程序是混合E3 / E4,因为我想使用Eclipse Workbench的一部分,但也为我以后基于纯E4的应用程序做了一些准备工作。
在这个应用程序中,我有一个使用自定义编辑器输入的编辑器(不是基于文件的,而是基于从数据库中提取的数据;当用户保存更改时,它们将被写回数据库)。我的本地内存中数据表示由EMF / Xcore管理,编辑器使用手动设计的GUI,通过EMF编辑数据绑定,即我使用EditingDomain
(即基本{{ 1}}使用AdapterFactoryEditingDomain
)跟踪所有更改。
要将我的E4编辑器插入E3编辑器,我使用兼容性层,尤其是BasicCommandStack
。
虽然到目前为止工作正常但我还没有能够撤消/重做工作。
我的代码看起来像这样(我在Scala-IDE中使用Scala):
E3编辑器桥:
DIEditorPart
和“真实”部分:
final class CustomEditorPartE3Bridge extends DIEditorPart(classOf[CustomEditorPart])
那么,我如何提供撤销/重做以便E3的撤销/重做机制启动?我是否必须以某种方式将我的final class CustomEditorPart {
@Inject private var _ctx: IEclipseContext = _
private var _view: Option[MyCustomEditorView] = None
@Inject private var _dirty: MDirtyable = _
@Inject @Optional private var _dirtyE3: IDirtyProviderService = _
private var doPersist: () => Unit = () => {}
@PostConstruct
def init(input: IEditorInput): Unit = input match {
case i: MyCustomEditorInput => initPart(i)
case _ =>
throw new IllegalStateException("Required a %s but got a %s".
format(classOf[MyCustomEditorInput].getName, input.getClass.getName))
}
private def initPart(input: MyCustomEditorInput): Unit = {
val cc = _ctx.createChild()
// Now we need an adapter factory and a respective editing domain
// to enable Undo and Redo
val adapterFactory = new ModelAdapterFactory // generated with Xcore
val cs = new BasicCommandStack
val domain = new AdapterFactoryEditingDomain(adapterFactory, cs)
// We need the editing domain in the control for Databinding
cc.set(classOf[EditingDomain], domain)
// Now we setup the view
_view = Some(ContextInjectionFactory.make(classOf[MyCustomEditorView], cc))
// And we handle dirtying of our part
object csl extends CommandStackListener {
def commandStackChanged(eo: EventObject): Unit = {
val dirty = cs.isSaveNeeded()
if (_dirtyE3 == null) {
_dirty.setDirty(dirty)
} else {
Display.getDefault.asyncExec(() => _dirtyE3.setDirtyState(dirty))
}
}
}
cs.addCommandStackListener(csl)
// Finally, we setup our saving routine.
doPersist = () => { /* not relevant here */ }
}
@Focus
def setFocus(): Unit = _view.foreach(_.setFocus)
@PersistState
def persistState(): Unit = {}
@Persist
def commit(): Unit = doPersist()
}
传播回我的E3桥并设置一些动作栏贡献者或者我可以为我注入一些设置撤消/重做的东西吗?
答案 0 :(得分:0)
我将此作为答案发布,因此我可以将其标记为解决方案。
在摆弄并搜索EHandlerService
使用的各种示例后,我想出了这个:
当我使用DIEditorPart
时,我可以注入IWorkbenchPart
。如果稍后在基于纯E4的应用程序中使用该部件时可能不存在,那么我将其注入@Optional
并稍后测试null
。
所以除了E4方式,我还有以下内容:
@Inject @Optional private var _workbenchPart: IWorkbenchPart = _
// In my method
val cc: IEclipseContext = ...
val domain: EditingDomain = ...
cc.set(classOf[EditingDomain], domain)
if (_workbenchPart != null) {
val undoAction = ContextInjectionFactory.make(classOf[UndoAction], cc)
val redoAction = ContextInjectionFactory.make(classOf[RedoAction], cc)
val site = _workbenchPart.getSite.asInstanceOf[{
def getActionBars(): org.eclipse.ui.IActionBars
}]
val targetActionBars = site.getActionBars
if (targetActionBars != null) {
targetActionBars.setGlobalActionHandler(ActionFactory.UNDO.getId, undoAction)
targetActionBars.setGlobalActionHandler(ActionFactory.REDO.getId, redoAction)
}
}
我的UndoAction
和RedoAction
如下所示:
abstract class UndoRedoAction(canExecute: CommandStack => Boolean,
execute: CommandStack => Unit) extends Action {
@Inject private var _domain: EditingDomain = _
@PostConstruct
private def init(): Unit = {
setEnabled(canExecute(_domain.getCommandStack))
object csl extends CommandStackListener {
def commandStackChanged(eo: EventObject): Unit = setEnabled(canExecute(_domain.getCommandStack))
}
_domain.getCommandStack.addCommandStackListener(csl)
}
override final def run(): Unit = execute(_domain.getCommandStack)
}
final class UndoAction extends UndoRedoAction(_.canUndo, _.undo)
final class RedoAction extends UndoRedoAction(_.canRedo, _.redo)
这有点像黑客,但它确实有效。