From 8a215cac81a88e2346ac0e0fbe4f55140d1845cc Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 22 Aug 2013 16:31:53 -0700 Subject: [PATCH] Add "Continue" operation --- data/core.yaml | 5 ++++ dist/locales/en.json | 5 ++++ index.html | 1 + js/id/modes/add_line.js | 22 ++++------------ js/id/operations/continue.js | 49 ++++++++++++++++++++++++++++++++++++ js/id/renderer/map.js | 9 +++++-- js/id/ui/radial_menu.js | 28 +++++++++++++++++---- test/index.html | 1 + 8 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 js/id/operations/continue.js diff --git a/data/core.yaml b/data/core.yaml index c56ef12c6..7d83f6c62 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -31,6 +31,11 @@ en: line: Started a line. area: Started an area. continue: + key: A + title: Continue + description: Continue this line. + not_eligible: No line can be continued here. + multiple: Several lines can be continued here. To choose a line, press the Shift key and click on it to select it. annotation: line: Continued a line. area: Continued an area. diff --git a/dist/locales/en.json b/dist/locales/en.json index 8f702b2a6..e57b6866c 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -41,6 +41,11 @@ } }, "continue": { + "key": "A", + "title": "Continue", + "description": "Continue this line.", + "not_eligible": "No line can be continued here.", + "multiple": "Several lines can be continued here. To choose a line, press the Shift key and click on it to select it.", "annotation": { "line": "Continued a line.", "area": "Continued an area." diff --git a/index.html b/index.html index 6fc21254d..ed2335394 100644 --- a/index.html +++ b/index.html @@ -174,6 +174,7 @@ + diff --git a/js/id/modes/add_line.js b/js/id/modes/add_line.js index 265389db5..537844701 100644 --- a/js/id/modes/add_line.js +++ b/js/id/modes/add_line.js @@ -41,25 +41,13 @@ iD.modes.AddLine = function(context) { } function startFromNode(node) { - var graph = context.graph(), - parent = graph.parentWays(node)[0], - isLine = parent && parent.geometry(graph) === 'line'; + var way = iD.Way(); - if (isLine && parent.first() === node.id) { - context.enter(iD.modes.DrawLine(context, parent.id, 'backward', graph)); + context.perform( + iD.actions.AddEntity(way), + iD.actions.AddVertex(way.id, node.id)); - } else if (isLine && parent.last() === node.id) { - context.enter(iD.modes.DrawLine(context, parent.id, 'forward', graph)); - - } else { - var way = iD.Way(); - - context.perform( - iD.actions.AddEntity(way), - iD.actions.AddVertex(way.id, node.id)); - - context.enter(iD.modes.DrawLine(context, way.id, 'forward', graph)); - } + context.enter(iD.modes.DrawLine(context, way.id, 'forward', context.graph())); } mode.enter = function() { diff --git a/js/id/operations/continue.js b/js/id/operations/continue.js new file mode 100644 index 000000000..34a1d61ba --- /dev/null +++ b/js/id/operations/continue.js @@ -0,0 +1,49 @@ +iD.operations.Continue = function(selectedIDs, context) { + var graph = context.graph(), + entities = selectedIDs.map(function(id) { return graph.entity(id); }), + geometries = _.extend({line: [], vertex: []}, + _.groupBy(entities, function(entity) { return entity.geometry(graph); })), + vertex = geometries.vertex[0]; + + function candidateWays() { + return graph.parentWays(vertex).filter(function(parent) { + return parent.geometry(graph) === 'line' && + (parent.first() === vertex.id || parent.last() === vertex.id) && + (geometries.line.length === 0 || geometries.line[0] === parent); + }); + } + + var operation = function() { + var candidate = candidateWays()[0]; + context.enter(iD.modes.DrawLine( + context, + candidate.id, + candidate.first() === vertex.id ? 'backward' : 'forward', + context.graph())); + }; + + operation.available = function() { + return geometries.vertex.length === 1 && geometries.line.length <= 1; + }; + + operation.disabled = function() { + var candidates = candidateWays(); + if (candidates.length === 0) + return 'not_eligible'; + if (candidates.length > 1) + return 'multiple'; + }; + + operation.tooltip = function() { + var disable = operation.disabled(); + return disable ? + t('operations.continue.' + disable) : + t('operations.continue.description'); + }; + + operation.id = "continue"; + operation.keys = [t('operations.continue.key')]; + operation.title = t('operations.continue.title'); + + return operation; +}; diff --git a/js/id/renderer/map.js b/js/id/renderer/map.js index 2c47dd143..7fa2ff6cc 100644 --- a/js/id/renderer/map.js +++ b/js/id/renderer/map.js @@ -20,7 +20,8 @@ iD.Map = function(context) { midpoints = iD.svg.Midpoints(roundedProjection, context), labels = iD.svg.Labels(roundedProjection, context), supersurface, surface, - mouse; + mouse, + mousemove; function map(selection) { context.history() @@ -52,6 +53,10 @@ iD.Map = function(context) { .attr('id', 'surface') .call(iD.svg.Surface(context)); + surface.on('mousemove.map', function() { + mousemove = d3.event; + }); + surface.on('mouseover.vertices', function() { if (map.editable() && !transformed) { var hover = d3.event.target.__data__; @@ -249,7 +254,7 @@ iD.Map = function(context) { } map.mouse = function() { - var e = d3.event, s; + var e = mousemove, s; while (s = e.sourceEvent) e = s; return mouse(e); }; diff --git a/js/id/ui/radial_menu.js b/js/id/ui/radial_menu.js index 3a05ed66e..b4633b552 100644 --- a/js/id/ui/radial_menu.js +++ b/js/id/ui/radial_menu.js @@ -34,7 +34,7 @@ iD.ui.RadialMenu = function(context, operations) { .attr('class', 'radial-menu-background') .attr('d', 'M' + r * Math.sin(a0) + ',' + r * Math.cos(a0) + - ' A' + r + ',' + r + ' 0 0,0 ' + + ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' + (r * Math.sin(a1) + 1e-3) + ',' + (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305) .attr('stroke-width', 50) @@ -68,14 +68,32 @@ iD.ui.RadialMenu = function(context, operations) { function mouseover(d, i) { var rect = context.surfaceRect(), angle = a0 + i * a, - dx = rect.left - (angle < 0 ? 200 : 0), - dy = rect.top; + top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px', + left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px', + bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px', + right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px'; tooltip - .style('left', (r + 25) * Math.sin(angle) + dx + center[0] + 'px') - .style('top', (r + 25) * Math.cos(angle) + dy + center[1]+ 'px') + .style('top', null) + .style('left', null) + .style('bottom', null) + .style('right', null) .style('display', 'block') .html(iD.ui.tooltipHtml(d.tooltip(), d.keys[0])); + + if (i === 0) { + tooltip + .style('right', right) + .style('top', top); + } else if (i >= 4) { + tooltip + .style('left', left) + .style('bottom', bottom); + } else { + tooltip + .style('left', left) + .style('top', top); + } } function mouseout() { diff --git a/test/index.html b/test/index.html index 5f7be8643..0952836ce 100644 --- a/test/index.html +++ b/test/index.html @@ -155,6 +155,7 @@ +