SQLite中如何用触发器执行取消和重做逻辑(2) 作者:tamsyn 来源:www.sqlite.com.cn 下面的demonstration代码包含一个status_refresh程序,它激活Undo and Redo按钮, 根据没做的和要重做的事来选菜单。你需要重新定义这个程序,用来涉及特定的Undo和Redo按钮,为你的应用线则进入菜单。这里所提供的执行只是一个例子。
demonstration代码假定SQLite数据库是用一个名为"db"的句柄打开的。对于一个内置内存的数据库来说,合适的指令应如下:
sqlite3 db :memory:
这里是demonstration代码:
--------------------------------------------------------------------------------
# 每件事都在一个私有的有名称的空间里进行 namespace eval ::undo {
# proc: ::undo::activate TABLE ... # title: Start up the undo/redo system # # 参数应是在一个或多个数据库表格(在数据库中和句柄"db"相关联) # 它们的变化被记录下来是为了撤销和重做的目的。 proc activate {args} { variable _undo if {$_undo(active)} return eval _create_triggers db $args set _undo(undostack) {} set _undo(redostack) {} set _undo(active) 1 set _undo(freeze) -1 _start_interval }
# proc: ::undo::deactivate # title: Halt the undo/redo system and delete the undo/redo stacks # proc deactivate {} { variable _undo if {!$_undo(active)} return _drop_triggers db set _undo(undostack) {} set _undo(redostack) {} set _undo(active) 0 set _undo(freeze) -1 }
# proc: ::undo::freeze # title: Stop accepting database changes into the undo stack # # 当这个例行程序被启用直到下一步被解冻前,新的数据库的变化将不被记录在撤销存储栈。 # proc freeze {} { variable _undo if {![info exists _undo(freeze)]} return if {$_undo(freeze)>=0} {error "recursive call to ::undo::freeze"} set _undo(freeze) [db one {SELECT coalesce(max(seq),0) FROM undolog}] }
# proc: ::undo::unfreeze # title: Begin accepting undo actions again. # proc unfreeze {} { variable _undo if {![info exists _undo(freeze)]} return if {$_undo(freeze)<0} {error "called ::undo::unfreeze while not frozen"} db eval "DELETE FROM undolog WHERE seq>$_undo(freeze)" set _undo(freeze) -1 }
# proc: ::undo::event # title: Something undoable has happened # # 当一个不可撤销的操作发生的时候调用这个程序。在下一个空闲时刻之前激活::undo::barrier。 # proc event {} { variable _undo if {$_undo(pending)==""} { set _undo(pending) [after idle ::undo::barrier] } }
# proc: ::undo::barrier # title: Create an undo barrier right now. # proc barrier {} { variable _undo catch {after cancel $_undo(pending)} set _undo(pending) {} if {!$_undo(active)} { refresh return } set end [db one {SELECT coalesce(max(seq),0) FROM undolog}] if {$_undo(freeze)>=0 && $end>$_undo(freeze)} {set end $_undo(freeze)} set begin $_undo(firstlog) _start_interval if {$begin==$_undo(firstlog)} { refresh return } lappend _undo(undostack) [list $begin $end] set _undo(redostack) {} refresh }
# proc: ::undo::undo # title: Do a single step of undo # proc undo {} { _step undostack redostack }
# proc: ::undo::redo # title: Redo a single step # proc redo {} { _step redostack undostack }
# proc: ::undo::refresh # title: Update the status of controls after a database change # # 基于现行数据库的状态,为了合理的进行控制,撤销模块在任何撤销和重做后调用这个例行程序。 这个模块通过激活所有顶级有名称的空间中的status_refresh模块来工作。 # proc refresh {} { set body {} foreach ns [namespace children ::] { if {[info proc ${ns}::status_refresh]==""} continue append body ${ns}::status_refresh/n } proc ::undo::refresh {} $body refresh }
# proc: ::undo::reload_all # title: Redraw everything based on the current database # # 为了使屏幕在数据库内容的基础上被完全重新绘图,撤销模块在任何的撤销和重做后都调用这个 # 例行程序。通过在每个顶级的有名称的空间调用"reload" 模块而不是::undo来完成这个程序。 proc reload_all {} { set body {} foreach ns [namespace children ::] { if {[info proc ${ns}::reload]==""} continue append body ${ns}::reload/n } proc ::undo::reload_all {} $body reload_all }
http://www.52php.cn/article/p-uluuuzzt-rg.html (编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|