【原創】命令堆疊(二十七)
在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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 【原創】mysql 錯誤緩衝堆疊薦MySql
- JS 堆疊JS
- java堆疊Java
- 堆疊圖
- 平衡堆疊
- 圖的深度優先遍歷[非堆疊、堆疊實現]
- 記憶體堆疊記憶體
- 堆疊的工作原理
- C#堆疊(Stack)C#
- thinkphp console 命令列列印錯誤呼叫堆疊PHP命令列
- C#中堆和堆疊的區別C#
- [golang]如何看懂呼叫堆疊Golang
- 華為裝置堆疊原理
- Thrift的網路堆疊
- C++堆疊詳解C++
- 泛型鏈式堆疊泛型
- 第六講 堆疊操作
- 益智補劑:Stamets堆疊
- 圖的深度優先遍歷(堆疊實現和非堆疊實現)
- junkman 遠端堆疊監控
- 什麼是網路堆疊?
- Java 堆疊記憶體分配Java記憶體
- iOS crash 日誌堆疊解析iOS
- (js佇列,堆疊) (FIFO,LIFO)JS佇列
- z-index堆疊規則Index
- StackOverflowError堆疊溢位錯誤Error
- JS 資料型別和堆疊JS資料型別
- CSS之定位和堆疊屬性CSS
- SQL隱碼攻擊-堆疊注入SQL
- Java堆疊的區別有哪些Java
- QT分局管理:堆疊窗體(三)QT
- 如何:強化TCP/IP堆疊安全TCP
- android I/DEBUG堆疊資訊Android
- echarts 堆疊面積階梯圖Echarts
- 虛擬地址空間,堆疊,堆,資料段,程式碼段
- AIX的topas命令詳解(原創)AI
- C中關於堆疊的總結
- information_schema.innodb_trx 查詢堆疊ORM