1 rio.Undo = { 2 setQueue: function(queue) { 3 if (!this._bindingPoints) { 4 this._bindingPoints = new (rio.Attr.create({ 5 attrAccessors: [ 6 "queue", 7 ["hasUndos", false], 8 ["hasRedos", false] 9 ] 10 }))(); 11 12 this._bindingPoints.bind("queue.undos", { 13 empty: function(empty) { 14 this._bindingPoints.setHasUndos(!empty); 15 }.bind(this) 16 }); 17 this._bindingPoints.bind("queue.redos", { 18 empty: function(empty) { 19 this._bindingPoints.setHasRedos(!empty); 20 }.bind(this) 21 }); 22 23 this.hasUndos = this._bindingPoints.hasUndos; 24 this.hasRedos = this._bindingPoints.hasRedos; 25 } 26 27 this._bindingPoints.setQueue(queue); 28 this._queue = queue; 29 }, 30 31 undoQueueEmpty: function() { 32 return this._queue.getUndos().empty(); 33 }, 34 35 redoQueueEmpty: function() { 36 return this._queue.getRedos().empty(); 37 }, 38 39 isProcessingUndo: function() { 40 return this._queue.getProcessingUndo(); 41 }, 42 43 isProcessingRedo: function() { 44 return this._queue.getProcessingRedo(); 45 }, 46 47 setProcessingUndo: function(val) { 48 this._queue.setProcessingUndo(val); 49 }, 50 51 setProcessingRedo: function(val) { 52 this._queue.setProcessingRedo(val); 53 }, 54 55 registerUndo: function(undo, dontClearRedos) { 56 if (!dontClearRedos) { 57 this._queue.getRedos().clear(); 58 } 59 this._queue.getUndos().push(function() { 60 rio.Undo.setProcessingUndo(true); 61 try { 62 undo(); 63 } finally { 64 rio.Undo.setProcessingUndo(false); 65 } 66 }); 67 }, 68 69 registerRedo: function(redo) { 70 this._queue.getRedos().push(function() { 71 rio.Undo.setProcessingRedo(true); 72 try { 73 redo(); 74 } finally { 75 rio.Undo.setProcessingRedo(false); 76 } 77 }); 78 }, 79 80 undo: function() { 81 this._doAction("undo"); 82 }, 83 84 redo: function() { 85 this._doAction("redo"); 86 }, 87 88 _actionProgress: false, 89 _actionQueue: [], 90 _doAction: function(action) { 91 if (this._actionProgress) { 92 this._actionQueue.push(this[action].bind(this)); 93 return; 94 } 95 this._actionProgress = true; 96 try { 97 var toDo = this._queue[("get-" + action + "s").camelize()]().pop(); 98 if (toDo) { 99 rio.Attr.transaction(function() { 100 toDo(); 101 }); 102 } 103 } finally { 104 this._afterAction(); 105 } 106 }, 107 108 _doAfterAction: function() { 109 (function() { 110 this._afterAction(); 111 }.bind(this)).defer(); 112 }, 113 114 _afterAction: function() { 115 var next = this._actionQueue.shift(); 116 this._actionProgress = false; 117 if (next) { 118 next(); 119 } 120 }, 121 122 toString: function() { return "Undo"; } 123 }; 124 125 rio.UndoQueue = rio.Attr.create({ 126 attrAccessors: [ 127 ["undos", []], 128 ["redos", []], 129 ["processingUndo", false], 130 ["processingRedo", false] 131 ] 132 }); 133 134 rio.Undo.setQueue(new rio.UndoQueue()); 135