mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
Fixing draw mode bugs
Disabling interactive draw undo for now. I know how to fix it but it's a bit tricky. So undo will just drop you out to browse mode for the time being. Fixes #477. Fixes #516.
This commit is contained in:
@@ -4,13 +4,17 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
controller = mode.controller,
|
||||
event = d3.dispatch('add', 'addHead', 'addTail', 'addNode', 'addWay'),
|
||||
way = mode.history.graph().entity(wayId),
|
||||
nodeId = way.nodes[index],
|
||||
hover, draw;
|
||||
|
||||
var node = iD.Node({loc: map.mouseCoordinates()}),
|
||||
nodeId = node.id;
|
||||
|
||||
history[way.isDegenerate() ? 'replace' : 'perform'](
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(wayId, node.id, index));
|
||||
|
||||
function move() {
|
||||
history.replace(
|
||||
iD.actions.MoveNode(nodeId, map.mouseCoordinates()),
|
||||
history.undoAnnotation());
|
||||
history.replace(iD.actions.MoveNode(nodeId, map.mouseCoordinates()));
|
||||
}
|
||||
|
||||
function add() {
|
||||
@@ -34,12 +38,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
}
|
||||
|
||||
function undone() {
|
||||
var way = history.graph().entity(wayId);
|
||||
if (way) {
|
||||
controller.enter(mode);
|
||||
} else {
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
controller.enter(iD.modes.Browse());
|
||||
}
|
||||
|
||||
var drawWay = function(surface) {
|
||||
@@ -73,10 +72,18 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
history.on('undone.draw', null);
|
||||
};
|
||||
|
||||
function ReplaceTemporaryNode(newNode) {
|
||||
return function(graph) {
|
||||
return graph
|
||||
.replace(way.removeNode(nodeId).addNode(newNode.id, index))
|
||||
.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect the way to an existing node and continue drawing.
|
||||
drawWay.addNode = function(node, annotation) {
|
||||
history.perform(
|
||||
iD.actions.AddWayNode(wayId, node.id, index),
|
||||
ReplaceTemporaryNode(node),
|
||||
annotation);
|
||||
|
||||
controller.enter(mode);
|
||||
@@ -88,8 +95,8 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(newNode),
|
||||
iD.actions.AddWayNode(wayId, newNode.id, index),
|
||||
iD.actions.AddWayNode(way.id, newNode.id, wayIndex),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
controller.enter(mode);
|
||||
@@ -99,9 +106,9 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
drawWay.add = function(loc, annotation) {
|
||||
var newNode = iD.Node({loc: loc});
|
||||
|
||||
history.perform(
|
||||
history.replace(
|
||||
iD.actions.AddNode(newNode),
|
||||
iD.actions.AddWayNode(wayId, newNode.id, index),
|
||||
ReplaceTemporaryNode(newNode),
|
||||
annotation);
|
||||
|
||||
controller.enter(mode);
|
||||
@@ -110,9 +117,7 @@ iD.behavior.DrawWay = function(wayId, headId, tailId, index, mode) {
|
||||
// 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());
|
||||
history.pop();
|
||||
|
||||
var way = history.graph().entity(wayId);
|
||||
if (way) {
|
||||
|
||||
@@ -54,9 +54,26 @@ iD.History = function() {
|
||||
change(previous);
|
||||
},
|
||||
|
||||
pop: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
if (index > 0) {
|
||||
index--;
|
||||
stack.pop();
|
||||
change(previous);
|
||||
}
|
||||
},
|
||||
|
||||
undo: function () {
|
||||
var previous = stack[index].graph;
|
||||
|
||||
// Pop to the first annotated state.
|
||||
while (index > 0) {
|
||||
if (stack[index].annotation) break;
|
||||
index--;
|
||||
}
|
||||
|
||||
// Pop to the next annotated state.
|
||||
while (index > 0) {
|
||||
index--;
|
||||
if (stack[index].annotation) break;
|
||||
|
||||
@@ -14,52 +14,40 @@ iD.modes.AddArea = function() {
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function startFromNode(a) {
|
||||
var way = iD.Way({tags: defaultTags}),
|
||||
b = iD.Node({loc: a.loc});
|
||||
function startFromNode(node) {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
'started an area');
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var a = iD.Node({loc: loc}),
|
||||
b = iD.Node({loc: loc}),
|
||||
var node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(a),
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(other.id, a.id, index),
|
||||
'started an area');
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
}
|
||||
|
||||
function start(loc) {
|
||||
var a = iD.Node({loc: loc}),
|
||||
b = iD.Node({loc: loc}),
|
||||
var node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(a),
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
'started an area');
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawArea(way.id));
|
||||
}
|
||||
|
||||
@@ -14,71 +14,49 @@ iD.modes.AddLine = function() {
|
||||
history = mode.history,
|
||||
controller = mode.controller;
|
||||
|
||||
function startFromNode(a) {
|
||||
var b = iD.Node({loc: a.loc}),
|
||||
graph = history.graph(),
|
||||
parent = graph.parentWays(a)[0],
|
||||
function startFromNode(node) {
|
||||
var graph = history.graph(),
|
||||
parent = graph.parentWays(node)[0],
|
||||
isLine = parent && parent.geometry(graph) === 'line';
|
||||
|
||||
if (isLine && parent.first() === a.id) {
|
||||
history.perform(
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddWayNode(parent.id, b.id, 0),
|
||||
'continued a line');
|
||||
|
||||
if (isLine && parent.first() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'backward'));
|
||||
|
||||
} else if (isLine && parent.last() === a.id) {
|
||||
history.perform(
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddWayNode(parent.id, b.id),
|
||||
'continued a line');
|
||||
|
||||
} else if (isLine && parent.last() === node.id) {
|
||||
controller.enter(iD.modes.DrawLine(parent.id, 'forward'));
|
||||
|
||||
} else {
|
||||
var way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
'continued a line');
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward'));
|
||||
}
|
||||
}
|
||||
|
||||
function startFromWay(other, loc, index) {
|
||||
var a = iD.Node({loc: loc}),
|
||||
b = iD.Node({loc: loc}),
|
||||
var node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(a),
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
iD.actions.AddWayNode(other.id, a.id, index),
|
||||
'started a line');
|
||||
iD.actions.AddWayNode(way.id, node.id),
|
||||
iD.actions.AddWayNode(other.id, node.id, index));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward'));
|
||||
}
|
||||
|
||||
function start(loc) {
|
||||
var a = iD.Node({loc: loc}),
|
||||
b = iD.Node({loc: loc}),
|
||||
var node = iD.Node({loc: loc}),
|
||||
way = iD.Way({tags: defaultTags});
|
||||
|
||||
history.perform(
|
||||
iD.actions.AddNode(a),
|
||||
iD.actions.AddNode(b),
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWay(way),
|
||||
iD.actions.AddWayNode(way.id, a.id),
|
||||
iD.actions.AddWayNode(way.id, b.id),
|
||||
'started a line');
|
||||
iD.actions.AddWayNode(way.id, node.id));
|
||||
|
||||
controller.enter(iD.modes.DrawLine(way.id, 'forward'));
|
||||
}
|
||||
|
||||
@@ -8,24 +8,25 @@ iD.modes.DrawArea = function(wayId) {
|
||||
|
||||
mode.enter = function() {
|
||||
var way = mode.history.graph().entity(wayId),
|
||||
index = way.nodes.length - 2,
|
||||
headId = way.nodes[index - 1],
|
||||
tailId = way.first();
|
||||
index = -1,
|
||||
headId = way.nodes[way.nodes.length - 2],
|
||||
tailId = way.first(),
|
||||
annotation = way.isDegenerate() ? 'started an area' : 'continued an area';
|
||||
|
||||
function addHeadTail() {
|
||||
behavior.finish();
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, way.nodes.length > 2 ? 'added to an area' : '');
|
||||
behavior.addNode(node, annotation);
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
behavior.addWay(way, loc, index, way.nodes.length > 2 ? 'added to an area' : '');
|
||||
behavior.addWay(way, loc, index, annotation);
|
||||
}
|
||||
|
||||
function add(loc) {
|
||||
behavior.add(loc, way.nodes.length > 2 ? 'added to an area' : '');
|
||||
behavior.add(loc, annotation);
|
||||
}
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
|
||||
|
||||
@@ -8,9 +8,10 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
|
||||
mode.enter = function() {
|
||||
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();
|
||||
index = (direction === 'forward') ? undefined : 0,
|
||||
headId = (direction === 'forward') ? way.last() : way.first(),
|
||||
tailId = (direction === 'forward') ? way.first() : way.last(),
|
||||
annotation = way.isDegenerate() ? 'started a line' : 'continued a line';
|
||||
|
||||
function addHead() {
|
||||
behavior.finish();
|
||||
@@ -19,22 +20,22 @@ iD.modes.DrawLine = function(wayId, direction) {
|
||||
function addTail(node) {
|
||||
// connect the way in a loop
|
||||
if (way.nodes.length > 2) {
|
||||
behavior.addNode(node, 'added to a line');
|
||||
behavior.addNode(node, annotation);
|
||||
} else {
|
||||
behavior.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function addNode(node) {
|
||||
behavior.addNode(node, 'added to a line');
|
||||
behavior.addNode(node, annotation);
|
||||
}
|
||||
|
||||
function addWay(way, loc, index) {
|
||||
behavior.addWay(way, loc, index, 'added to a line');
|
||||
behavior.addWay(way, loc, index, annotation);
|
||||
}
|
||||
|
||||
function add(loc) {
|
||||
behavior.add(loc, 'added to a line');
|
||||
behavior.add(loc, annotation);
|
||||
}
|
||||
|
||||
behavior = iD.behavior.DrawWay(wayId, headId, tailId, index, mode)
|
||||
|
||||
@@ -70,6 +70,27 @@ describe("iD.History", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#pop", function () {
|
||||
it("updates the graph", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.pop();
|
||||
expect(history.undoAnnotation()).to.be.undefined;
|
||||
});
|
||||
|
||||
it("does not push the redo stack", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.pop();
|
||||
expect(history.redoAnnotation()).to.be.undefined;
|
||||
});
|
||||
|
||||
it("emits a change event", function () {
|
||||
history.perform(action);
|
||||
history.on('change', spy);
|
||||
history.pop();
|
||||
expect(spy).to.have.been.calledWith([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#undo", function () {
|
||||
it("pops the undo stack", function () {
|
||||
history.perform(action, "annotation");
|
||||
@@ -77,6 +98,13 @@ describe("iD.History", function () {
|
||||
expect(history.undoAnnotation()).to.be.undefined;
|
||||
});
|
||||
|
||||
it("pops past unannotated states", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.perform(action);
|
||||
history.undo();
|
||||
expect(history.undoAnnotation()).to.be.undefined;
|
||||
});
|
||||
|
||||
it("pushes the redo stack", function () {
|
||||
history.perform(action, "annotation");
|
||||
history.undo();
|
||||
|
||||
Reference in New Issue
Block a user