mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-14 01:33:03 +00:00
First working revision of undo redo
This commit is contained in:
@@ -95,6 +95,9 @@
|
||||
|
||||
d3.select('.zoombuttons .zoom-in').on('click', map.zoomIn);
|
||||
d3.select('.zoombuttons .zoom-out').on('click', map.zoomOut);
|
||||
|
||||
d3.select('#undo').on('click', map.undo);
|
||||
d3.select('#redo').on('click', map.redo);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -4,6 +4,7 @@ iD.Graph.prototype = {
|
||||
|
||||
// a pointer to the top of the stack.
|
||||
head: {},
|
||||
annotation: null,
|
||||
|
||||
// stack of previous versions of this datastructure
|
||||
prev: [],
|
||||
@@ -29,6 +30,27 @@ iD.Graph.prototype = {
|
||||
return pois;
|
||||
},
|
||||
|
||||
undo: function() {
|
||||
if (this.prev.length && this.prev[0] !== this.head) {
|
||||
// skip changes without annotations
|
||||
for (var idx = this.prev.indexOf(this.head) - 1; idx > 0; idx--) {
|
||||
if (this.annotations[idx]) break;
|
||||
}
|
||||
this.head = this.prev[idx];
|
||||
this.annotation = this.annotations[idx];
|
||||
}
|
||||
},
|
||||
|
||||
redo: function() {
|
||||
if (this.prev.length && this.prev[this.prev.length - 1] !== this.head) {
|
||||
for (var idx = this.prev.indexOf(this.head) + 1; idx < this.prev.length - 1; idx++) {
|
||||
if (this.annotations[idx]) break;
|
||||
}
|
||||
this.head = this.prev[idx];
|
||||
this.annotation = this.annotations[idx];
|
||||
}
|
||||
},
|
||||
|
||||
insert: function(a) {
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
if (this.head[a[i].id]) return;
|
||||
@@ -54,6 +76,7 @@ iD.Graph.prototype = {
|
||||
|
||||
// Make head the top of the previous stack
|
||||
this.head = this.prev[this.prev.length - 1];
|
||||
this.annotation = this.annotations[this.annotations.length - 1];
|
||||
},
|
||||
|
||||
intersects: function(version, extent) {
|
||||
|
||||
@@ -10,6 +10,16 @@ iD.Map = function(elem) {
|
||||
|
||||
var version = 0;
|
||||
|
||||
// lon/lat object to array
|
||||
function ll2a(o) {
|
||||
return [o.lon, o.lat];
|
||||
}
|
||||
|
||||
// array to lon/lat object
|
||||
function a2ll(o) {
|
||||
return { lon: o[0], lat: o[1] };
|
||||
}
|
||||
|
||||
var map = {},
|
||||
width, height,
|
||||
dispatch = d3.dispatch('move', 'update'),
|
||||
@@ -30,8 +40,13 @@ iD.Map = function(elem) {
|
||||
// this is used with handles
|
||||
dragbehavior = d3.behavior.drag()
|
||||
.origin(function(d) {
|
||||
var n = graph.head[d];
|
||||
var p = projection([n.lon, n.lat]);
|
||||
var data = (typeof d === 'number') ? graph.head[d] : d;
|
||||
graph.modify(function(o) {
|
||||
var c = {};
|
||||
c[data.id] = pdata.object(data).set({ modified: true }).get();
|
||||
return o.set(c);
|
||||
}, '');
|
||||
p = projection(ll2a(data));
|
||||
return { x: p[0], y: p[1] };
|
||||
})
|
||||
.on('drag', function(d) {
|
||||
@@ -42,20 +57,28 @@ iD.Map = function(elem) {
|
||||
graph.head[d].lon = ll[0];
|
||||
graph.head[d].lat = ll[1];
|
||||
drawVector();
|
||||
})
|
||||
.on('dragend', function(d) {
|
||||
var data = (typeof d === 'number') ? graph.head[d] : d;
|
||||
graph.modify(function(o) {
|
||||
var c = {};
|
||||
c[data.id] = pdata.object(c[data.id]).get();
|
||||
o.set(c);
|
||||
return o;
|
||||
}, 'moved an element');
|
||||
map.update();
|
||||
}),
|
||||
// geo
|
||||
linegen = d3.svg.line()
|
||||
.defined(function(d) {
|
||||
return !!graph.head[d];
|
||||
})
|
||||
.x(function(d) {
|
||||
var node = graph.head[d];
|
||||
return projection([node.lon, node.lat])[0];
|
||||
})
|
||||
.y(function(d) {
|
||||
var node = graph.head[d];
|
||||
return projection([node.lon, node.lat])[1];
|
||||
}),
|
||||
.defined(function(d) {
|
||||
return !!graph.head[d];
|
||||
})
|
||||
.x(function(d) {
|
||||
return projection(ll2a(graph.head[d]))[0];
|
||||
})
|
||||
.y(function(d) {
|
||||
return projection(ll2a(graph.head[d]))[1];
|
||||
}),
|
||||
// Abstract linegen so that it pulls from `.children`. This
|
||||
// makes it possible to call simply `.attr('d', nodeline)`.
|
||||
nodeline = function(d) {
|
||||
@@ -63,13 +86,12 @@ iD.Map = function(elem) {
|
||||
},
|
||||
key = function(d) { return d.id; };
|
||||
|
||||
// Creating containers
|
||||
// -------------------
|
||||
// Containers
|
||||
// ----------
|
||||
// The map uses SVG groups in order to restrict
|
||||
// visual and event ordering - fills below casings, casings below
|
||||
// strokes, and so on.
|
||||
var surface = parent.append('svg')
|
||||
.call(zoombehavior);
|
||||
var surface = parent.append('svg').call(zoombehavior);
|
||||
|
||||
surface.append('defs').append('clipPath')
|
||||
.attr('id', 'clip')
|
||||
@@ -91,10 +113,10 @@ iD.Map = function(elem) {
|
||||
temp = r.append('g').attr('id', 'temp-g');
|
||||
|
||||
var class_stroke = iD.Style.styleClasses('stroke'),
|
||||
class_fill = iD.Style.styleClasses('stroke'),
|
||||
class_area = iD.Style.styleClasses('area'),
|
||||
class_marker = iD.Style.styleClasses('marker'),
|
||||
class_casing = iD.Style.styleClasses('casing');
|
||||
class_fill = iD.Style.styleClasses('stroke'),
|
||||
class_area = iD.Style.styleClasses('area'),
|
||||
class_marker = iD.Style.styleClasses('marker'),
|
||||
class_casing = iD.Style.styleClasses('casing');
|
||||
|
||||
var tileclient = iD.Tiles(tilegroup, projection);
|
||||
|
||||
@@ -172,8 +194,7 @@ iD.Map = function(elem) {
|
||||
.attr('r', 5)
|
||||
.call(dragbehavior);
|
||||
handles.attr('transform', function(d) {
|
||||
var node = graph.head[d];
|
||||
return 'translate(' + projection([node.lon, node.lat]) + ')';
|
||||
return 'translate(' + projection(ll2a(graph.head[d])) + ')';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -227,9 +248,21 @@ iD.Map = function(elem) {
|
||||
// -----------
|
||||
var undolabel = d3.select('button#undo small');
|
||||
dispatch.on('update', function() {
|
||||
undolabel.text(graph.annotations[graph.annotations.length - 1]);
|
||||
undolabel.text(graph.annotation);
|
||||
redraw();
|
||||
});
|
||||
|
||||
// Undo/redo
|
||||
function undo() {
|
||||
graph.undo();
|
||||
map.update();
|
||||
}
|
||||
|
||||
function redo() {
|
||||
graph.redo();
|
||||
map.update();
|
||||
}
|
||||
|
||||
// Getters & setters for map state
|
||||
// -------------------------------
|
||||
// The map state can be expressed entirely as the combination
|
||||
@@ -281,13 +314,9 @@ iD.Map = function(elem) {
|
||||
function zoomOut() { return setZoom(Math.floor(getZoom() - 1)); }
|
||||
|
||||
function getCenter() {
|
||||
var ll = projection.invert([
|
||||
return a2ll(projection.invert([
|
||||
width / 2,
|
||||
height / 2]);
|
||||
return {
|
||||
lon: ll[0],
|
||||
lat: ll[1]
|
||||
};
|
||||
height / 2]));
|
||||
}
|
||||
|
||||
function setCenter(loc) {
|
||||
@@ -322,6 +351,9 @@ iD.Map = function(elem) {
|
||||
map.graph = graph;
|
||||
map.surface = surface;
|
||||
|
||||
map.undo = undo;
|
||||
map.redo = redo;
|
||||
|
||||
setSize(parent.node().offsetWidth, parent.node().offsetHeight);
|
||||
redraw();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user