Files
iD/modules/ui/fields/restrictions.js
T
Bryan Housel 98d484fc1f Restore hover behavior to restrictions editor, add breathe behavior
The issue was: now that selections are immutable you can't add behaviors
to them unless they are already entered.  i.e. the surface selection in
enter does not end up being the real surface after merging to update.
2016-10-30 11:35:36 -04:00

242 lines
6.5 KiB
JavaScript

import * as d3 from 'd3';
import { t } from '../../util/locale';
import {
behaviorBreathe,
behaviorHover
} from '../../behavior/index';
import {
osmEntity,
osmIntersection,
osmInferRestriction,
osmTurn
} from '../../osm/index';
import {
actionRestrictTurn,
actionUnrestrictTurn
} from '../../actions/index';
import {
geoExtent,
geoRawMercator
} from '../../geo/index';
import {
svgLayers,
svgLines,
svgTurns,
svgVertices
} from '../../svg/index';
import { utilRebind } from '../../util/rebind';
import { utilFunctor } from '../../util/index';
import {
utilGetDimensions,
utilSetDimensions
} from '../../util/dimensions';
export function uiFieldRestrictions(field, context) {
var dispatch = d3.dispatch('change'),
breathe = behaviorBreathe(context),
hover = behaviorHover(context),
vertexID,
fromNodeID;
function restrictions(selection) {
// if form field is hidden or has detached from dom, clean up.
if (!d3.select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
selection.call(restrictions.off);
return;
}
var wrap = selection.selectAll('.preset-input-wrap')
.data([0]);
var enter = wrap.enter()
.append('div')
.attr('class', 'preset-input-wrap');
enter
.append('div')
.attr('class', 'restriction-help');
var intersection = osmIntersection(context.graph(), vertexID),
graph = intersection.graph,
vertex = graph.entity(vertexID),
filter = utilFunctor(true),
extent = geoExtent(),
projection = geoRawMercator();
var d = utilGetDimensions(wrap.merge(enter)),
c = [d[0] / 2, d[1] / 2],
z = 24;
projection
.scale(256 * Math.pow(2, z) / (2 * Math.PI));
var s = projection(vertex.loc);
projection
.translate([c[0] - s[0], c[1] - s[1]])
.clipExtent([[0, 0], d]);
var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
drawVertices = svgVertices(projection, context),
drawLines = svgLines(projection, context),
drawTurns = svgTurns(projection, context);
enter
.call(drawLayers);
wrap = wrap
.merge(enter);
var surface = wrap.selectAll('.surface');
if (!enter.empty()) {
surface
.call(breathe)
.call(hover);
}
surface
.call(utilSetDimensions, d)
.call(drawVertices, graph, [vertex], filter, extent, z)
.call(drawLines, graph, intersection.ways, filter)
.call(drawTurns, graph, intersection.turns(fromNodeID));
surface
.on('click.restrictions', click)
.on('mouseover.restrictions', mouseover)
.on('mouseout.restrictions', mouseout);
surface
.selectAll('.selected')
.classed('selected', false);
if (fromNodeID) {
surface
.selectAll('.' + intersection.highways[fromNodeID].id)
.classed('selected', true);
}
mouseout();
context.history()
.on('change.restrictions', render);
d3.select(window)
.on('resize.restrictions', function() {
utilSetDimensions(wrap, null);
render();
});
function click() {
surface
.call(breathe.off)
.call(breathe);
var datum = d3.event.target.__data__;
if (datum instanceof osmEntity) {
fromNodeID = intersection.adjacentNodeId(datum.id);
render();
} else if (datum instanceof osmTurn) {
if (datum.restriction) {
context.perform(
actionUnrestrictTurn(datum, projection),
t('operations.restriction.annotation.delete')
);
} else {
context.perform(
actionRestrictTurn(datum, projection),
t('operations.restriction.annotation.create')
);
}
}
}
function mouseover() {
var datum = d3.event.target.__data__;
if (datum instanceof osmTurn) {
var graph = context.graph(),
presets = context.presets(),
preset;
if (datum.restriction) {
preset = presets.match(graph.entity(datum.restriction), graph);
} else {
preset = presets.item('type/restriction/' +
osmInferRestriction(
graph,
datum.from,
datum.via,
datum.to,
projection
)
);
}
wrap.selectAll('.restriction-help')
.text(t('operations.restriction.help.' +
(datum.restriction ? 'toggle_off' : 'toggle_on'),
{ restriction: preset.name() })
);
}
}
function mouseout() {
wrap.selectAll('.restriction-help')
.text(t('operations.restriction.help.' +
(fromNodeID ? 'toggle' : 'select'))
);
}
function render() {
if (context.hasEntity(vertexID)) {
restrictions(selection);
}
}
}
restrictions.entity = function(_) {
if (!vertexID || vertexID !== _.id) {
fromNodeID = null;
vertexID = _.id;
}
};
restrictions.tags = function() {};
restrictions.focus = function() {};
restrictions.off = function(selection) {
selection.selectAll('.surface')
.call(hover.off)
.call(breathe.off)
.on('click.restrictions', null)
.on('mouseover.restrictions', null)
.on('mouseout.restrictions', null);
context.history()
.on('change.restrictions', null);
d3.select(window)
.on('resize.restrictions', null);
};
return utilRebind(restrictions, dispatch, 'on');
}