在GEF框架中,通常会用到命令执行、撤销和重复的操作,在Eclipse中,也大量地采用Command、CommandManager和ICommandListener等机制来控制命令的执行及监听。在此将简要介绍GEF命令堆栈(CommandStack)的运行方式,有兴趣的读者可以跟踪Eclipse源代码,查找其他框架命令的执行和撤销。
命令堆栈(CommandStack)
GEF框架会维护CommandStack,通过CommandStack来执行、撤销和重复命令的操作。CommandStack中有两个堆栈(Stack)类型的数据——undoable和redoable:通过undoable,CommandStack知道有哪些命令可以撤销;通过redoable,CommandStack知道有哪些命令可能被重复。
当用户执行撤销操作时(例如按快捷键【Ctrl+Z】),GEF框架会调用CommandStack的undo方法,执行撤销的操作。当用户执行重复的操作时(例如按快捷键【Ctrl+Y】),GEF框架会调用CommandStack的redo方法,执行重复的操作。undo和redo方法的代码片断如以下代码如示。
public void undo() {
Command command = (Command)undoable.pop();
notifyListeners(command, PRE_UNDO);
try {
command.undo();
redoable.push(command);
notifyListeners();
} finally {
notifyListeners(command, POST_UNDO);
}
}
public void redo() {
if (!canRedo())
return;
Command command = (Command)redoable.pop();
notifyListeners(command, PRE_REDO);
try {
command.redo();
undoable.push(command);
notifyListeners();
} finally {
notifyListeners(command, POST_REDO);
}
}
undo和redo方法会从相应堆栈的顶部取出命令,执行命令的undo和redo操作,然后把取出的命令放入另外一个堆栈中。通过这种机制,GEF框架能够重复和撤销用户创建的命令,从而完成重复和撤销的操作。
CommandStack不但完成重复和撤销命令的操作,还会协助完成命令的执行,当GEF框架要执行命令时,会调用CommandStack的execute方法执行相关命令,如以下代码片段所示。
public void execute(Command command) {
if (command == null || !command.canExecute())
return;
flushRedo();
notifyListeners(command, PRE_EXECUTE);
try {
command.execute();
if (getUndoLimit() > 0) {
while (undoable.size() >= getUndoLimit()) {
((Command)undoable.remove(0)).dispose();
if (saveLocation > -1)
saveLocation--;
}
}
if (saveLocation > undoable.size())
saveLocation = -1;
undoable.push(command);
notifyListeners();
} finally {
notifyListeners(command, POST_EXECUTE);
}
}
CommandStack会调用command的execute方法执行命令,然后把command放入撤销命令的堆栈中。
另外,读者可以看到,在execute、undo和redo方法中都会调用notifyListeners方法,CommandStack通过notifyListeners方法通知所有注册的监听器,命令堆栈已经发生了改变。
监听器
在GEF编辑器中,用户可以通过“getEditDomain().getCommandStack()”代码获得编辑器的命令堆栈,在CommandStack中可以通过addCommandStackListener方法添加命令堆栈的监听器,监听器是CommandStackListener类型的对象。CommandStackListener接口定义如例程1所示。
例程1 CommandStackListener.java
package org.eclipse.gef.commands;
import java.util.EventObject;
public interface CommandStackListener {
void commandStackChanged(EventObject event);
}
CommandStackListener接口中声明了一个方法commandStackChanged,当命令堆栈发生改变时,commandStackChanged方法将会执行,如以下代码片段所示。
public void commandStackChanged(EventObject event)
{
updateActions(stackActionIDs);
setDirty(getCommandStack().isDirty());
}
protected void setDirty(boolean dirty)
{
if (isDirty != dirty)
{
isDirty = dirty;
//通知Eclipse,当前编辑器已经被修改
firePropertyChange(IEditorPart.PROP_DIRTY);
}
}
如以上代码所示,当命令堆栈改变时,编辑器将更新相应的Action,另外通过fireProperty Change方法通知编辑器,当前编辑的内容已经被修改。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/13081368/viewspace-407098/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/13081368/viewspace-407098/