Skip to content

Commit

Permalink
refactor: move multi selection outline into separate feature
Browse files Browse the repository at this point in the history
closes to #944
  • Loading branch information
misiekhardcore committed Nov 1, 2024
1 parent 65bd338 commit d20f509
Show file tree
Hide file tree
Showing 8 changed files with 399 additions and 257 deletions.
93 changes: 93 additions & 0 deletions lib/features/outline/MultiSelectionOutline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
append as svgAppend,
attr as svgAttr,
create as svgCreate,
classes as svgClasses,
clear as svgClear
} from 'tiny-svg';

import { assign } from 'min-dash';

import { getBBox } from '../../util/Elements';

var SELECTION_OUTLINE_PADDING = 6;

/**
* @typedef {import('../../model/Types').Element} Element
*
* @typedef {import('../../core/EventBus').default} EventBus
* @typedef {import('../selection/Selection').default} Selection
* @typedef {import('../../core/Canvas').default} Canvas
*/

/**
* @class
*
* A plugin that adds an outline to shapes and connections that may be activated and styled
* via CSS classes.
*
* @param {EventBus} eventBus
* @param {Canvas} canvas
* @param {Selection} selection
*/
export default function MultiSelectionOutline(eventBus, canvas, selection) {
this._canvas = canvas;

var self = this;

eventBus.on('element.changed', function(event) {
if (selection.isSelected(event.element)) {
self._updateMultiSelectionOutline(selection.get());
}
});

eventBus.on('selection.changed', function(event) {
var newSelection = event.newSelection;

self._updateMultiSelectionOutline(newSelection);
});
}



MultiSelectionOutline.prototype._updateMultiSelectionOutline = 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);
};


MultiSelectionOutline.$inject = [ 'eventBus', 'canvas', 'selection' ];

// 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
};
}
11 changes: 9 additions & 2 deletions lib/features/outline/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import SelectionModule from '../selection';

import Outline from './Outline';
import MultiSelectionOutline from './MultiSelectionOutline';


/**
* @type { import('didi').ModuleDeclaration }
*/
export default {
__init__: [ 'outline' ],
outline: [ 'type', Outline ]
__depends__: [
SelectionModule
],
__init__: [ 'outline', 'multiSelectionOutline' ],
outline: [ 'type', Outline ],
multiSelectionOutline: [ 'type', MultiSelectionOutline ]
};
73 changes: 2 additions & 71 deletions lib/features/selection/SelectionVisuals.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,15 @@
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';

/**
* @typedef {import('../../core/Canvas').default} Canvas
* @typedef {import('../../core/EventBus').default} EventBus
* @typedef {import('./Selection').default} Selection
*/

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 <code>hover</code> and <code>selected</code> classes to them.
Expand All @@ -35,15 +20,10 @@ var SELECTION_OUTLINE_PADDING = 6;
*
* @param {Canvas} canvas
* @param {EventBus} eventBus
* @param {Selection} selection
*/
export default function SelectionVisuals(canvas, eventBus, selection) {
export default function SelectionVisuals(canvas, eventBus) {
this._canvas = canvas;

var self = this;

this._multiSelectionBox = null;

function addMarker(e, cls) {
canvas.addMarker(e, cls);
}
Expand Down Expand Up @@ -84,59 +64,10 @@ export default function SelectionVisuals(canvas, eventBus, selection) {
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'
'eventBus'
];

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
};
}
2 changes: 0 additions & 2 deletions lib/features/selection/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import InteractionEventsModule from '../interaction-events';
import OutlineModule from '../outline';

import Selection from './Selection';
import SelectionVisuals from './SelectionVisuals';
Expand All @@ -13,7 +12,6 @@ export default {
__init__: [ 'selectionVisuals', 'selectionBehavior' ],
__depends__: [
InteractionEventsModule,
OutlineModule
],
selection: [ 'type', Selection ],
selectionVisuals: [ 'type', SelectionVisuals ],
Expand Down
Loading

0 comments on commit d20f509

Please sign in to comment.