Trying out radial menus for operations UI (#226)

This commit is contained in:
John Firebaugh
2013-01-23 15:30:19 -05:00
parent 72618574f3
commit d6d1709e7b
6 changed files with 141 additions and 57 deletions

View File

@@ -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
------------------------------------------------------- */

View File

@@ -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>

View File

@@ -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
View 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;
};

View File

@@ -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) {

View File

@@ -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>