mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 01:02:58 +00:00
Trying out radial menus for operations UI (#226)
This commit is contained in:
22
css/app.css
22
css/app.css
@@ -1102,6 +1102,28 @@ div.typeahead a:first-child {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.arc-menu-item {
|
||||
fill: white;
|
||||
stroke: black;
|
||||
stroke-width: 1;
|
||||
cursor:url(../img/cursor-pointer.png) 6 1, auto;
|
||||
}
|
||||
|
||||
.arc-menu-item:hover {
|
||||
fill: #bde5aa;
|
||||
}
|
||||
|
||||
.arc-menu-item:active {
|
||||
fill: #6bc641;
|
||||
}
|
||||
|
||||
.arc-menu-item.disabled {
|
||||
cursor: auto;
|
||||
pointer-events: none;
|
||||
fill: rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
|
||||
/* Media Queries
|
||||
------------------------------------------------------- */
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<script src="js/id/svg/vertices.js"></script>
|
||||
|
||||
<script src="js/id/ui.js"></script>
|
||||
<script src='js/id/ui/arc_menu.js'></script>
|
||||
<script src='js/id/ui/inspector.js'></script>
|
||||
<script src='js/id/ui/modal.js'></script>
|
||||
<script src='js/id/ui/confirm.js'></script>
|
||||
|
||||
@@ -7,7 +7,8 @@ iD.modes.Select = function(entity, initial) {
|
||||
|
||||
var inspector = iD.ui.inspector().initial(!!initial),
|
||||
keybinding = d3.keybinding('select'),
|
||||
behaviors;
|
||||
behaviors,
|
||||
arcMenu;
|
||||
|
||||
function remove() {
|
||||
if (entity.type === 'way') {
|
||||
@@ -32,7 +33,8 @@ iD.modes.Select = function(entity, initial) {
|
||||
}
|
||||
|
||||
mode.enter = function() {
|
||||
var surface = mode.map.surface;
|
||||
var surface = mode.map.surface,
|
||||
history = mode.history;
|
||||
|
||||
behaviors = [
|
||||
iD.behavior.Hover(),
|
||||
@@ -71,32 +73,12 @@ iD.modes.Select = function(entity, initial) {
|
||||
|
||||
inspector
|
||||
.on('changeTags', changeTags)
|
||||
.on('reverseWay', function(d) {
|
||||
mode.history.perform(
|
||||
iD.actions.ReverseWay(d.id),
|
||||
'reversed a way');
|
||||
|
||||
}).on('splitWay', function(d) {
|
||||
mode.history.perform(
|
||||
iD.actions.SplitWay(d.id),
|
||||
'split a way');
|
||||
|
||||
}).on('unjoin', function(d) {
|
||||
mode.history.perform(
|
||||
iD.actions.UnjoinNode(d.id),
|
||||
'unjoined ways');
|
||||
|
||||
}).on('remove', function() {
|
||||
remove();
|
||||
|
||||
}).on('close', function() {
|
||||
mode.controller.exit();
|
||||
});
|
||||
.on('close', function() { mode.controller.exit(); });
|
||||
|
||||
// Exit mode if selected entity gets undone
|
||||
mode.history.on('change.entity-undone', function() {
|
||||
history.on('change.entity-undone', function() {
|
||||
var old = entity;
|
||||
entity = mode.history.graph().entity(entity.id);
|
||||
entity = history.graph().entity(entity.id);
|
||||
if (!entity) {
|
||||
mode.controller.enter(iD.modes.Browse());
|
||||
} else if(!_.isEqual(entity.tags, old.tags)) {
|
||||
@@ -121,7 +103,7 @@ iD.modes.Select = function(entity, initial) {
|
||||
d3.mouse(mode.map.surface.node()), mode.map),
|
||||
node = iD.Node({ loc: choice.loc });
|
||||
|
||||
mode.history.perform(
|
||||
history.perform(
|
||||
iD.actions.AddNode(node),
|
||||
iD.actions.AddWayNode(datum.id, node.id, choice.index),
|
||||
'added a point to a road');
|
||||
@@ -144,10 +126,17 @@ iD.modes.Select = function(entity, initial) {
|
||||
return d && entity && d.id === entity.id;
|
||||
})
|
||||
.classed('selected', true);
|
||||
|
||||
arcMenu = iD.ui.ArcMenu(entity, history);
|
||||
|
||||
if (d3.event) {
|
||||
surface.call(arcMenu, d3.mouse(surface.node()));
|
||||
}
|
||||
};
|
||||
|
||||
mode.exit = function () {
|
||||
var surface = mode.map.surface;
|
||||
var surface = mode.map.surface,
|
||||
history = mode.history;
|
||||
|
||||
if (entity) {
|
||||
changeTags(entity, inspector.tags());
|
||||
@@ -173,10 +162,12 @@ iD.modes.Select = function(entity, initial) {
|
||||
surface.on('click.select', null)
|
||||
.on('dblclick.select', null);
|
||||
|
||||
mode.history.on('change.entity-undone', null);
|
||||
history.on('change.entity-undone', null);
|
||||
|
||||
surface.selectAll(".selected")
|
||||
.classed('selected', false);
|
||||
|
||||
surface.call(arcMenu.close);
|
||||
};
|
||||
|
||||
return mode;
|
||||
|
||||
97
js/id/ui/arc_menu.js
Normal file
97
js/id/ui/arc_menu.js
Normal file
@@ -0,0 +1,97 @@
|
||||
iD.ui.ArcMenu = function(entity, history) {
|
||||
var arcMenu = function(selection, center) {
|
||||
var π = Math.PI;
|
||||
var operations;
|
||||
|
||||
if (entity.geometry() === 'vertex') {
|
||||
operations = [
|
||||
{
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
description: 'deleted a node',
|
||||
action: iD.actions.DeleteNode(entity.id)
|
||||
},
|
||||
{
|
||||
id: 'split',
|
||||
text: 'Split Way',
|
||||
description: 'split a way',
|
||||
action: iD.actions.SplitWay(entity.id)
|
||||
},
|
||||
{
|
||||
id: 'unjoin',
|
||||
text: 'Unjoin',
|
||||
description: 'unjoined lines',
|
||||
action: iD.actions.UnjoinNode(entity.id)
|
||||
}
|
||||
];
|
||||
} else if (entity.geometry() === 'point') {
|
||||
operations = [
|
||||
{
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
description: 'deleted a point',
|
||||
action: iD.actions.DeleteNode(entity.id)
|
||||
}
|
||||
];
|
||||
} else if (entity.geometry() === 'line') {
|
||||
operations = [
|
||||
{
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
description: 'deleted a line',
|
||||
action: iD.actions.DeleteWay(entity.id)
|
||||
},
|
||||
{
|
||||
id: 'reverse',
|
||||
text: 'Reverse',
|
||||
description: 'reversed a way',
|
||||
action: iD.actions.ReverseWay(entity.id)
|
||||
}
|
||||
];
|
||||
} else if (entity.geometry() === 'area') {
|
||||
operations = [
|
||||
{
|
||||
id: 'delete',
|
||||
text: 'Delete',
|
||||
description: 'deleted an area',
|
||||
action: iD.actions.DeleteWay(entity.id)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
var arc = d3.svg.arc()
|
||||
.outerRadius(70)
|
||||
.innerRadius(30)
|
||||
.startAngle(function (d, i) { return 2 * Math.PI / operations.length * i; })
|
||||
.endAngle(function (d, i) { return 2 * Math.PI / operations.length * (i + 1); });
|
||||
|
||||
var arcs = selection.selectAll('.arc-menu')
|
||||
.data(operations)
|
||||
.enter().append('g')
|
||||
.attr('class', 'arc-menu')
|
||||
.attr('transform', "translate(" + center + ")")
|
||||
.attr('opacity', 0);
|
||||
|
||||
arcs.transition()
|
||||
.attr('opacity', 0.8);
|
||||
|
||||
arcs.append('path')
|
||||
.attr('class', function (d) { return 'arc-menu-item arc-menu-item-' + d.id; })
|
||||
.attr('d', arc)
|
||||
.classed('disabled', function (d) { return !d.action.enabled(history.graph()); })
|
||||
.on('click', function (d) { history.perform(d.action, d.description); });
|
||||
|
||||
arcs.append('text')
|
||||
.attr("transform", function(d, i) { return "translate(" + arc.centroid(d, i) + ")"; })
|
||||
.attr("dy", ".35em")
|
||||
.style("text-anchor", "middle")
|
||||
.text(function(d) { return d.text; });
|
||||
};
|
||||
|
||||
arcMenu.close = function(selection) {
|
||||
selection.selectAll('.arc-menu')
|
||||
.remove();
|
||||
};
|
||||
|
||||
return arcMenu;
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
iD.ui.inspector = function() {
|
||||
var event = d3.dispatch('changeTags', 'reverseWay',
|
||||
'update', 'remove', 'close', 'splitWay', 'unjoin'),
|
||||
var event = d3.dispatch('changeTags', 'close'),
|
||||
taginfo = iD.taginfo(),
|
||||
initial = false,
|
||||
tagList;
|
||||
@@ -69,39 +68,12 @@ iD.ui.inspector = function() {
|
||||
inspectorButton1.append('span').attr('class','icon icon-pre-text apply');
|
||||
inspectorButton1.append('span').attr('class','label').text('Okay');
|
||||
|
||||
var inspectorButton2 = inspectorButtonWrap.append('button')
|
||||
.attr('class', 'delete col6 action')
|
||||
.on('click', function(entity) { event.remove(entity); });
|
||||
|
||||
inspectorButton2.append('span').attr('class','icon icon-pre-text delete');
|
||||
inspectorButton2.append('span').attr('class','label').text('Delete');
|
||||
|
||||
var minorButtons = selection.append('div').attr('class','minor-buttons fl');
|
||||
|
||||
minorButtons.append('a')
|
||||
.attr('href', 'http://www.openstreetmap.org/browse/' + entity.type + '/' + entity.osmId())
|
||||
.attr('target', '_blank')
|
||||
.text('View on OSM');
|
||||
|
||||
if (entity.type === 'way') {
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Reverse Direction')
|
||||
.on('click', function() { event.reverseWay(entity); });
|
||||
}
|
||||
|
||||
if (entity.geometry() === 'vertex') {
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Split Way')
|
||||
.on('click', function() { event.splitWay(entity); });
|
||||
|
||||
minorButtons.append('a')
|
||||
.attr('href', '#')
|
||||
.text('Unjoin')
|
||||
.on('click', function() { event.unjoin(entity); });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function drawTags(tags) {
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
<script src="../js/id/svg/vertices.js"></script>
|
||||
|
||||
<script src='../js/id/ui.js'></script>
|
||||
<script src='../js/id/ui/arc_menu.js'></script>
|
||||
<script src='../js/id/ui/inspector.js'></script>
|
||||
<script src='../js/id/ui/commit.js'></script>
|
||||
<script src='../js/id/ui/loading.js'></script>
|
||||
|
||||
Reference in New Issue
Block a user