在一個具體項目中想實現UNDO/REDO的功能, 操作的次數沒有限制, 而且數據的類型比較復雜. 如有這方面有經驗的高手, 可否談談你是如何實現的.
評論
-
# re: 有沒有在具體項目中作過UNDO/REDO的高手, 給提點建議.
Posted @ 2005-09-23 10:21
這是個很好的話題,相信很多人都考慮過,而且想過各種復雜的做法。
實際上有個最簡單的解決辦法。有幾點要先注意到的:
1、每個基本操作都是可以分解為添加/刪除動作的。
2、每個UNDO/REDO動作是由一組基本的添加/刪除動作組成的,這個基本的動作本身也是一個UNDO/REDO動作。
3、如果一個基本的UNDO動作做的工作是添加,對應的REDO動作就是刪除。
4、UNDO/REDO動作必須以一個順序來執行。
5、當前位置處于UNDO歷史中時,一個DO動作要刪除當前位置后面的所有UNDO動作。
比如在文字編輯器中,輸入一段話,構成一個“添加字符串”動作。刪除一段話,構成一個“刪除字符串”動作。它們在動作歷史中,只需要保存發生這個動作時的一些基本環境信息。
另一些復雜的動作,比如選擇一段文字,拖到另一個位置,可以分解為一個刪除+一個添加動作,并把這2個動作組成一個給用戶使用的UNDO/REDO動作。當用戶UNDO時,執行后一個添加動作的反動作即刪除動作,接著執行前一個刪除動作的反動作即添加動作。
設計UNDO/REDO功能,實際上就是把那些高級功能拆為最基本的添加/刪除動作。
以上是個人看法。可以找一些開源的編輯器程序來看它們的源碼,實際上UNDO/REDO功能大部分時候都是用在編輯器中。。。 回復 更多評論
-
# re: 有沒有在具體項目中作過UNDO/REDO的高手, 給提點建議.
Posted @ 2005-09-23 11:07
謝謝!
COMMAND模式似乎也是提供這樣的解決方案. 我在以前也考慮過, 但這種方法也是有些不足:
1. 通常COMMAND模式已經應用到接近APPLICATION/GUI層, 在這個層面的DEVELOPER通常還是稍微差些,要求去理解底層的邏輯通常是不容易的.
2. 考慮到COMMAND眾多, 在COMMAND中實現UNDO/REDO也是很麻煩的事.
還有一點是, 個人認為UNDO/REDO應該是一種架構層面的問題, 應該從架構角度找到解決問題的方法. 這樣一來, 至少在另一個項目中可以復用. 如依賴COMMAND, 沒辦法做到這一點. 回復 更多評論
-
# re: 有沒有在具體項目中作過UNDO/REDO的高手, 給提點建議.
Posted @ 2005-09-23 11:40
那些東西應該全部封裝在底層,而且你不該把這么底層的部分暴露給GUI開發人員。
比如你提供了幾個底層的函數:addChar(ch), addString(text), insertString(pos, text),moveCursor(pos)它的實現中都向Undo History中插入Action。
GUI開發人員可能要定義一個功能functionA,這個功能中要調用這幾個函數,并組成一個Undo動作。他們根本不需要知道你底層如何動作的,只需要簡單做這個過程:
document->BeginAction ("插入日期和開發人員名字");
document->addChar(...);
docuemnt->insertString(...);
document->...;
document->EndAction();
注意中間有一項失敗時,應該調用回滾。
EndAction()激發一個事件,通知GUI在UNDO列表中加入一項“插入日期和開發人員名字”。
這不是我的方案,實際上我至少看到過3個編輯器源碼這么干,好像成了一個定式了。。。呵呵 回復 更多評論
-
# re: 有沒有在具體項目中作過UNDO/REDO的高手, 給提點建議.
Posted @ 2005-09-23 12:16
謝謝, 很清楚! 我考慮試試看! 回復 更多評論
-
# re: 有沒有在具體項目中作過UNDO/REDO的高手, 給提點建議.
Posted @ 2006-04-21 10:54
我是采用C++實現的,在我得博客里面有比較詳細的介紹,可以參考。
我得博客:http://blog.csdn.net/pandaxcl/ 回復 更多評論