diff --git a/index.html b/index.html index 7b384ffce..9e59359cd 100755 --- a/index.html +++ b/index.html @@ -70,7 +70,19 @@ iD.Hash().map(map); iD.UI.bind(); - iD.controller(map); + var controller = iD.controller(map); + + d3.selectAll('button#place').on('click', function() { + controller.go(iD.actions.AddPlace); + }); + + d3.selectAll('button#road').on('click', function() { + controller.go(iD.actions.AddRoad); + }); + + d3.selectAll('button#area').on('click', function() { + controller.go(iD.actions.AddArea); + }); window.onresize = function() { map.setSize(m.node().offsetWidth, diff --git a/js/iD/actions/actions.js b/js/iD/actions/actions.js index 2584b35ed..18efa77ee 100644 --- a/js/iD/actions/actions.js +++ b/js/iD/actions/actions.js @@ -1,13 +1,6 @@ iD.actions = {}; iD.actions.AddPlace = { - bind: function(controller, map) { - this.controller = controller; - this.map = map; - d3.selectAll('button#place').on('click', function() { - iD.actions.AddPlace.enter(); - }); - }, node: function(ll) { return { type: 'node', @@ -56,30 +49,125 @@ iD.actions.AddPlace = { }; iD.actions.AddRoad = { - bind: function(controller, map) { - this.controller = controller; - this.map = map; - d3.selectAll('button#road').on('click', function() { - iD.actions.AddRoad.enter(); - }); + node: function(ll) { + return { + type: 'node', + lat: ll[1], + lon: ll[0], + id: iD.Util.id(), + tags: {} + }; + }, + way: function(ll) { + return { + type: 'way', + nodes: [], + tags: { + highway: 'residential' + }, + id: iD.Util.id() + }; }, enter: function() { d3.selectAll('button').classed('active', false); d3.selectAll('button#road').classed('active', true); + + var surface = this.map.surface; + var teaser = surface.selectAll('g#temp-g') + .append('g').attr('id', 'addroad'); + + teaser.append('circle') + .attr('class', 'teaser-point') + .attr('r', 10); + + surface.on('mousemove.addroad', function() { + teaser.attr('transform', function() { + var off = d3.mouse(surface.node()); + return 'translate(' + off + ')'; + }); + }); + + surface.on('click.addroad', function() { + var ll = this.map.projection.invert( + d3.mouse(surface.node())); + var way = this.way(); + var node = this.node(ll); + way.nodes.push(node.id); + iD.operations.changeWayNodes(this.map, way, node); + this.controller.go(iD.actions.DrawRoad(way)); + this.exit(); + }.bind(this)); + + d3.select(document).on('keydown.addplace', function() { + if (d3.event.keyCode === 27) this.exit(); + }.bind(this)); }, exit: function() { + this.map.surface.on('.addroad', null); + d3.select(document).on('.addroad', null); + d3.selectAll('#addroad').remove(); d3.selectAll('button#road').classed('active', false); } }; +iD.actions.DrawRoad = function(way) { + return { + node: function(ll) { + return { + type: 'node', + lat: ll[1], + lon: ll[0], + id: iD.Util.id(), + tags: {} + }; + }, + enter: function() { + var surface = this.map.surface; + + this.falsenode = this.node([0, 0]); + + iD.operations.addTemporary(this.map, this.falsenode); + // way.nodes = way.nodes.slice(); + way.nodes.push(this.falsenode.id); + + surface.on('mousemove.drawroad', function() { + var ll = this.map.projection.invert(d3.mouse(surface.node())); + this.falsenode.lon = ll[0]; + this.falsenode.lat = ll[1]; + this.map.update(); + }.bind(this)); + + surface.on('click.drawroad', function() { + d3.event.stopPropagation(); + + way.nodes.pop(); + + var ll = this.map.projection.invert(d3.mouse(surface.node())); + var node = this.node(ll); + + way.nodes.push(node.id); + + iD.operations.changeWayNodes(this.map, way, node); + + way.nodes = way.nodes.slice(); + way.nodes.push(this.falsenode.id); + }.bind(this)); + + surface.on('dblclick.drawroad', function() { + d3.event.stopPropagation(); + this.exit(); + }.bind(this)); + }, + exit: function() { + iD.operations.addTemporary(this.map, this.falsenode); + this.map.surface.on('.drawroad', null); + d3.select(document).on('.drawroad', null); + d3.selectAll('#drawroad').remove(); + } + }; +}; + iD.actions.AddArea = { - bind: function(controller, map) { - this.controller = controller; - this.map = map; - d3.selectAll('button#area').on('click', function() { - iD.actions.AddArea.enter(); - }); - }, enter: function() { d3.selectAll('button').classed('active', false); d3.selectAll('button#area').classed('active', true); @@ -90,22 +178,19 @@ iD.actions.AddArea = { }; iD.actions.Move = { - bind: function(controller, map) { - this.controller = controller; - this.map = map; - }, enter: function() { d3.selectAll('button').classed('active', false); }, exit: function() { } }; + iD.controller = function(map) { var controller = { action: null }; - for (var a in iD.actions) iD.actions[a].bind(controller, map); - controller.go = function(x) { + x.controller = controller; + x.map = map; if (controller.action) { controller.action.exit(); } diff --git a/js/iD/actions/operations.js b/js/iD/actions/operations.js index e0f1bc73c..873fa6fe9 100644 --- a/js/iD/actions/operations.js +++ b/js/iD/actions/operations.js @@ -8,3 +8,39 @@ iD.operations.addNode = function(map, node) { }, 'added a place'); map.update(); }; + +iD.operations.startWay = function(map, way) { + map.graph.modify(function(graph) { + var o = {}; + o[way.id] = way; + return graph.set(o); + }, 'started a road'); + map.update(); +}; + +iD.operations.changeWayNodes = function(map, way, node) { + map.graph.modify(function(graph) { + var o = {}; + way.nodes = way.nodes.slice(); + o[way.id] = pdata.object(way).get(); + o[node.id] = node; + return graph.set(o); + }, 'added to a road'); + map.update(); +}; + +iD.operations.addTemporary = function(map, node) { + map.graph.modify(function(graph) { + var o = {}; + o[node.id] = node; + return graph.set(o); + }, ''); + map.update(); +}; + +iD.operations.removeTemporary = function(map, node) { + map.graph.modify(function(graph) { + return graph.remove(node.id); + }, ''); + map.update(); +}; diff --git a/js/iD/renderer/Map.js b/js/iD/renderer/Map.js index ed1ed89ba..9bdc1a937 100755 --- a/js/iD/renderer/Map.js +++ b/js/iD/renderer/Map.js @@ -354,6 +354,8 @@ iD.Map = function(elem) { map.undo = undo; map.redo = redo; + map.redraw = redraw; + setSize(parent.node().offsetWidth, parent.node().offsetHeight); redraw();