modules/ui/top_toolbar.js (221 lines of code) (raw):

import { event as d3_event, select as d3_select } from 'd3-selection'; import { t } from '../util/locale'; import { utilFunctor } from '../util/util'; import { modeBrowse } from '../modes/browse'; import _debounce from 'lodash-es/debounce'; import { operationCircularize, operationContinue, operationDelete, operationDisconnect, operationDowngrade, operationExtract, operationMerge, operationOrthogonalize, operationReverse, operationSplit, operationStraighten } from '../operations'; import { uiToolAddFavorite, uiToolAddFeature, uiToolAddRecent, uiToolNotes, uiToolOperation, uiToolSave, uiToolUndoRedo } from './tools'; import { uiToolAddAddablePresets } from './tools/quick_presets_addable'; import { uiToolAddGeneric } from './tools/quick_presets_generic'; import { uiToolSimpleButton } from './tools/simple_button'; import { uiToolWaySegments } from './tools/way_segments'; import { uiToolRepeatAdd } from './tools/repeat_add'; import { uiToolStructure } from './tools/structure'; import { uiToolCenterZoom } from './tools/center_zoom'; import { uiToolStopDraw } from './tools/stop_draw'; import { uiToolToolbox } from './tools/toolbox'; import { uiToolAddingGeometry } from './tools/adding_geometry'; import { uiToolPowerSupport } from './tools/power_support'; export function uiTopToolbar(context) { var circularize = uiToolOperation(context, operationCircularize), continueTool = uiToolOperation(context, operationContinue), deleteTool = uiToolOperation(context, operationDelete), disconnect = uiToolOperation(context, operationDisconnect), downgrade = uiToolOperation(context, operationDowngrade), extract = uiToolOperation(context, operationExtract, { isToggledOn: false }), merge = uiToolOperation(context, operationMerge), orthogonalize = uiToolOperation(context, operationOrthogonalize), reverse = uiToolOperation(context, operationReverse), split = uiToolOperation(context, operationSplit), straighten = uiToolOperation(context, operationStraighten); var toolbox = uiToolToolbox(context), addAddable = uiToolAddAddablePresets(context), addFeature = uiToolAddFeature(context), addGeneric = uiToolAddGeneric(context), addFavorite = uiToolAddFavorite(context), addRecent = uiToolAddRecent(context), notes = uiToolNotes(context), undoRedo = uiToolUndoRedo(context), save = uiToolSave(context), waySegments = uiToolWaySegments(context), structure = uiToolStructure(context), repeatAdd = uiToolRepeatAdd(context), centerZoom = uiToolCenterZoom(context), stopDraw = uiToolStopDraw(context), addingGeometry = uiToolAddingGeometry(context), powerSupport = uiToolPowerSupport(context), /* deselect = uiToolSimpleButton({ id: 'deselect', label: t('toolbar.deselect.title'), iconName: 'iD-icon-close', onClick: function() { context.enter(modeBrowse(context)); }, tooltipKey: 'Esc', barButtonClass: 'wide' }), */ cancelSave = uiToolSimpleButton({ id: 'cancel', label: t('confirm.cancel'), iconName: 'iD-icon-close', onClick: function() { context.enter(modeBrowse(context)); }, tooltipKey: 'Esc', allowed: function() { return context.mode().id === 'save'; } }); function allowedTools() { var mode = context.mode(); if (!mode) return []; var tools; if (mode.id === 'save') { tools = [ toolbox, 'spacer', cancelSave ]; } else if (mode.id === 'select' && !mode.newFeature() && mode.selectedIDs().every(function(id) { return context.graph().hasEntity(id); })) { tools = [ toolbox, 'spacer', /* deselect, 'spacer', */ centerZoom, 'spacer', straighten, orthogonalize, circularize, reverse, split, disconnect, extract, merge, continueTool, 'spacer', downgrade, deleteTool, 'spacer', undoRedo, save ]; } else if (mode.id === 'add-point' || mode.id === 'add-line' || mode.id === 'add-area' || mode.id === 'draw-line' || mode.id === 'draw-area') { tools = [ toolbox, addingGeometry, 'spacer', structure, powerSupport, 'spacer', waySegments, 'spacer', repeatAdd, undoRedo, stopDraw ]; } else { tools = [ toolbox, 'spacer', centerZoom, 'spacer', addFeature, addAddable, addGeneric, addFavorite, addRecent, 'spacer', notes, 'spacer', undoRedo, save ]; } tools = tools.filter(function(tool) { return !tool.allowed || tool.allowed(); }); return tools; } function topToolbar(bar) { bar.on('wheel.topToolbar', function() { if (!d3_event.deltaX) { // translate vertical scrolling into horizontal scrolling in case // the user doesn't have an input device that can scroll horizontally bar.node().scrollLeft += d3_event.deltaY; } }); var debouncedUpdate = _debounce(update, 250, { leading: true, trailing: true }); context.history() .on('change.topToolbar', debouncedUpdate); context.layers() .on('change.topToolbar', debouncedUpdate); context.map() .on('move.topToolbar', debouncedUpdate) .on('drawn.topToolbar', debouncedUpdate); context.on('enter.topToolbar', update); context.presets() .on('favoritePreset.topToolbar', update) .on('recentsChange.topToolbar', update); toolbox.onChange = function() { update(); }; update(); function update() { var tools = allowedTools(); toolbox.setAllowedTools(tools); tools = tools.filter(function(tool) { return tool.userToggleable === false || tool.isToggledOn !== false; }); var deduplicatedTools = []; // remove adjacent duplicates (i.e. spacers) tools.forEach(function(tool) { if (!deduplicatedTools.length || deduplicatedTools[deduplicatedTools.length - 1] !== tool) { deduplicatedTools.push(tool); } }); tools = deduplicatedTools; var toolbarItems = bar.selectAll('.toolbar-item') .data(tools, function(d) { return d.id || d; }); toolbarItems.exit() .each(function(d) { if (d.uninstall) { d.uninstall(); } }) .remove(); var itemsEnter = toolbarItems .enter() .each(function(d) { if (d.install) { d.install(); } }) .append('div') .attr('class', function(d) { var classes = 'toolbar-item ' + (d.id || d).replace('_', '-'); if (d.itemClass) classes += ' ' + d.itemClass; return classes; }); var actionableItems = itemsEnter.filter(function(d) { return typeof d !== 'string'; }); actionableItems .append('div') .attr('class', function(d) { var classes = 'item-content'; if (d.contentClass) classes += ' ' + d.contentClass; return classes; }); actionableItems .append('div') .attr('class', 'item-label'); toolbarItems = toolbarItems.merge(itemsEnter) .each(function(d){ if (d.render) d3_select(this).select('.item-content').call(d.render, bar); }); toolbarItems.selectAll('.item-label') .text(function(d) { return utilFunctor(d.label)(); }); } } return topToolbar; }