import { assign, forEach } from 'min-dash'; import { append as svgAppend, attr as svgAttr, classes as svgClasses, clear as svgClear, create as svgCreate } from 'tiny-svg'; import { getBBox } from '../../util/Elements'; var MARKER_HOVER = 'hover', MARKER_SELECTED = 'selected'; var SELECTION_OUTLINE_PADDING = 6; /** * A plugin that adds a visible selection UI to shapes and connections * by appending the hover and selected classes to them. * * @class * * Makes elements selectable, too. * * @param {Canvas} canvas * @param {EventBus} eventBus */ export default function SelectionVisuals(canvas, eventBus, selection) { this._canvas = canvas; var self = this; this._multiSelectionBox = null; function addMarker(e, cls) { canvas.addMarker(e, cls); } function removeMarker(e, cls) { canvas.removeMarker(e, cls); } eventBus.on('element.hover', function(event) { addMarker(event.element, MARKER_HOVER); }); eventBus.on('element.out', function(event) { removeMarker(event.element, MARKER_HOVER); }); eventBus.on('selection.changed', function(event) { function deselect(s) { removeMarker(s, MARKER_SELECTED); } function select(s) { addMarker(s, MARKER_SELECTED); } var oldSelection = event.oldSelection, newSelection = event.newSelection; forEach(oldSelection, function(e) { if (newSelection.indexOf(e) === -1) { deselect(e); } }); forEach(newSelection, function(e) { if (oldSelection.indexOf(e) === -1) { select(e); } }); self._updateSelectionOutline(newSelection); }); eventBus.on('element.changed', function(event) { if (selection.isSelected(event.element)) { self._updateSelectionOutline(selection.get()); } }); } SelectionVisuals.$inject = [ 'canvas', 'eventBus', 'selection' ]; SelectionVisuals.prototype._updateSelectionOutline = function(selection) { var layer = this._canvas.getLayer('selectionOutline'); svgClear(layer); var enabled = selection.length > 1; var container = this._canvas.getContainer(); svgClasses(container)[enabled ? 'add' : 'remove']('djs-multi-select'); if (!enabled) { return; } var bBox = addSelectionOutlinePadding(getBBox(selection)); var rect = svgCreate('rect'); svgAttr(rect, assign({ rx: 3 }, bBox)); svgClasses(rect).add('djs-selection-outline'); svgAppend(layer, rect); }; // helpers ////////// function addSelectionOutlinePadding(bBox) { return { x: bBox.x - SELECTION_OUTLINE_PADDING, y: bBox.y - SELECTION_OUTLINE_PADDING, width: bBox.width + SELECTION_OUTLINE_PADDING * 2, height: bBox.height + SELECTION_OUTLINE_PADDING * 2 }; }