Convert History to module pattern

There is only ever one History, so memory use is not a
concern.
This commit is contained in:
John Firebaugh
2012-12-03 17:44:24 -05:00
parent 0370b487e3
commit e93c9624d8
3 changed files with 117 additions and 77 deletions
+75 -77
View File
@@ -1,85 +1,83 @@
iD.History = function() {
if (!(this instanceof iD.History)) return new iD.History();
this.stack = [iD.Graph()];
this.index = 0;
};
var stack = [iD.Graph()],
index = 0;
iD.History.prototype = {
return {
graph: function () {
return stack[index];
},
graph: function() {
return this.stack[this.index];
},
merge: function (graph) {
for (var i = 0; i < stack.length; i++) {
stack[i] = stack[i].merge(graph);
}
},
merge: function(graph) {
for (var i = 0; i < this.stack.length; i++) {
this.stack[i] = this.stack[i].merge(graph);
}
},
perform: function(action) {
this.stack = this.stack.slice(0, this.index + 1);
this.stack.push(action(this.graph()));
this.index++;
},
replace: function(action) {
// assert(this.index == this.stack.length - 1)
this.stack[this.index] = action(this.graph());
},
undo: function() {
while (this.index > 0) {
this.index--;
if (this.stack[this.index].annotation) break;
}
},
redo: function() {
while (this.index < this.stack.length - 1) {
this.index++;
if (this.stack[this.index].annotation) break;
}
},
undoAnnotation: function() {
var index = this.index;
while (index >= 0) {
if (this.stack[index].annotation) return this.stack[index].annotation;
index--;
}
},
redoAnnotation: function() {
var index = this.index + 1;
while (index <= this.stack.length - 1) {
if (this.stack[index].annotation) return this.stack[index].annotation;
perform: function (action) {
stack = stack.slice(0, index + 1);
stack.push(action(this.graph()));
index++;
},
replace: function (action) {
// assert(index == stack.length - 1)
stack[index] = action(this.graph());
},
undo: function () {
while (index > 0) {
index--;
if (stack[index].annotation) break;
}
},
redo: function () {
while (index < stack.length - 1) {
index++;
if (stack[index].annotation) break;
}
},
undoAnnotation: function () {
var i = index;
while (i >= 0) {
if (stack[i].annotation) return stack[i].annotation;
i--;
}
},
redoAnnotation: function () {
var i = index + 1;
while (i <= stack.length - 1) {
if (stack[i].annotation) return stack[i].annotation;
i++;
}
},
// generate reports of changes for changesets to use
modify: function () {
return stack[index].modifications();
},
create: function () {
return stack[index].creations();
},
'delete': function () {
return _.difference(
_.pluck(stack[0].entities, 'id'),
_.pluck(stack[index].entities, 'id')
).map(function (id) {
return stack[0].fetch(id);
});
},
changes: function () {
return {
modify: this.modify(),
create: this.create(),
'delete': this['delete']()
};
}
},
// generate reports of changes for changesets to use
modify: function() {
return this.stack[this.index].modifications();
},
create: function() {
return this.stack[this.index].creations();
},
'delete': function() {
return _.difference(
_.pluck(this.stack[0].entities, 'id'),
_.pluck(this.stack[this.index].entities, 'id')
).map(function(id) {
return this.stack[0].fetch(id);
}.bind(this));
},
changes: function() {
return {
modify: this.modify(),
create: this.create(),
'delete': this['delete']()
};
}
};
+1
View File
@@ -72,6 +72,7 @@
<script src="spec/oauth.js"></script>
<script src="spec/graph.js"></script>
<script src="spec/entity.js"></script>
<script src="spec/history.js"></script>
<script src="spec/connection.js"></script>
<script src="spec/geojson.js"></script>
<script src="spec/xml.js"></script>
+41
View File
@@ -0,0 +1,41 @@
describe("History", function () {
var history, spy,
graph = iD.Graph([], "action"),
action = function() { return graph; };
beforeEach(function () {
history = iD.History();
});
describe("#graph", function () {
it("returns the current graph", function () {
expect(history.graph()).to.be.an.instanceOf(iD.Graph);
});
});
describe("#perform", function () {
it("updates the graph", function () {
history.perform(action);
expect(history.graph()).to.equal(graph);
});
it("pushes the undo stack", function () {
history.perform(action);
expect(history.undoAnnotation()).to.equal("action");
});
});
describe("#undo", function () {
it("pops the undo stack", function () {
history.perform(action);
history.undo();
expect(history.undoAnnotation()).to.be.undefined;
});
it("pushes the redo stack", function () {
history.perform(action);
history.undo();
expect(history.redoAnnotation()).to.equal("action");
});
});
});