mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-18 14:45:12 +02:00
Extract Draw behavior
Fixed some bugs but introduced others.
This commit is contained in:
@@ -91,6 +91,8 @@
|
||||
<script src='js/id/behavior/drag_midpoint.js'></script>
|
||||
<script src='js/id/behavior/drag_node.js'></script>
|
||||
<script src='js/id/behavior/drag_way.js'></script>
|
||||
<script src='js/id/behavior/draw.js'></script>
|
||||
<script src='js/id/behavior/draw_way.js'></script>
|
||||
<script src='js/id/behavior/hover.js'></script>
|
||||
|
||||
<script src='js/id/modes.js'></script>
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
iD.behavior.Draw = function () {
|
||||
var event = d3.dispatch('move', 'add', 'drop', 'cancel', 'finish'),
|
||||
keybinding = d3.keybinding('draw');
|
||||
|
||||
function draw(selection) {
|
||||
function mousemove() {
|
||||
event.move();
|
||||
}
|
||||
|
||||
function click() {
|
||||
event.add();
|
||||
}
|
||||
|
||||
function backspace() {
|
||||
d3.event.preventDefault();
|
||||
event.drop();
|
||||
}
|
||||
|
||||
function del() {
|
||||
d3.event.preventDefault();
|
||||
event.cancel();
|
||||
}
|
||||
|
||||
function ret() {
|
||||
d3.event.preventDefault();
|
||||
event.finish();
|
||||
}
|
||||
|
||||
selection
|
||||
.on('mousemove.draw', mousemove)
|
||||
.on('click.draw', click);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
.on('⌦', del)
|
||||
.on('⎋', ret)
|
||||
.on('↩', ret);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
return draw;
|
||||
}
|
||||
|
||||
draw.off = function(selection) {
|
||||
selection
|
||||
.on('mousemove.draw', null)
|
||||
.on('click.draw', null);
|
||||
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
return d3.rebind(draw, event, 'on');
|
||||
};
|
||||
@@ -0,0 +1,146 @@
|
||||
iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
var map = mode.map,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'),
|
||||
way = mode.history.graph().entity(wayId),
|
||||
nodeId = way.nodes[index],
|
||||
hover, draw;
|
||||
|
||||
function move() {
|
||||
history.replace(
|
||||
iD.actions.MoveNode(nodeId, map.mouseCoordinates()),
|
||||
history.undoAnnotation());
|
||||
}
|
||||
|
||||
function add() {
|
||||
var datum = d3.select(d3.event.target).datum() || {};
|
||||
|
||||
if (datum.id === headId) {
|
||||
event.addHead(datum);
|
||||
} else if (datum.id === tailId) {
|
||||
event.addTail(datum);
|
||||
} else if (datum.type === 'node' && datum.id !== nodeId) {
|
||||
event.addNode(datum);
|
||||
} else if (datum.type === 'way') {
|
||||
var choice = iD.geo.chooseIndex(datum, d3.mouse(map.surface.node()), map);
|
||||
event.addWay(datum, choice.loc, choice.index);
|
||||
} else if (datum.midpoint) {
|
||||
var way = history.graph().entity(datum.way);
|
||||
event.addWay(way, datum.loc, datum.index);
|
||||
} else {
|
||||
event.add(map.mouseCoordinates());
|
||||
}
|
||||
}
|
||||
|
||||
function undone() {
|
||||
var way = history.graph().entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(mode);
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
var drawWay = function(surface) {
|
||||
map.fastEnable(false)
|
||||
.minzoom(16)
|
||||
.dblclickEnable(false);
|
||||
|
||||
surface.call(hover)
|
||||
.call(draw)
|
||||
.selectAll('.way, .node')
|
||||
.filter(function (d) { return d.id === wayId || d.id === nodeId; })
|
||||
.classed('active', true);
|
||||
|
||||
history.on('undone.draw', undone);
|
||||
};
|
||||
|
||||
drawWay.off = function(surface) {
|
||||
map.fastEnable(true)
|
||||
.minzoom(0)
|
||||
.tail(false);
|
||||
|
||||
window.setTimeout(function() {
|
||||
map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
|
||||
surface.call(hover.off)
|
||||
.call(draw.off)
|
||||
.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
history.on('undone.draw', null);
|
||||
};
|
||||
|
||||
// Connect the way to an existing node. Continue drawing, or enter the optional `newMode`.
|
||||
drawWay.addNode = function(node, annotation, newMode) {
|
||||
history.perform(
|
||||
iD.actions.AddWayNode(wayId, node.id, index),
|
||||
annotation);
|
||||
|
||||
controller.enter(newMode || mode);
|
||||
};
|
||||
|
||||
// Connect the way to an existing way.
|
||||
drawWay.addWay = function(way, loc, wayIndex, annotation) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(newNode),
|
||||
iD.actions.AddWayNode(wayId, newNode.id, index),
|
||||
iD.actions.AddWayNode(way.id, newNode.id, wayIndex),
|
||||
annotation);
|
||||
|
||||
controller.enter(mode);
|
||||
};
|
||||
|
||||
// Accept the current position of the temporary node and continue drawing.
|
||||
drawWay.add = function(loc, annotation) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(newNode),
|
||||
iD.actions.AddWayNode(wayId, newNode.id, index),
|
||||
annotation);
|
||||
|
||||
controller.enter(mode);
|
||||
};
|
||||
|
||||
// Remove the temporary node and the last connected node but continue drawing.
|
||||
drawWay.drop = function() {
|
||||
history.undo();
|
||||
};
|
||||
|
||||
// Finish the draw operation, removing the temporary node. If the way has enough
|
||||
// nodes to be valid, it's selected. Otherwise, return to browse mode.
|
||||
drawWay.finish = function() {
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(nodeId),
|
||||
history.undoAnnotation());
|
||||
|
||||
var way = history.graph().entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
};
|
||||
|
||||
// Cancel the draw operation and return to browse, deleting everything drawn.
|
||||
drawWay.cancel = function() {
|
||||
history.perform(iD.actions.DeleteWay(wayId), 'cancelled drawing');
|
||||
controller.enter(iD.modes.Browse());
|
||||
};
|
||||
|
||||
hover = iD.behavior.Hover();
|
||||
|
||||
draw = iD.behavior.Draw()
|
||||
.on('move', move)
|
||||
.on('add', add)
|
||||
.on('drop', drawWay.drop)
|
||||
.on('cancel', drawWay.cancel)
|
||||
.on('finish', drawWay.finish);
|
||||
|
||||
return d3.rebind(drawWay, event, 'on');
|
||||
};
|
||||
@@ -8,7 +8,7 @@ iD.History = function() {
|
||||
|
||||
var annotation;
|
||||
|
||||
if (_.isString(_.last(actions))) {
|
||||
if (!_.isFunction(_.last(actions))) {
|
||||
annotation = actions.pop();
|
||||
}
|
||||
|
||||
|
||||
+30
-15
@@ -6,30 +6,33 @@ iD.modes.AddArea = function() {
|
||||
description: 'Add parks, buildings, lakes, or other areas to the map.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-area');
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.tail('Click on the map to start drawing an area, like a park, lake, or building.');
|
||||
|
||||
map.surface.on('click.addarea', function() {
|
||||
function add() {
|
||||
var datum = d3.select(d3.event.target).datum() || {},
|
||||
way = iD.Way({tags: { area: 'yes' }});
|
||||
way = iD.Way({tags: { area: 'yes' }}),
|
||||
node;
|
||||
|
||||
if (datum.type === 'node') {
|
||||
// start from an existing node
|
||||
node = datum;
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, datum.id),
|
||||
iD.actions.AddWayNode(way.id, datum.id));
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
} else {
|
||||
// start from a new node
|
||||
var node = iD.Node({loc: map.mouseCoordinates()});
|
||||
node = iD.Node({loc: map.mouseCoordinates()});
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddNode(node),
|
||||
@@ -37,24 +40,36 @@ iD.modes.AddArea = function() {
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
}
|
||||
|
||||
node = iD.Node({loc: node.loc});
|
||||
|
||||
history.replace(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(way.id, node.id, -1),
|
||||
'started an area');
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
});
|
||||
}
|
||||
|
||||
keybinding.on('⎋', function() {
|
||||
function cancel() {
|
||||
controller.exit();
|
||||
});
|
||||
}
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
behavior = iD.behavior.Draw()
|
||||
.on('add', add)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel)
|
||||
(surface);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addarea', null);
|
||||
keybinding.off();
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+34
-19
@@ -6,37 +6,38 @@ iD.modes.AddLine = function() {
|
||||
description: 'Lines can be highways, streets, pedestrian paths, or even canals.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-line');
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
graph = map.history().graph(),
|
||||
node,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.tail('Click on the map to start drawing an road, path, or route.');
|
||||
|
||||
map.surface.on('click.addline', function() {
|
||||
function add() {
|
||||
var datum = d3.select(d3.event.target).datum() || {},
|
||||
way = iD.Way({ tags: { highway: 'residential' } }),
|
||||
direction = 'forward';
|
||||
direction = 'forward',
|
||||
node;
|
||||
|
||||
if (datum.type === 'node') {
|
||||
// continue an existing way
|
||||
var id = datum.id;
|
||||
var parents = history.graph(graph).parentWays(datum);
|
||||
node = datum;
|
||||
var parents = history.graph(graph).parentWays(node);
|
||||
var isLine = parents.length && parents[0].geometry(graph) === 'line';
|
||||
if (isLine && parents[0].nodes[0] === id ) {
|
||||
if (isLine && parents[0].first() === node.id) {
|
||||
way = parents[0];
|
||||
direction = 'backward';
|
||||
} else if (isLine && _.last(parents[0].nodes) === id) {
|
||||
} else if (isLine && parents[0].last() === node.id) {
|
||||
way = parents[0];
|
||||
} else {
|
||||
history.perform(
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, datum.id));
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
}
|
||||
|
||||
} else if (datum.type === 'way') {
|
||||
@@ -60,22 +61,36 @@ iD.modes.AddLine = function() {
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
}
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, direction));
|
||||
});
|
||||
var index = (direction === 'forward') ? way.nodes.length : 0,
|
||||
|
||||
keybinding.on('⎋', function() {
|
||||
node = iD.Node({loc: node.loc});
|
||||
|
||||
history.replace(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(way.id, node.id, index),
|
||||
'started a line');
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, direction, node));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
controller.exit();
|
||||
});
|
||||
}
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
behavior = iD.behavior.Draw()
|
||||
.on('add', add)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel)
|
||||
(surface);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addline', null);
|
||||
keybinding.off();
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
map.dblclickEnable(true);
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+16
-10
@@ -5,16 +5,17 @@ iD.modes.AddPoint = function() {
|
||||
description: 'Restaurants, monuments, and postal boxes are points.'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('add-point');
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
map.tail('Click on the map to add a point.');
|
||||
|
||||
map.surface.on('click.addpoint', function() {
|
||||
function add() {
|
||||
var node = iD.Node({loc: map.mouseCoordinates()});
|
||||
|
||||
history.perform(
|
||||
@@ -22,20 +23,25 @@ iD.modes.AddPoint = function() {
|
||||
'added a point');
|
||||
|
||||
controller.enter(iD.modes.Select(node, true));
|
||||
});
|
||||
}
|
||||
|
||||
keybinding.on('⎋', function() {
|
||||
function cancel() {
|
||||
controller.exit();
|
||||
});
|
||||
}
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
behavior = iD.behavior.Draw()
|
||||
.on('add', add)
|
||||
.on('cancel', cancel)
|
||||
.on('finish', cancel)
|
||||
(surface);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
mode.map.tail(false);
|
||||
mode.map.surface.on('click.addpoint', null);
|
||||
keybinding.off();
|
||||
var map = mode.map,
|
||||
surface = map.surface;
|
||||
|
||||
map.tail(false);
|
||||
behavior.off(surface);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+19
-127
@@ -4,147 +4,39 @@ iD.modes.DrawArea = function(wayId) {
|
||||
id: 'draw-area'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('draw-area');
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
way = history.graph().entity(wayId),
|
||||
index = way.nodes.length - 1,
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
index = way.nodes.length - 2,
|
||||
headId = way.nodes[index - 1],
|
||||
tailId = way.first(),
|
||||
node = iD.Node({loc: map.mouseCoordinates()});
|
||||
tailId = way.first();
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.fastEnable(false);
|
||||
map.tail('Click to add points to your area. Click the first point to finish the area.');
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(way.id, node.id, index));
|
||||
|
||||
surface.selectAll('.way, .node')
|
||||
.filter(function (d) { return d.id === wayId || d.id === node.id; })
|
||||
.classed('active', true);
|
||||
|
||||
function ReplaceTemporaryNode(replacementId) {
|
||||
return function(graph) {
|
||||
graph = graph.replace(graph.entity(wayId).updateNode(replacementId, index));
|
||||
graph = graph.remove(node);
|
||||
return graph;
|
||||
}
|
||||
function addHeadTail() {
|
||||
behavior.finish();
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, way.nodes.length > 2 ? 'added to an area' : '');
|
||||
}
|
||||
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum() || {};
|
||||
|
||||
if (datum.id === tailId || datum.id === headId) {
|
||||
if (way.nodes.length > 3) {
|
||||
history.undo();
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
} else {
|
||||
// Areas with less than 3 nodes gets deleted
|
||||
history.replace(iD.actions.DeleteWay(way.id));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
} else if (datum.type === 'node' && datum.id !== node.id) {
|
||||
// connect the way to an existing node
|
||||
history.replace(
|
||||
ReplaceTemporaryNode(datum.id),
|
||||
way.nodes.length > 2 ? 'added to an area' : '');
|
||||
|
||||
controller.enter(iD.modes.DrawArea(wayId));
|
||||
|
||||
} else {
|
||||
history.replace(
|
||||
iD.actions.Noop(),
|
||||
way.nodes.length > 2 ? 'added to an area' : '');
|
||||
|
||||
controller.enter(iD.modes.DrawArea(wayId));
|
||||
}
|
||||
function add(loc) {
|
||||
behavior.add(loc, way.nodes.length > 2 ? 'added to an area' : '');
|
||||
}
|
||||
|
||||
function backspace() {
|
||||
d3.event.preventDefault();
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
|
||||
.on('addHead', addHeadTail)
|
||||
.on('addTail', addHeadTail)
|
||||
.on('addNode', addNode)
|
||||
.on('addWay', add)
|
||||
.on('add', add);
|
||||
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(node.id),
|
||||
iD.actions.DeleteNode(headId));
|
||||
|
||||
if (history.graph().entity(wayId)) {
|
||||
controller.enter(iD.modes.DrawArea(wayId));
|
||||
} else {
|
||||
// The way was deleted because it had too few nodes.
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
function del() {
|
||||
d3.event.preventDefault();
|
||||
history.replace(iD.actions.DeleteWay(wayId));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
function ret() {
|
||||
d3.event.preventDefault();
|
||||
|
||||
history.replace(iD.actions.DeleteNode(node.id));
|
||||
|
||||
if (history.graph().entity(wayId)) {
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
} else {
|
||||
// The way was deleted because it had too few nodes.
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
surface
|
||||
.on('mousemove.drawarea', mousemove)
|
||||
.on('click.drawarea', click);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
.on('⌦', del)
|
||||
.on('⎋', ret)
|
||||
.on('↩', ret);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
history.on('undone.drawarea', function () {
|
||||
controller.enter(iD.modes.Browse());
|
||||
});
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click to add points to your area. Click the first point to finish the area.');
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history;
|
||||
|
||||
surface.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
map.tail(false);
|
||||
map.fastEnable(true);
|
||||
|
||||
surface
|
||||
.on('mousemove.drawarea', null)
|
||||
.on('click.drawarea', null);
|
||||
|
||||
keybinding.off();
|
||||
|
||||
history.on('undone.drawarea', null);
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
mode.map.surface.call(behavior.off);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
+38
-166
@@ -4,182 +4,54 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
id: 'draw-line'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('draw-line');
|
||||
var behavior;
|
||||
|
||||
mode.enter = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history,
|
||||
controller = mode.controller,
|
||||
way = history.graph().entity(wayId),
|
||||
node = iD.Node({loc: map.mouseCoordinates()}),
|
||||
index = (direction === 'forward') ? way.nodes.length : 0,
|
||||
headId = (direction === 'forward') ? way.last() : way.first(),
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
index = (direction === 'forward') ? way.nodes.length - 1 : 0,
|
||||
headId = (direction === 'forward') ? way.nodes[index - 1] : way.nodes[index + 1],
|
||||
tailId = (direction === 'forward') ? way.first() : way.last();
|
||||
|
||||
iD.behavior.Hover()(surface);
|
||||
function addHead() {
|
||||
behavior.finish();
|
||||
}
|
||||
|
||||
map.dblclickEnable(false)
|
||||
.fastEnable(false)
|
||||
.tail('Click to add more points to the line. ' +
|
||||
function addTail(node) {
|
||||
// connect the way in a loop
|
||||
if (way.nodes.length > 2) {
|
||||
behavior.addNode(node, 'added to a line', iD.modes.Select(way, true))
|
||||
} else {
|
||||
behavior.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, 'added to a line');
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
behavior.addWay(way, loc, index, 'added to a line');
|
||||
}
|
||||
|
||||
function add(loc) {
|
||||
behavior.add(loc, 'added to a line');
|
||||
}
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
|
||||
.on('addHead', addHead)
|
||||
.on('addTail', addTail)
|
||||
.on('addNode', addNode)
|
||||
.on('addWay', addWay)
|
||||
.on('add', add);
|
||||
|
||||
mode.map.surface.call(behavior);
|
||||
mode.map.tail('Click to add more points to the line. ' +
|
||||
'Click on other lines to connect to them, and double-click to ' +
|
||||
'end the line.');
|
||||
|
||||
map.minzoom(16);
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(wayId, node.id, index));
|
||||
|
||||
surface.selectAll('.way, .node')
|
||||
.filter(function (d) { return d.id === wayId || d.id === node.id; })
|
||||
.classed('active', true);
|
||||
|
||||
function ReplaceTemporaryNode(replacementId) {
|
||||
return function(graph) {
|
||||
graph = graph.replace(graph.entity(wayId).updateNode(replacementId, index));
|
||||
graph = graph.remove(node);
|
||||
return graph;
|
||||
}
|
||||
}
|
||||
|
||||
function mousemove() {
|
||||
history.replace(iD.actions.MoveNode(node.id, map.mouseCoordinates()));
|
||||
}
|
||||
|
||||
function click() {
|
||||
var datum = d3.select(d3.event.target).datum() || {};
|
||||
|
||||
if (datum.id === tailId) {
|
||||
// connect the way in a loop
|
||||
if (way.nodes.length > 2) {
|
||||
history.replace(
|
||||
ReplaceTemporaryNode(tailId),
|
||||
'added to a line');
|
||||
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
|
||||
} else {
|
||||
history.replace(iD.actions.DeleteWay(way.id));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
} else if (datum.id === headId) {
|
||||
// finish the way
|
||||
history.undo();
|
||||
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
|
||||
} else if (datum.type === 'node' && datum.id !== node.id) {
|
||||
// connect the way to an existing node
|
||||
history.replace(
|
||||
ReplaceTemporaryNode(datum.id),
|
||||
'added to a line');
|
||||
|
||||
controller.enter(iD.modes.DrawLine(wayId, direction));
|
||||
|
||||
} else if (datum.type === 'way' || datum.midpoint) {
|
||||
var choice;
|
||||
// connect the way to an existing way
|
||||
if (datum.midpoint) {
|
||||
// if clicked on midpoint
|
||||
datum.id = datum.way;
|
||||
choice = datum;
|
||||
} else {
|
||||
choice = iD.geo.chooseIndex(datum, d3.mouse(surface.node()), map);
|
||||
}
|
||||
|
||||
history.replace(
|
||||
iD.actions.MoveNode(node.id, choice.loc),
|
||||
iD.actions.AddWayNode(datum.id, node.id, choice.index),
|
||||
'added to a line');
|
||||
|
||||
controller.enter(iD.modes.DrawLine(wayId, direction));
|
||||
|
||||
} else {
|
||||
history.replace(
|
||||
iD.actions.Noop(),
|
||||
'added to a line');
|
||||
|
||||
controller.enter(iD.modes.DrawLine(wayId, direction));
|
||||
}
|
||||
}
|
||||
|
||||
function backspace() {
|
||||
d3.event.preventDefault();
|
||||
|
||||
history.replace(
|
||||
iD.actions.DeleteNode(node.id),
|
||||
iD.actions.DeleteNode(headId));
|
||||
|
||||
if (history.graph().entity(wayId)) {
|
||||
controller.enter(iD.modes.DrawLine(wayId, direction));
|
||||
} else {
|
||||
// The way was deleted because it had too few nodes.
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
function del() {
|
||||
d3.event.preventDefault();
|
||||
history.replace(iD.actions.DeleteWay(wayId));
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
function ret() {
|
||||
d3.event.preventDefault();
|
||||
|
||||
history.replace(iD.actions.DeleteNode(node.id));
|
||||
|
||||
if (history.graph().entity(wayId)) {
|
||||
controller.enter(iD.modes.Select(way, true));
|
||||
} else {
|
||||
// The way was deleted because it had too few nodes.
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
}
|
||||
|
||||
surface
|
||||
.on('mousemove.drawline', mousemove)
|
||||
.on('click.drawline', click);
|
||||
|
||||
keybinding
|
||||
.on('⌫', backspace)
|
||||
.on('⌦', del)
|
||||
.on('⎋', ret)
|
||||
.on('↩', ret);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
|
||||
history.on('undone.drawline', function () {
|
||||
controller.enter(iD.modes.Browse());
|
||||
});
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
var map = mode.map,
|
||||
surface = map.surface,
|
||||
history = mode.history;
|
||||
|
||||
surface.selectAll('.way, .node')
|
||||
.classed('active', false);
|
||||
|
||||
map.tail(false);
|
||||
map.fastEnable(true);
|
||||
map.minzoom(0);
|
||||
|
||||
surface
|
||||
.on('mousemove.drawline', null)
|
||||
.on('click.drawline', null);
|
||||
|
||||
keybinding.off();
|
||||
|
||||
history.on('undone.drawline', null);
|
||||
|
||||
window.setTimeout(function() {
|
||||
mode.map.dblclickEnable(true);
|
||||
}, 1000);
|
||||
mode.map.surface.call(behavior.off);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
@@ -341,6 +341,7 @@ iD.Map = function() {
|
||||
map.minzoom = function(_) {
|
||||
if (!arguments.length) return minzoom;
|
||||
minzoom = _;
|
||||
return map;
|
||||
};
|
||||
|
||||
map.history = function (_) {
|
||||
|
||||
@@ -86,6 +86,8 @@
|
||||
<script src='../js/id/behavior/drag_midpoint.js'></script>
|
||||
<script src='../js/id/behavior/drag_node.js'></script>
|
||||
<script src='../js/id/behavior/drag_way.js'></script>
|
||||
<script src='../js/id/behavior/draw.js'></script>
|
||||
<script src='../js/id/behavior/draw_way.js'></script>
|
||||
<script src='../js/id/behavior/hover.js'></script>
|
||||
|
||||
<script src='../js/id/modes.js'></script>
|
||||
|
||||
Reference in New Issue
Block a user