Merge branch 'edit_menu'

This commit is contained in:
Bryan Housel
2017-02-25 15:29:01 -05:00
40 changed files with 812 additions and 258 deletions
+2 -5
View File
@@ -274,9 +274,7 @@ export function uiCommit(context) {
function warningClick(d) {
if (d.entity) {
context.map().zoomTo(d.entity);
context.enter(
modeSelect(context, [d.entity.id]).suppressMenu(true)
);
context.enter(modeSelect(context, [d.entity.id]));
}
}
@@ -286,8 +284,7 @@ export function uiCommit(context) {
if (change.changeType !== 'deleted' &&
context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
context.map().zoomTo(entity);
context.surface().selectAll(
utilEntityOrMemberSelector([entity.id], context.graph()))
context.surface().selectAll(utilEntityOrMemberSelector([entity.id], context.graph()))
.classed('hover', true);
}
}
+180
View File
@@ -0,0 +1,180 @@
import * as d3 from 'd3';
import { geoRoundCoords } from '../geo/index';
import { textDirection } from '../util/locale';
import { uiTooltipHtml } from './tooltipHtml';
export function uiEditMenu(context, operations) {
var menu,
center = [0, 0],
offset = [0, 0],
tooltip;
var p = 8, // top padding
m = 4, // top margin
h = 15, // height of icon
vpBottomMargin = 45, // viewport bottom margin
vpSideMargin = 35, // viewport side margin
buttonWidth = 44,
buttonHeight = (2 * p + h),
menuWidth = buttonWidth,
menuHeight = (2 * m) + operations.length * buttonHeight,
menuSideMargin = 10,
tooltipWidth = 200,
tooltipHeight = 200; // a reasonable guess, real height depends on tooltip contents
var editMenu = function (selection) {
if (!operations.length) return;
selection.node().parentNode.focus();
var isRTL = textDirection === 'rtl',
viewport = context.surfaceRect();
if (!isRTL && (center[0] + menuSideMargin + menuWidth) > (viewport.width - vpSideMargin)) {
// menu is going left-to-right and near right viewport edge, go left instead
isRTL = true;
} else if (isRTL && (center[0] - menuSideMargin - menuWidth) < vpSideMargin) {
// menu is going right-to-left and near left viewport edge, go right instead
isRTL = false;
}
offset[0] = (isRTL ? -1 * (menuSideMargin + menuWidth) : menuSideMargin);
if (center[1] + menuHeight > (viewport.height - vpBottomMargin)) {
// menu is near bottom viewport edge, shift upwards
offset[1] = -1 * (center[1] + menuHeight - viewport.height + vpBottomMargin);
}
var origin = [ center[0] + offset[0], center[1] + offset[1] ];
menu = selection
.append('g')
.attr('class', 'edit-menu')
.attr('transform', 'translate(' + origin + ')')
.attr('opacity', 0);
menu
.transition()
.attr('opacity', 1);
menu
.append('rect')
.attr('class', 'edit-menu-background')
.attr('x', 4)
.attr('rx', 4)
.attr('ry', 4)
.attr('width', menuWidth)
.attr('height', menuHeight)
.attr('stroke-linecap', 'round');
var button = menu.selectAll('.edit-menu-item')
.data(operations)
.enter()
.append('g')
.attr('class', function (d) { return 'edit-menu-item edit-menu-item-' + d.id; })
.classed('disabled', function (d) { return d.disabled(); })
.attr('transform', function (d, i) {
return 'translate(' + geoRoundCoords([
0,
m + i * buttonHeight
]).join(',') + ')';
});
button
.append('rect')
.attr('x', 4)
.attr('width', buttonWidth)
.attr('height', buttonHeight)
.on('click', click)
.on('mousedown', mousedown)
.on('mouseover', mouseover)
.on('mouseout', mouseout);
button
.append('use')
.attr('width', '20')
.attr('height', '20')
.attr('transform', function () {
return 'translate(' + [2 * p, 5] + ')';
})
.attr('xlink:href', function (d) { return '#operation-' + d.id; });
tooltip = d3.select(document.body)
.append('div')
.attr('class', 'tooltip-inner edit-menu-tooltip');
function click(operation) {
d3.event.stopPropagation();
if (operation.disabled()) return;
operation();
editMenu.close();
}
function mousedown() {
d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
}
function mouseover(d, i) {
var tipX, tipY;
if (!isRTL) {
tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
} else {
tipX = viewport.left + origin[0] - 4 - tooltipWidth;
}
if (tipX + tooltipWidth > viewport.right) {
// tip is going left-to-right and near right viewport edge, go left instead
tipX = viewport.left + origin[0] - 4 - tooltipWidth;
} else if (tipX < viewport.left) {
// tip is going right-to-left and near left viewport edge, go right instead
tipX = viewport.left + origin[0] + menuSideMargin + menuWidth;
}
tipY = viewport.top + origin[1] + (i * buttonHeight);
if (tipY + tooltipHeight > viewport.bottom) {
// tip is near bottom viewport edge, shift upwards
tipY -= tipY + tooltipHeight - viewport.bottom;
}
tooltip
.style('left', tipX + 'px')
.style('top', tipY + 'px')
.style('display', 'block')
.html(uiTooltipHtml(d.tooltip(), d.keys[0], d.title));
}
function mouseout() {
tooltip.style('display', 'none');
}
};
editMenu.close = function () {
if (menu) {
menu
.style('pointer-events', 'none')
.transition()
.attr('opacity', 0)
.remove();
}
if (tooltip) {
tooltip.remove();
}
};
editMenu.center = function (_) {
if (!arguments.length) return center;
center = _;
return editMenu;
};
return editMenu;
}
+1 -1
View File
@@ -272,7 +272,7 @@ export function uiFeatureList(context) {
edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
context.map().center(edge.loc);
}
context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
context.enter(modeSelect(context, [d.entity.id]));
} else {
context.zoomToEntity(d.id);
}
+26 -17
View File
@@ -1,26 +1,35 @@
import { uiModal } from './modal';
import * as d3 from 'd3';
var timer;
export function uiFlash(selection) {
var modalSelection = uiModal(selection);
export function uiFlash(showDuration) {
showDuration = showDuration || 1500;
modalSelection.select('.modal')
.classed('modal-flash', true);
if (timer) {
timer.stop();
}
modalSelection.select('.content')
.classed('modal-section', true)
d3.select('#footer-wrap')
.attr('class', 'footer-hide');
d3.select('#flash-wrap')
.attr('class', 'footer-show');
var content = d3.select('#flash-wrap').selectAll('.content')
.data([0]);
content = content.enter()
.append('div')
.attr('class', 'description');
.attr('class', 'content')
.merge(content);
modalSelection.on('click.flash', function() {
modalSelection.remove();
});
setTimeout(function() {
modalSelection.remove();
return true;
}, 1500);
timer = d3.timeout(function() {
timer = null;
d3.select('#footer-wrap')
.attr('class', 'footer-show');
d3.select('#flash-wrap')
.attr('class', 'footer-hide');
}, showDuration);
return modalSelection;
return content;
}
+2
View File
@@ -47,3 +47,5 @@ export { uiTooltipHtml } from './tooltipHtml';
export { uiUndoRedo } from './undo_redo';
export { uiViewOnOSM } from './view_on_osm';
export { uiZoom } from './zoom';
export { uiEditMenu } from './edit_menu';
+17 -4
View File
@@ -116,6 +116,7 @@ export function uiInit(context) {
.attr('class', 'spinner')
.call(uiSpinner(context));
var controls = bar
.append('div')
.attr('class', 'map-controls');
@@ -145,6 +146,7 @@ export function uiInit(context) {
.attr('class', 'map-control help-control')
.call(uiHelp(context));
var about = content
.append('div')
.attr('id', 'about');
@@ -155,6 +157,12 @@ export function uiInit(context) {
.attr('dir', 'ltr')
.call(uiAttribution(context));
about
.append('div')
.attr('class', 'api-status')
.call(uiStatus(context));
var footer = about
.append('div')
.attr('id', 'footer')
@@ -162,15 +170,20 @@ export function uiInit(context) {
footer
.append('div')
.attr('class', 'api-status')
.call(uiStatus(context));
.attr('id', 'flash-wrap')
.attr('class', 'footer-hide');
footer
var footerWrap = footer
.append('div')
.attr('id', 'footer-wrap')
.attr('class', 'footer-show');
footerWrap
.append('div')
.attr('id', 'scale-block')
.call(uiScale(context));
var aboutList = footer
var aboutList = footerWrap
.append('div')
.attr('id', 'info-block')
.append('ul')
+12 -7
View File
@@ -31,7 +31,7 @@ export function uiIntroPoint(context, reveal) {
t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
{ tooltipClass: 'intro-points-add' });
var corner = [-85.632481,41.944094];
var corner = [-85.632481, 41.944094];
context.on('enter.intro', addPoint);
@@ -125,11 +125,11 @@ export function uiIntroPoint(context, reveal) {
context.on('enter.intro', enterDelete);
var pointBox = pad(corner, 150, context);
reveal(pointBox, t('intro.points.reselect_delete'));
reveal(pointBox, t('intro.points.rightclick'));
context.map().on('move.intro', function() {
pointBox = pad(corner, 150, context);
reveal(pointBox, t('intro.points.reselect_delete'), {duration: 0});
reveal(pointBox, t('intro.points.rightclick'), {duration: 0});
});
}
@@ -143,10 +143,15 @@ export function uiIntroPoint(context, reveal) {
context.history().on('change.intro', deleted);
setTimeout(function() {
var node = d3.select('.radial-menu-item-delete').node();
var pointBox = pad(node.getBoundingClientRect(), 50, context);
reveal(pointBox,
t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
// deprecation warning - Radial Menu to be removed in iD v3
var node = d3.select('.edit-menu-item-delete, .radial-menu-item-delete').node();
if (!node) {
deletePoint();
} else {
var pointBox = pad(node.getBoundingClientRect(), 50, context);
reveal(pointBox,
t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
}
}, 300);
}
+1 -1
View File
@@ -21,7 +21,7 @@ export function uiRawMemberEditor(context) {
function selectMember(d) {
d3.event.preventDefault();
context.enter(modeSelect(context, [d.id]).suppressMenu(true));
context.enter(modeSelect(context, [d.id]));
}
+2 -2
View File
@@ -25,7 +25,7 @@ export function uiRawMembershipEditor(context) {
function selectRelation(d) {
d3.event.preventDefault();
context.enter(modeSelect(context, [d.relation.id]).suppressMenu(true));
context.enter(modeSelect(context, [d.relation.id]));
}
@@ -55,7 +55,7 @@ export function uiRawMembershipEditor(context) {
t('operations.add.annotation.relation')
);
context.enter(modeSelect(context, [relation.id]).suppressMenu(true));
context.enter(modeSelect(context, [relation.id]));
}
}
+15 -7
View File
@@ -63,12 +63,13 @@ export function uiScale(context) {
loc2 = projection.invert([maxLength, dims[1]]),
scale = scaleDefs(loc1, loc2);
selection.select('#scalepath')
selection.select('#scale-path')
.attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
selection.select('#scaletext')
.attr('x', scale.px + 8)
.attr('y', tickHeight)
selection.select('#scale-textgroup')
.attr('transform', 'translate(' + (scale.px + 8) + ',' + tickHeight + ')');
selection.select('#scale-text')
.text(scale.text);
}
@@ -79,14 +80,21 @@ export function uiScale(context) {
selection.call(update);
}
var g = selection.append('svg')
var scalegroup = selection.append('svg')
.attr('id', 'scale')
.on('click', switchUnits)
.append('g')
.attr('transform', 'translate(10,11)');
g.append('path').attr('id', 'scalepath');
g.append('text').attr('id', 'scaletext');
scalegroup
.append('path')
.attr('id', 'scale-path');
scalegroup
.append('g')
.attr('id', 'scale-textgroup')
.append('text')
.attr('id', 'scale-text');
selection.call(update);
+2 -2
View File
@@ -9,7 +9,7 @@ import { utilDisplayName } from '../util/index';
export function uiSelectionList(context, selectedIDs) {
function selectEntity(entity) {
context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
context.enter(modeSelect(context, [entity.id]));
}
@@ -19,7 +19,7 @@ export function uiSelectionList(context, selectedIDs) {
if (index > -1) {
selectedIDs.splice(index, 1);
}
context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
context.enter(modeSelect(context, selectedIDs));
}
+13 -6
View File
@@ -1,11 +1,18 @@
import { t } from '../util/locale';
export function uiTooltipHtml(text, key) {
var s = '<span>' + text + '</span>';
if (key) {
s += '<div class="keyhint-wrap">' +
'<span> ' + (t('tooltip_keyhint')) + ' </span>' +
'<span class="keyhint"> ' + key + '</span></div>';
export function uiTooltipHtml(text, key, heading) {
var s = '';
if (heading) {
s += '<div class="tooltip-heading"><span>' + heading + '</span></div>';
}
if (text) {
s += '<div class="tooltip-text"><span>' + text + '</span></div>';
}
if (key) {
s += '<div class="keyhint-wrap"><span>' + t('tooltip_keyhint') + '</span>' +
'<span class="keyhint">' + key + '</span></div>';
}
return s;
}