Skip to content

Commit edc4b0b

Browse files
author
Niklas Kiefer
committed
feat(selection): add marker to related elements
1 parent 22174c2 commit edc4b0b

File tree

4 files changed

+241
-3
lines changed

4 files changed

+241
-3
lines changed

assets/diagram-js.css

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,39 @@
88
}
99

1010
.djs-element.hover .djs-outline,
11-
.djs-element.selected .djs-outline {
11+
.djs-element.selected .djs-outline,
12+
.djs-element.related-selected .djs-outline,
13+
.djs-element.related-hover .djs-outline {
1214
visibility: visible;
1315
shape-rendering: crispEdges;
1416
stroke-dasharray: 3,3;
1517
}
1618

1719
.djs-element.selected .djs-outline {
1820
stroke: #8888FF;
21+
opacity: 1;
1922
stroke-width: 1px;
2023
}
2124

2225
.djs-element.hover .djs-outline {
2326
stroke: #FF8888;
27+
opacity: 1;
28+
stroke-width: 1px;
29+
}
30+
31+
.djs-element.related-selected .djs-outline {
32+
stroke: #8888FF;
33+
opacity: 0.5;
34+
stroke-width: 1px;
35+
}
36+
37+
.djs-element.related-hover .djs-outline {
38+
stroke: #FF8888;
39+
opacity: 0.5;
2440
stroke-width: 1px;
2541
}
2642

43+
2744
.djs-shape.connect-ok .djs-visual > :nth-child(1) {
2845
fill: #DCFECC /* light-green */ !important;
2946
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {
2+
forEach
3+
} from 'min-dash';
4+
5+
import {
6+
getType
7+
} from '../../util/Elements';
8+
9+
var MARKER_RELATED_SELECTED = 'related-selected',
10+
MARKER_RELATED_HOVER = 'related-hover';
11+
12+
13+
/**
14+
* A plugin that adds a visible selection UI to related elements after an element
15+
* was selected by appending the <code>related-selected</code> and
16+
* <code>related-hover</code> classes to them.
17+
*
18+
* @class
19+
*
20+
* Creates outline on related elements after selecting an element
21+
*
22+
* @param {EventBus} events
23+
* @param {Canvas} canvas
24+
*/
25+
export default function HighlightRelated(events, canvas) {
26+
27+
function applyToRelatedElements(e, cls, fn) {
28+
29+
// shape, connection -> mark related labels
30+
if (getType(e) === 'shape' || getType(e) === 'connection') {
31+
forEach(e.labels, function(label) {
32+
fn(label, cls);
33+
});
34+
}
35+
36+
// label -> mark related shape, connection
37+
if (e.labelTarget) {
38+
fn(e.labelTarget, cls);
39+
}
40+
}
41+
42+
function addMarkerToRelated(e, cls) {
43+
applyToRelatedElements(e, cls, canvas.addMarker.bind(canvas));
44+
}
45+
46+
function removeMarkerFromRelated(e, cls) {
47+
applyToRelatedElements(e, cls, canvas.removeMarker.bind(canvas));
48+
}
49+
50+
events.on('element.hover', function(event) {
51+
addMarkerToRelated(event.element, MARKER_RELATED_HOVER);
52+
});
53+
54+
events.on('element.out', function(event) {
55+
removeMarkerFromRelated(event.element, MARKER_RELATED_HOVER);
56+
});
57+
58+
events.on('selection.changed', function(event) {
59+
var oldSelection = event.oldSelection,
60+
newSelection = event.newSelection;
61+
62+
forEach(oldSelection, function(e) {
63+
if (newSelection.indexOf(e) === -1) {
64+
removeMarkerFromRelated(e, MARKER_RELATED_SELECTED);
65+
}
66+
});
67+
68+
forEach(newSelection, function(e) {
69+
if (oldSelection.indexOf(e) === -1) {
70+
addMarkerToRelated(e, MARKER_RELATED_SELECTED);
71+
}
72+
});
73+
});
74+
}
75+
76+
HighlightRelated.$inject = [
77+
'eventBus',
78+
'canvas',
79+
];

lib/features/selection/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ import OutlineModule from '../outline';
44
import Selection from './Selection';
55
import SelectionVisuals from './SelectionVisuals';
66
import SelectionBehavior from './SelectionBehavior';
7+
import HighlightRelated from './HighlightRelated';
78

89

910
export default {
10-
__init__: [ 'selectionVisuals', 'selectionBehavior' ],
11+
__init__: [ 'selectionVisuals', 'selectionBehavior', 'highlightRelated' ],
1112
__depends__: [
1213
InteractionEventsModule,
1314
OutlineModule
1415
],
1516
selection: [ 'type', Selection ],
1617
selectionVisuals: [ 'type', SelectionVisuals ],
17-
selectionBehavior: [ 'type', SelectionBehavior ]
18+
selectionBehavior: [ 'type', SelectionBehavior ],
19+
highlightRelated: [ 'type', HighlightRelated ]
1820
};
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import {
2+
bootstrapDiagram,
3+
inject
4+
} from 'test/TestHelper';
5+
6+
import selectionModule from 'lib/features/selection';
7+
8+
import {
9+
matches
10+
} from 'min-dom';
11+
12+
13+
describe('features/selection/HighlightRelated', function() {
14+
15+
beforeEach(bootstrapDiagram({ modules: [ selectionModule ] }));
16+
17+
describe('bootstrap', function() {
18+
19+
beforeEach(bootstrapDiagram({ modules: [ selectionModule ] }));
20+
21+
it('should bootstrap diagram with component', inject(function() {
22+
23+
}));
24+
25+
});
26+
27+
describe('selection box on related elements', function() {
28+
29+
var shape, shape2, connection, label, label2;
30+
31+
beforeEach(inject(function(elementFactory, canvas) {
32+
33+
// given
34+
shape = elementFactory.createShape({
35+
id: 'child',
36+
x: 100, y: 100, width: 100, height: 100
37+
});
38+
39+
canvas.addShape(shape);
40+
41+
shape2 = elementFactory.createShape({
42+
id: 'child2',
43+
x: 300, y: 100, width: 100, height: 100
44+
});
45+
46+
canvas.addShape(shape2);
47+
48+
connection = elementFactory.createConnection({
49+
id: 'connection',
50+
waypoints: [ { x: 150, y: 150 }, { x: 150, y: 200 }, { x: 350, y: 150 } ],
51+
source: shape,
52+
target: shape2
53+
});
54+
55+
canvas.addConnection(connection);
56+
57+
label = elementFactory.createLabel({
58+
id: 'label',
59+
x: 100, y: 200, width: 20, height: 20,
60+
labelTarget: shape
61+
});
62+
63+
canvas.addShape(label);
64+
65+
label2 = elementFactory.createLabel({
66+
id: 'label2',
67+
x: 200, y: 200, width: 20, height: 20,
68+
labelTarget: connection
69+
});
70+
71+
canvas.addShape(label2);
72+
}));
73+
74+
describe('shapes', function() {
75+
76+
77+
it('should show box on related label on select',
78+
inject(function(selection, canvas) {
79+
80+
// when
81+
selection.select(shape);
82+
83+
// then
84+
var gfx = canvas.getGraphics(label),
85+
hasOutline = matches(gfx, '.related-selected');
86+
87+
expect(hasOutline).to.be.true;
88+
}));
89+
90+
91+
it('should show box on shape on selecting label',
92+
inject(function(selection, canvas) {
93+
94+
// when
95+
selection.select(label);
96+
97+
// then
98+
var gfx = canvas.getGraphics(shape),
99+
hasOutline = matches(gfx, '.related-selected');
100+
101+
expect(hasOutline).to.be.true;
102+
}));
103+
});
104+
105+
106+
describe('connection', function() {
107+
108+
109+
it('should show box on related label on select',
110+
inject(function(selection, canvas) {
111+
112+
// when
113+
selection.select(connection);
114+
115+
// then
116+
var gfx = canvas.getGraphics(label2),
117+
hasOutline = matches(gfx, '.related-selected');
118+
119+
expect(hasOutline).to.be.true;
120+
}));
121+
122+
123+
it('should paler box on connection on selecting label',
124+
inject(function(selection, canvas) {
125+
126+
// when
127+
selection.select(label2);
128+
129+
// then
130+
var gfx = canvas.getGraphics(connection),
131+
hasOutline = matches(gfx, '.related-selected');
132+
133+
expect(hasOutline).to.be.true;
134+
}));
135+
136+
});
137+
138+
});
139+
140+
});

0 commit comments

Comments
 (0)