mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-12 16:52:50 +00:00
14
index.html
14
index.html
@@ -49,8 +49,8 @@
|
||||
<script type='text/javascript' src='js/iD/renderer/markers.js'></script>
|
||||
<script type='text/javascript' src='js/iD/ui/Inspector.js'></script>
|
||||
|
||||
<script type='text/javascript' src='js/iD/actions/modes.js'></script>
|
||||
<script type='text/javascript' src='js/iD/actions/actions.js'></script>
|
||||
<script type='text/javascript' src='js/iD/actions/operations.js'></script>
|
||||
|
||||
<script type='text/javascript' src='js/iD/controller/Controller.js'></script>
|
||||
|
||||
@@ -98,15 +98,15 @@
|
||||
});
|
||||
|
||||
d3.selectAll('button#place').on('click', function() {
|
||||
controller.go(iD.actions.AddPlace);
|
||||
controller.enter(iD.modes.AddPlace);
|
||||
});
|
||||
|
||||
d3.selectAll('button#road').on('click', function() {
|
||||
controller.go(iD.actions.AddRoad);
|
||||
controller.enter(iD.modes.AddRoad);
|
||||
});
|
||||
|
||||
d3.selectAll('button#area').on('click', function() {
|
||||
controller.go(iD.actions.AddArea);
|
||||
controller.enter(iD.modes.AddArea);
|
||||
});
|
||||
|
||||
window.onresize = function() {
|
||||
@@ -146,11 +146,11 @@
|
||||
map.redo();
|
||||
}
|
||||
// p
|
||||
if (d3.event.which === 80) controller.go(iD.actions.AddPlace);
|
||||
if (d3.event.which === 80) controller.enter(iD.modes.AddPlace);
|
||||
// r
|
||||
if (d3.event.which === 82) controller.go(iD.actions.AddRoad);
|
||||
if (d3.event.which === 82) controller.enter(iD.modes.AddRoad);
|
||||
// a
|
||||
if (d3.event.which === 65) controller.go(iD.actions.AddArea);
|
||||
if (d3.event.which === 65) controller.enter(iD.modes.AddArea);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -1,304 +1,67 @@
|
||||
iD.actions = {};
|
||||
|
||||
// Actions are like 'modes' for the editor. They are entered by bindings to
|
||||
// clicks and keypresses, and exited by the same.
|
||||
//
|
||||
// Actions aim to include a bare minimum of 'business logic' - this is separated
|
||||
// into operations.
|
||||
|
||||
iD.actions._node = function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'node',
|
||||
lat: ll[1],
|
||||
lon: ll[0],
|
||||
id: iD.Util.id('node'),
|
||||
tags: {}
|
||||
}, {});
|
||||
};
|
||||
|
||||
iD.actions.AddPlace = {
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#place').classed('active', true);
|
||||
|
||||
var surface = this.map.surface;
|
||||
var teaser = surface.selectAll('g#temp-g')
|
||||
.append('g').attr('id', 'addplace');
|
||||
|
||||
teaser.append('circle')
|
||||
.attr('class', 'handle')
|
||||
.attr('r', 3);
|
||||
|
||||
surface.on('mousemove.addplace', function() {
|
||||
teaser.attr('transform', function() {
|
||||
var off = d3.mouse(surface.node());
|
||||
return 'translate(' + off + ')';
|
||||
});
|
||||
});
|
||||
|
||||
surface.on('click.addplace', function() {
|
||||
var ll = this.map.projection.invert(
|
||||
d3.mouse(surface.node()));
|
||||
var n = iD.actions._node(ll);
|
||||
n._poi = true;
|
||||
this.map.operate(iD.operations.addNode(n));
|
||||
this.map.selectClick(n);
|
||||
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('mousemove.addplace', null);
|
||||
this.map.surface.on('click.addplace', null);
|
||||
d3.select(document).on('keydown.addplace', null);
|
||||
d3.selectAll('#addplace').remove();
|
||||
d3.selectAll('button#place').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.actions.AddRoad = {
|
||||
way: function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'way',
|
||||
nodes: [],
|
||||
tags: {
|
||||
highway: 'residential'
|
||||
},
|
||||
modified: true,
|
||||
id: iD.Util.id('way')
|
||||
});
|
||||
},
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#road').classed('active', true);
|
||||
|
||||
var surface = this.map.surface;
|
||||
this.map.handleDrag(false);
|
||||
var teaser = surface.selectAll('g#temp-g')
|
||||
.append('g').attr('id', 'addroad');
|
||||
|
||||
teaser.append('circle')
|
||||
.attr('class', 'handle')
|
||||
.style('pointer-events', 'none')
|
||||
.attr('r', 3);
|
||||
|
||||
surface.on('mousemove.addroad', function() {
|
||||
teaser.attr('transform', function() {
|
||||
var off = d3.mouse(surface.node());
|
||||
return 'translate(' + off + ')';
|
||||
});
|
||||
});
|
||||
|
||||
surface.on('click.addroad', function() {
|
||||
var t = d3.select(d3.event.target);
|
||||
var node;
|
||||
var way = this.way();
|
||||
|
||||
// connect a way to an existing way
|
||||
if (t.data() && t.data()[0] && t.data()[0].type === 'node') {
|
||||
node = t.data()[0];
|
||||
} else {
|
||||
node = iD.actions._node(this.map.projection.invert(
|
||||
d3.mouse(surface.node())));
|
||||
}
|
||||
|
||||
way.nodes.push(node.id);
|
||||
this.map.operate(iD.operations.changeWayNodes(way, node));
|
||||
this.map.selectClick(way);
|
||||
this.controller.go(iD.actions.DrawRoad(way));
|
||||
}.bind(this));
|
||||
|
||||
d3.select(document).on('keydown.addroad', function() {
|
||||
if (d3.event.keyCode === 27) this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('click.addroad', null);
|
||||
this.map.surface.on('mousemove.addroad', null);
|
||||
this.map.handleDrag(true);
|
||||
d3.select(document).on('keydown.addroad', null);
|
||||
d3.selectAll('#addroad').remove();
|
||||
d3.selectAll('button#road').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.actions.DrawRoad = function(way) {
|
||||
return {
|
||||
enter: function() {
|
||||
var surface = this.map.surface;
|
||||
var lastNode = this.map.history.graph().entity(way.nodes[way.nodes.length - 1]);
|
||||
this.nextnode = iD.actions._node([lastNode.lon, lastNode.lat]);
|
||||
way.nodes.push(this.nextnode.id);
|
||||
this.map.operate(iD.operations.changeWayNodes(way, this.nextnode));
|
||||
|
||||
surface.on('mousemove.drawroad', function() {
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
this.map.history.replace(iD.operations.move(this.nextnode, ll));
|
||||
this.map.update();
|
||||
}.bind(this));
|
||||
|
||||
surface.on('click.drawroad', function() {
|
||||
if (this._doubleTime) {
|
||||
window.clearTimeout(this._doubleTime);
|
||||
this._doubleTime = null;
|
||||
} else {
|
||||
// forgive me
|
||||
var that = this;
|
||||
this._doubleTime = window.setTimeout(function(e) {
|
||||
return function() {
|
||||
d3.event = e;
|
||||
var t = d3.select(d3.event.target);
|
||||
d3.event.stopPropagation();
|
||||
// connect a way to an existing way
|
||||
if (t.data() && t.data()[0] && t.data()[0].type === 'node') {
|
||||
node = t.data()[0];
|
||||
} else {
|
||||
node = iD.actions._node(that.map.projection.invert(
|
||||
d3.mouse(surface.node())));
|
||||
}
|
||||
way.nodes.pop();
|
||||
way.nodes.push(node.id);
|
||||
that.map.operate(iD.operations.changeWayNodes(way, node));
|
||||
way.nodes = way.nodes.slice();
|
||||
that.controller.go(iD.actions.DrawRoad(way));
|
||||
};
|
||||
}(_.clone(d3.event)), 150);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
surface.on('dblclick.drawroad', function() {
|
||||
d3.event.stopPropagation();
|
||||
this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('mousemove.drawroad', null);
|
||||
this.map.surface.on('click.drawroad', null);
|
||||
this.map.surface.on('dblclick.drawroad', null);
|
||||
d3.select(document).on('.drawroad', null);
|
||||
d3.selectAll('#drawroad').remove();
|
||||
}
|
||||
iD.actions.noop = function() {
|
||||
return function(graph) {
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
|
||||
iD.actions.AddArea = {
|
||||
way: function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'way',
|
||||
nodes: [],
|
||||
tags: {
|
||||
building: 'yes'
|
||||
},
|
||||
modified: true,
|
||||
id: iD.Util.id('way')
|
||||
});
|
||||
},
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#area').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', 'handle')
|
||||
.attr('r', 3);
|
||||
|
||||
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 = iD.actions._node(ll);
|
||||
way.nodes.push(node.id);
|
||||
|
||||
this.map.operate(iD.operations.changeWayNodes(way, node));
|
||||
this.map.selectClick(way);
|
||||
this.controller.go(iD.actions.DrawArea(way));
|
||||
}.bind(this));
|
||||
|
||||
d3.select(document).on('keydown.addroad', function() {
|
||||
if (d3.event.keyCode === 27) this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('click.addarea', null);
|
||||
this.map.surface.on('mousemove.addarea', null);
|
||||
d3.select(document).on('keydown.addarea', null);
|
||||
d3.selectAll('#addroad').remove();
|
||||
d3.selectAll('button#area').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.actions.DrawArea = function(way) {
|
||||
return {
|
||||
enter: function() {
|
||||
var surface = this.map.surface;
|
||||
|
||||
var lastNode = this.map.history.graph().entity(way.nodes[way.nodes.length - 1]);
|
||||
var firstNode = this.map.history.graph().entity(way.nodes[0]);
|
||||
|
||||
this.nextnode = iD.actions._node([lastNode.lon, lastNode.lat]);
|
||||
|
||||
way.nodes.push(this.nextnode.id);
|
||||
way.nodes.push(firstNode.id);
|
||||
this.map.operate(iD.operations.changeWayNodes(way, this.nextnode));
|
||||
this.map.operate(iD.operations.changeWayNodes(way, firstNode));
|
||||
|
||||
surface.on('mousemove.drawarea', function() {
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
this.map.history.replace(iD.operations.move(this.nextnode, ll));
|
||||
this.map.update();
|
||||
}.bind(this));
|
||||
|
||||
surface.on('click.drawarea', function() {
|
||||
d3.event.stopPropagation();
|
||||
way.nodes.pop();
|
||||
way.nodes.pop();
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
var node = iD.actions._node(ll);
|
||||
way.nodes.push(node.id);
|
||||
this.map.operate(iD.operations.changeWayNodes(way, node));
|
||||
this.controller.go(iD.actions.DrawRoad(way));
|
||||
}.bind(this));
|
||||
|
||||
surface.on('dblclick.drawarea', function() {
|
||||
d3.event.stopPropagation();
|
||||
var a = this.map.history.graph().entity(way.nodes.pop());
|
||||
var b = this.map.history.graph().entity(way.nodes.pop());
|
||||
this.map.operate(iD.operations.changeWayNodes(way, a));
|
||||
this.map.operate(iD.operations.remove(a));
|
||||
this.map.operate(iD.operations.remove(b));
|
||||
way.nodes.push(way.nodes[0]);
|
||||
var closeNode = this.map.history.graph().entity(way.nodes[0]);
|
||||
this.map.operate(iD.operations.changeWayNodes(way, closeNode));
|
||||
this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('mousemove.drawarea', null);
|
||||
this.map.surface.on('click.drawarea', null);
|
||||
this.map.surface.on('dblclick.drawarea', null);
|
||||
d3.select(document).on('.drawarea', null);
|
||||
d3.selectAll('#drawarea').remove();
|
||||
}
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/AddCommand.java
|
||||
iD.actions.addNode = function(node) {
|
||||
return function(graph) {
|
||||
return graph.replace(node, 'added a place');
|
||||
};
|
||||
};
|
||||
|
||||
iD.actions.Move = {
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
},
|
||||
exit: function() { }
|
||||
iD.actions.startWay = function(way) {
|
||||
return function(graph) {
|
||||
return graph.replace(way, 'started a road');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
|
||||
iD.actions.remove = function(node) {
|
||||
return function(graph) {
|
||||
return graph.remove(node, 'removed a feature');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
|
||||
iD.actions.changeWayNodes = function(way, node) {
|
||||
return function(graph) {
|
||||
return graph.replace(way.update({
|
||||
nodes: way.nodes.slice()
|
||||
})).replace(node, 'added to a road');
|
||||
};
|
||||
};
|
||||
|
||||
iD.actions.changeTags = function(node, tags) {
|
||||
return function(graph) {
|
||||
return graph.replace(node.update({
|
||||
tags: tags
|
||||
}), 'changed tags');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
|
||||
iD.actions.move = function(entity, to) {
|
||||
return function(graph) {
|
||||
return graph.replace(entity.update({
|
||||
lon: to.lon || to[0],
|
||||
lat: to.lat || to[1]
|
||||
}), 'moved an element');
|
||||
};
|
||||
};
|
||||
|
||||
iD.actions.addTemporary = function(node) {
|
||||
return function(graph) {
|
||||
return graph.replace(node);
|
||||
};
|
||||
};
|
||||
|
||||
iD.actions.removeTemporary = function(node) {
|
||||
return function(graph) {
|
||||
return graph.remove(node);
|
||||
};
|
||||
};
|
||||
|
||||
303
js/iD/actions/modes.js
Normal file
303
js/iD/actions/modes.js
Normal file
@@ -0,0 +1,303 @@
|
||||
iD.modes = {};
|
||||
|
||||
// Modes are entered by bindings to clicks and keypresses, and exited by the same.
|
||||
//
|
||||
// Modes aim to include a bare minimum of 'business logic' - this is separated
|
||||
// into actions.
|
||||
|
||||
iD.modes._node = function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'node',
|
||||
lat: ll[1],
|
||||
lon: ll[0],
|
||||
id: iD.Util.id('node'),
|
||||
tags: {}
|
||||
}, {});
|
||||
};
|
||||
|
||||
iD.modes.AddPlace = {
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#place').classed('active', true);
|
||||
|
||||
var surface = this.map.surface;
|
||||
var teaser = surface.selectAll('g#temp-g')
|
||||
.append('g').attr('id', 'addplace');
|
||||
|
||||
teaser.append('circle')
|
||||
.attr('class', 'handle')
|
||||
.attr('r', 3);
|
||||
|
||||
surface.on('mousemove.addplace', function() {
|
||||
teaser.attr('transform', function() {
|
||||
var off = d3.mouse(surface.node());
|
||||
return 'translate(' + off + ')';
|
||||
});
|
||||
});
|
||||
|
||||
surface.on('click.addplace', function() {
|
||||
var ll = this.map.projection.invert(
|
||||
d3.mouse(surface.node()));
|
||||
var n = iD.modes._node(ll);
|
||||
n._poi = true;
|
||||
this.map.perform(iD.actions.addNode(n));
|
||||
this.map.selectClick(n);
|
||||
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('mousemove.addplace', null);
|
||||
this.map.surface.on('click.addplace', null);
|
||||
d3.select(document).on('keydown.addplace', null);
|
||||
d3.selectAll('#addplace').remove();
|
||||
d3.selectAll('button#place').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.modes.AddRoad = {
|
||||
way: function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'way',
|
||||
nodes: [],
|
||||
tags: {
|
||||
highway: 'residential'
|
||||
},
|
||||
modified: true,
|
||||
id: iD.Util.id('way')
|
||||
});
|
||||
},
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#road').classed('active', true);
|
||||
|
||||
var surface = this.map.surface;
|
||||
this.map.handleDrag(false);
|
||||
var teaser = surface.selectAll('g#temp-g')
|
||||
.append('g').attr('id', 'addroad');
|
||||
|
||||
teaser.append('circle')
|
||||
.attr('class', 'handle')
|
||||
.style('pointer-events', 'none')
|
||||
.attr('r', 3);
|
||||
|
||||
surface.on('mousemove.addroad', function() {
|
||||
teaser.attr('transform', function() {
|
||||
var off = d3.mouse(surface.node());
|
||||
return 'translate(' + off + ')';
|
||||
});
|
||||
});
|
||||
|
||||
surface.on('click.addroad', function() {
|
||||
var t = d3.select(d3.event.target);
|
||||
var node;
|
||||
var way = this.way();
|
||||
|
||||
// connect a way to an existing way
|
||||
if (t.data() && t.data()[0] && t.data()[0].type === 'node') {
|
||||
node = t.data()[0];
|
||||
} else {
|
||||
node = iD.modes._node(this.map.projection.invert(
|
||||
d3.mouse(surface.node())));
|
||||
}
|
||||
|
||||
way.nodes.push(node.id);
|
||||
this.map.perform(iD.actions.changeWayNodes(way, node));
|
||||
this.map.selectClick(way);
|
||||
this.controller.enter(iD.modes.DrawRoad(way));
|
||||
}.bind(this));
|
||||
|
||||
d3.select(document).on('keydown.addroad', function() {
|
||||
if (d3.event.keyCode === 27) this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('click.addroad', null);
|
||||
this.map.surface.on('mousemove.addroad', null);
|
||||
this.map.handleDrag(true);
|
||||
d3.select(document).on('keydown.addroad', null);
|
||||
d3.selectAll('#addroad').remove();
|
||||
d3.selectAll('button#road').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.modes.DrawRoad = function(way) {
|
||||
return {
|
||||
enter: function() {
|
||||
var surface = this.map.surface;
|
||||
var lastNode = this.map.history.graph().entity(way.nodes[way.nodes.length - 1]);
|
||||
this.nextnode = iD.modes._node([lastNode.lon, lastNode.lat]);
|
||||
way.nodes.push(this.nextnode.id);
|
||||
this.map.perform(iD.actions.changeWayNodes(way, this.nextnode));
|
||||
|
||||
surface.on('mousemove.drawroad', function() {
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
this.map.history.replace(iD.actions.move(this.nextnode, ll));
|
||||
this.map.update();
|
||||
}.bind(this));
|
||||
|
||||
surface.on('click.drawroad', function() {
|
||||
if (this._doubleTime) {
|
||||
window.clearTimeout(this._doubleTime);
|
||||
this._doubleTime = null;
|
||||
} else {
|
||||
// forgive me
|
||||
var that = this;
|
||||
this._doubleTime = window.setTimeout(function(e) {
|
||||
return function() {
|
||||
d3.event = e;
|
||||
var t = d3.select(d3.event.target);
|
||||
d3.event.stopPropagation();
|
||||
// connect a way to an existing way
|
||||
if (t.data() && t.data()[0] && t.data()[0].type === 'node') {
|
||||
node = t.data()[0];
|
||||
} else {
|
||||
node = iD.modes._node(that.map.projection.invert(
|
||||
d3.mouse(surface.node())));
|
||||
}
|
||||
way.nodes.pop();
|
||||
way.nodes.push(node.id);
|
||||
that.map.perform(iD.actions.changeWayNodes(way, node));
|
||||
way.nodes = way.nodes.slice();
|
||||
that.controller.enter(iD.modes.DrawRoad(way));
|
||||
};
|
||||
}(_.clone(d3.event)), 150);
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
surface.on('dblclick.drawroad', function() {
|
||||
d3.event.stopPropagation();
|
||||
this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('mousemove.drawroad', null);
|
||||
this.map.surface.on('click.drawroad', null);
|
||||
this.map.surface.on('dblclick.drawroad', null);
|
||||
d3.select(document).on('.drawroad', null);
|
||||
d3.selectAll('#drawroad').remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
iD.modes.AddArea = {
|
||||
way: function(ll) {
|
||||
return iD.Entity({
|
||||
type: 'way',
|
||||
nodes: [],
|
||||
tags: {
|
||||
building: 'yes'
|
||||
},
|
||||
modified: true,
|
||||
id: iD.Util.id('way')
|
||||
});
|
||||
},
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
d3.selectAll('button#area').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', 'handle')
|
||||
.attr('r', 3);
|
||||
|
||||
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 = iD.modes._node(ll);
|
||||
way.nodes.push(node.id);
|
||||
|
||||
this.map.perform(iD.actions.changeWayNodes(way, node));
|
||||
this.map.selectClick(way);
|
||||
this.controller.enter(iD.modes.DrawArea(way));
|
||||
}.bind(this));
|
||||
|
||||
d3.select(document).on('keydown.addroad', function() {
|
||||
if (d3.event.keyCode === 27) this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('click.addarea', null);
|
||||
this.map.surface.on('mousemove.addarea', null);
|
||||
d3.select(document).on('keydown.addarea', null);
|
||||
d3.selectAll('#addroad').remove();
|
||||
d3.selectAll('button#area').classed('active', false);
|
||||
}
|
||||
};
|
||||
|
||||
iD.modes.DrawArea = function(way) {
|
||||
return {
|
||||
enter: function() {
|
||||
var surface = this.map.surface;
|
||||
|
||||
var lastNode = this.map.history.graph().entity(way.nodes[way.nodes.length - 1]);
|
||||
var firstNode = this.map.history.graph().entity(way.nodes[0]);
|
||||
|
||||
this.nextnode = iD.modes._node([lastNode.lon, lastNode.lat]);
|
||||
|
||||
way.nodes.push(this.nextnode.id);
|
||||
way.nodes.push(firstNode.id);
|
||||
this.map.perform(iD.actions.changeWayNodes(way, this.nextnode));
|
||||
this.map.perform(iD.actions.changeWayNodes(way, firstNode));
|
||||
|
||||
surface.on('mousemove.drawarea', function() {
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
this.map.history.replace(iD.actions.move(this.nextnode, ll));
|
||||
this.map.update();
|
||||
}.bind(this));
|
||||
|
||||
surface.on('click.drawarea', function() {
|
||||
d3.event.stopPropagation();
|
||||
way.nodes.pop();
|
||||
way.nodes.pop();
|
||||
var ll = this.map.projection.invert(d3.mouse(surface.node()));
|
||||
var node = iD.modes._node(ll);
|
||||
way.nodes.push(node.id);
|
||||
this.map.perform(iD.actions.changeWayNodes(way, node));
|
||||
this.controller.enter(iD.modes.DrawRoad(way));
|
||||
}.bind(this));
|
||||
|
||||
surface.on('dblclick.drawarea', function() {
|
||||
d3.event.stopPropagation();
|
||||
var a = this.map.history.graph().entity(way.nodes.pop());
|
||||
var b = this.map.history.graph().entity(way.nodes.pop());
|
||||
this.map.perform(iD.actions.changeWayNodes(way, a));
|
||||
this.map.perform(iD.actions.remove(a));
|
||||
this.map.perform(iD.actions.remove(b));
|
||||
way.nodes.push(way.nodes[0]);
|
||||
var closeNode = this.map.history.graph().entity(way.nodes[0]);
|
||||
this.map.perform(iD.actions.changeWayNodes(way, closeNode));
|
||||
this.exit();
|
||||
}.bind(this));
|
||||
},
|
||||
exit: function() {
|
||||
this.map.surface.on('mousemove.drawarea', null);
|
||||
this.map.surface.on('click.drawarea', null);
|
||||
this.map.surface.on('dblclick.drawarea', null);
|
||||
d3.select(document).on('.drawarea', null);
|
||||
d3.selectAll('#drawarea').remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
iD.modes.Move = {
|
||||
enter: function() {
|
||||
d3.selectAll('button').classed('active', false);
|
||||
},
|
||||
exit: function() { }
|
||||
};
|
||||
@@ -1,67 +0,0 @@
|
||||
iD.operations = {};
|
||||
|
||||
iD.operations.noop = function() {
|
||||
return function(graph) {
|
||||
return graph;
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/AddCommand.java
|
||||
iD.operations.addNode = function(node) {
|
||||
return function(graph) {
|
||||
return graph.replace(node, 'added a place');
|
||||
};
|
||||
};
|
||||
|
||||
iD.operations.startWay = function(way) {
|
||||
return function(graph) {
|
||||
return graph.replace(way, 'started a road');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
|
||||
iD.operations.remove = function(node) {
|
||||
return function(graph) {
|
||||
return graph.remove(node, 'removed a feature');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
|
||||
iD.operations.changeWayNodes = function(way, node) {
|
||||
return function(graph) {
|
||||
return graph.replace(way.update({
|
||||
nodes: way.nodes.slice()
|
||||
})).replace(node, 'added to a road');
|
||||
};
|
||||
};
|
||||
|
||||
iD.operations.changeTags = function(node, tags) {
|
||||
return function(graph) {
|
||||
return graph.replace(node.update({
|
||||
tags: tags
|
||||
}), 'changed tags');
|
||||
};
|
||||
};
|
||||
|
||||
// https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
|
||||
// https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
|
||||
iD.operations.move = function(entity, to) {
|
||||
return function(graph) {
|
||||
return graph.replace(entity.update({
|
||||
lon: to.lon || to[0],
|
||||
lat: to.lat || to[1]
|
||||
}), 'moved an element');
|
||||
};
|
||||
};
|
||||
|
||||
iD.operations.addTemporary = function(node) {
|
||||
return function(graph) {
|
||||
return graph.replace(node);
|
||||
};
|
||||
};
|
||||
|
||||
iD.operations.removeTemporary = function(node) {
|
||||
return function(graph) {
|
||||
return graph.remove(node);
|
||||
};
|
||||
};
|
||||
@@ -1,19 +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) {
|
||||
var controller = { action: null };
|
||||
var controller = { mode: null };
|
||||
|
||||
controller.go = function(x) {
|
||||
x.controller = controller;
|
||||
x.map = map;
|
||||
if (controller.action) {
|
||||
controller.action.exit();
|
||||
controller.enter = function(mode) {
|
||||
mode.controller = controller;
|
||||
mode.map = map;
|
||||
if (controller.mode) {
|
||||
controller.mode.exit();
|
||||
}
|
||||
x.enter();
|
||||
controller.action = x;
|
||||
mode.enter();
|
||||
controller.mode = mode;
|
||||
};
|
||||
|
||||
controller.go(iD.actions.Move);
|
||||
controller.enter(iD.modes.Move);
|
||||
|
||||
return controller;
|
||||
};
|
||||
|
||||
@@ -15,15 +15,15 @@ iD.History.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
operate: function(operation) {
|
||||
perform: function(action) {
|
||||
this.stack = this.stack.slice(0, this.index + 1);
|
||||
this.stack.push(operation(this.graph()));
|
||||
this.stack.push(action(this.graph()));
|
||||
this.index++;
|
||||
},
|
||||
|
||||
replace: function(operation) {
|
||||
replace: function(action) {
|
||||
// assert(this.index == this.stack.length - 1)
|
||||
this.stack[this.index] = operation(this.graph());
|
||||
this.stack[this.index] = action(this.graph());
|
||||
},
|
||||
|
||||
undo: function() {
|
||||
|
||||
@@ -31,11 +31,11 @@ iD.Map = function(elem) {
|
||||
return { x: p[0], y: p[1] };
|
||||
})
|
||||
.on('dragstart', function() {
|
||||
history.operate(iD.operations.noop());
|
||||
history.perform(iD.actions.noop());
|
||||
})
|
||||
.on('drag', function(entity) {
|
||||
var to = projection.invert([d3.event.x, d3.event.y]);
|
||||
history.replace(iD.operations.move(entity, to));
|
||||
history.replace(iD.actions.move(entity, to));
|
||||
var only = {};
|
||||
only[entity.id] = true;
|
||||
redraw(only);
|
||||
@@ -392,11 +392,11 @@ iD.Map = function(elem) {
|
||||
}
|
||||
|
||||
inspector.on('change', function(d, tags) {
|
||||
map.operate(iD.operations.changeTags(d, tags));
|
||||
map.perform(iD.actions.changeTags(d, tags));
|
||||
});
|
||||
|
||||
inspector.on('remove', function(d) {
|
||||
map.operate(iD.operations.remove(d));
|
||||
map.perform(iD.actions.remove(d));
|
||||
hideInspector();
|
||||
});
|
||||
|
||||
@@ -453,8 +453,8 @@ iD.Map = function(elem) {
|
||||
redraw();
|
||||
});
|
||||
|
||||
function _do(operation) {
|
||||
history.operate(operation);
|
||||
function perform(action) {
|
||||
history.perform(action);
|
||||
map.update();
|
||||
}
|
||||
|
||||
@@ -591,7 +591,7 @@ iD.Map = function(elem) {
|
||||
map.history = history;
|
||||
map.surface = surface;
|
||||
|
||||
map.operate = _do;
|
||||
map.perform = perform;
|
||||
map.undo = undo;
|
||||
map.redo = redo;
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
<script type='text/javascript' src='../js/iD/renderer/markers.js'></script>
|
||||
<script type='text/javascript' src='../js/iD/ui/Inspector.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../js/iD/actions/modes.js'></script>
|
||||
<script type='text/javascript' src='../js/iD/actions/actions.js'></script>
|
||||
<script type='text/javascript' src='../js/iD/actions/operations.js'></script>
|
||||
|
||||
<script type='text/javascript' src='../js/iD/controller/Controller.js'></script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user