diff --git a/js/id/actions/modes.js b/js/id/actions/modes.js index 650b893d5..2ab14af37 100644 --- a/js/id/actions/modes.js +++ b/js/id/actions/modes.js @@ -42,7 +42,7 @@ iD.modes.AddPlace = { d3.mouse(surface.node())); var n = iD.modes._node(ll); n._poi = true; - this.map.perform(iD.actions.addNode(n)); + this.history.perform(iD.actions.addNode(n)); this.map.selectEntity(n); this.controller.exit(); this.exit(); @@ -117,16 +117,16 @@ iD.modes.AddRoad = { d3.mouse(surface.node()))); var connectedWay = this.map.history().graph().entity(t.data()[0].id); connectedWay.nodes.splice(index, 0, node.id); - this.map.perform(iD.actions.addWayNode(connectedWay, node)); + this.history.perform(iD.actions.addWayNode(connectedWay, node)); } else { node = iD.modes._node(this.map.projection.invert( d3.mouse(surface.node()))); } if (start) { - this.map.perform(iD.actions.startWay(way)); + this.history.perform(iD.actions.startWay(way)); way.nodes.push(node.id); - this.map.perform(iD.actions.addWayNode(way, node)); + this.history.perform(iD.actions.addWayNode(way, node)); } this.controller.enter(iD.modes.DrawRoad(way.id, direction)); } @@ -164,7 +164,7 @@ iD.modes.DrawRoad = function(way_id, direction) { firstNode = way.nodes[0], lastNode = _.last(way.nodes); way.nodes[push](nextnode_id); - this.map.perform(iD.actions.addWayNode(way, nextnode)); + this.history.perform(iD.actions.addWayNode(way, nextnode)); function mousemove() { var ll = this.map.projection.invert(d3.mouse(surface.node())); @@ -183,20 +183,20 @@ iD.modes.DrawRoad = function(way_id, direction) { if (t.data() && t.data()[0] && t.data()[0].type === 'node') { if (t.data()[0].id == firstNode || t.data()[0].id == lastNode) { var l = this.map.history().graph().entity(way.nodes[pop]()); - this.map.perform(iD.actions.removeWayNode(way, l)); + this.history.perform(iD.actions.removeWayNode(way, l)); // If this is drawing a loop and this is not the drawing // end of the stick, finish the circle if (direction === 'forward' && t.data()[0].id == firstNode) { way.nodes[push](firstNode); - this.map.perform(iD.actions.addWayNode(way, + this.history.perform(iD.actions.addWayNode(way, this.map.history().graph().entity(firstNode))); } else if (direction === 'backward' && t.data()[0].id == lastNode) { way.nodes[push](lastNode); - this.map.perform(iD.actions.addWayNode(way, + this.history.perform(iD.actions.addWayNode(way, this.map.history().graph().entity(lastNode))); } delete way.tags.elastic; - this.map.perform(iD.actions.changeTags(way, way.tags)); + this.history.perform(iD.actions.changeTags(way, way.tags)); this.map.selectEntity(way); // End by clicking on own tail return this.controller.exit(); @@ -210,15 +210,15 @@ iD.modes.DrawRoad = function(way_id, direction) { d3.mouse(surface.node()))); var connectedWay = this.map.history().graph().entity(t.data()[0].id); connectedWay.nodes.splice(1, 0, node.id); - this.map.perform(iD.actions.addWayNode(connectedWay, node)); + this.history.perform(iD.actions.addWayNode(connectedWay, node)); } else { node = iD.modes._node(this.map.projection.invert( d3.mouse(surface.node()))); } var old = this.map.history().graph().entity(way.nodes[pop]()); - this.map.perform(iD.actions.removeWayNode(way, old)); + this.history.perform(iD.actions.removeWayNode(way, old)); way.nodes[push](node.id); - this.map.perform(iD.actions.addWayNode(way, node)); + this.history.perform(iD.actions.addWayNode(way, node)); way.nodes = way.nodes.slice(); this.controller.enter(iD.modes.DrawRoad(way_id, direction)); } @@ -273,9 +273,9 @@ iD.modes.AddArea = { d3.mouse(surface.node()))); } - this.map.perform(iD.actions.startWay(way)); + this.history.perform(iD.actions.startWay(way)); way.nodes.push(node.id); - this.map.perform(iD.actions.addWayNode(way, node)); + this.history.perform(iD.actions.addWayNode(way, node)); this.map.selectEntity(way); this.controller.enter(iD.modes.DrawArea(way.id)); } @@ -309,7 +309,7 @@ iD.modes.DrawArea = function(way_id) { nextnode_id = nextnode.id; way.nodes.push(nextnode_id); - this.map.perform(iD.actions.addWayNode(way, nextnode)); + this.history.perform(iD.actions.addWayNode(way, nextnode)); function mousemove() { var ll = this.map.projection.invert(d3.mouse(surface.node())); @@ -329,12 +329,12 @@ iD.modes.DrawArea = function(way_id) { if (t.data() && t.data()[0] && t.data()[0].type === 'node') { if (t.data()[0].id == firstnode_id) { var l = this.map.history().graph().entity(way.nodes.pop()); - this.map.perform(iD.actions.removeWayNode(way, l)); + this.history.perform(iD.actions.removeWayNode(way, l)); way.nodes.push(way.nodes[0]); - this.map.perform(iD.actions.addWayNode(way, + this.history.perform(iD.actions.addWayNode(way, this.map.history().graph().entity(way.nodes[0]))); delete way.tags.elastic; - this.map.perform(iD.actions.changeTags(way, way.tags)); + this.history.perform(iD.actions.changeTags(way, way.tags)); // End by clicking on own tail return this.controller.exit(); } else { @@ -346,9 +346,9 @@ iD.modes.DrawArea = function(way_id) { d3.mouse(surface.node()))); } var old = this.map.history().graph().entity(way.nodes.pop()); - this.map.perform(iD.actions.removeWayNode(way, old)); + this.history.perform(iD.actions.removeWayNode(way, old)); way.nodes.push(node.id); - this.map.perform(iD.actions.addWayNode(way, node)); + this.history.perform(iD.actions.addWayNode(way, node)); way.nodes = way.nodes.slice(); this.controller.enter(iD.modes.DrawArea(way_id)); } diff --git a/js/id/controller/controller.js b/js/id/controller/controller.js index c3721b4eb..ac204b753 100644 --- a/js/id/controller/controller.js +++ b/js/id/controller/controller.js @@ -1,16 +1,19 @@ // A controller holds a single action at a time and calls `.enter` and `.exit` // to bind and unbind actions. -iD.Controller = function(map) { +iD.Controller = function(map, history) { var event = d3.dispatch('enter', 'exit'); var controller = { mode: null }; controller.enter = function(mode) { mode.controller = controller; + mode.history = history; mode.map = map; + if (controller.mode) { controller.mode.exit(); event.exit(controller.mode); } + mode.enter(); controller.mode = mode; event.enter(mode); diff --git a/js/id/id.js b/js/id/id.js index 6a54170b8..25d43ecec 100644 --- a/js/id/id.js +++ b/js/id/id.js @@ -5,7 +5,7 @@ var iD = function(container) { map = iD.Map() .connection(connection) .history(history), - controller = iD.Controller(map); + controller = iD.Controller(map, history); map.background.source(iD.Background.Bing); @@ -39,13 +39,13 @@ var iD = function(container) { .attr({ id: 'undo', 'class': 'mini' }) .property('disabled', true) .html('←') - .on('click', map.undo); + .on('click', history.undo); bar.append('button') .attr({ id: 'redo', 'class': 'mini' }) .property('disabled', true) .html('→') - .on('click', map.redo); + .on('click', history.redo); bar.append('input') .attr({ type: 'text', placeholder: 'find a place', id: 'geocode-location' }) @@ -118,7 +118,7 @@ var iD = function(container) { "report a bug " + "/ imagery © 2012 Bing, GeoEye, Getmapping, Intermap, Microsoft.

"); - history.on('change', function() { + history.on('change.buttons', function() { var undo = history.undoAnnotation(), redo = history.redoAnnotation(); @@ -140,11 +140,11 @@ var iD = function(container) { d3.select(document).on('keydown', function() { // cmd-z if (d3.event.which === 90 && d3.event.metaKey) { - map.undo(); + history.undo(); } // cmd-shift-z if (d3.event.which === 90 && d3.event.metaKey && d3.event.shiftKey) { - map.redo(); + history.redo(); } }); diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 611b2db3c..9c19d6973 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -12,9 +12,8 @@ iD.Map = function() { .scale(projection.scale()) .scaleExtent([1024, 256 * Math.pow(2, 20)]) .on('zoom', zoomPan), - only, dblclickEnabled = true, - dragging = false, + dragging, dragbehavior = d3.behavior.drag() .origin(function(entity) { if (entity.accuracy) { @@ -31,8 +30,7 @@ iD.Map = function() { d3.event.sourceEvent.stopPropagation(); if (!dragging) { - dragging = true; - only = iD.Util.trueObj([entity.id].concat( + dragging = iD.Util.trueObj([entity.id].concat( _.pluck(history.graph().parents(entity.id), 'id'))); history.perform(iD.actions.noop()); } @@ -40,11 +38,11 @@ iD.Map = function() { var to = projection.invert([d3.event.x, d3.event.y]); history.replace(iD.actions.move(entity, to)); - redraw(only); + redraw(); }) .on('dragend', function () { if (dragging) { - dragging = false; + dragging = undefined; redraw(); } }), @@ -455,16 +453,16 @@ iD.Map = function() { .filter(function(d) { return d.type === 'way'; }) .forEach(function(parent) { parent.nodes = _.without(parent.nodes, entity.id); - map.perform(iD.actions.removeWayNode(parent, entity)); + history.perform(iD.actions.removeWayNode(parent, entity)); }); - map.perform(iD.actions.remove(entity)); + history.perform(iD.actions.remove(entity)); } inspector.on('changeTags', function(d, tags) { var entity = history.graph().entity(d.id); - map.perform(iD.actions.changeTags(entity, tags)); + history.perform(iD.actions.changeTags(entity, tags)); }).on('changeWayDirection', function(d) { - map.perform(iD.actions.changeWayDirection(d)); + history.perform(iD.actions.changeWayDirection(d)); }).on('remove', function(d) { removeEntity(d); hideInspector(); @@ -500,38 +498,20 @@ iD.Map = function() { redraw(); } - function redraw(only) { - if (!only) { + function redraw() { + if (!dragging) { dispatch.move(map); tilegroup.call(background); } if (map.zoom() > 16) { download(); - drawVector(only); + drawVector(dragging); } else { hideVector(); } return map; } - map.perform = function(action) { - history.perform(action); - redraw(); - return map; - }; - - map.undo = function() { - history.undo(); - redraw(); - return map; - }; - - map.redo = function() { - history.redo(); - redraw(); - return map; - }; - function dblclickEnable(_) { if (!arguments.length) return dblclickEnabled; dblclickEnabled = _; @@ -613,6 +593,7 @@ iD.Map = function() { map.history = function (_) { if (!arguments.length) return history; history = _; + history.on('change.map', redraw); return map; };