15 |
15 |
|
16 |
16 |
const oneCharacterWidth = 8.3; // approximate width (in pixels) of one character using Consolas at 15px font size
|
17 |
17 |
const minimumWidth = 200;
|
|
18 |
const relatedArchetypeIconWidth = 20;
|
18 |
19 |
|
19 |
20 |
var rootElement;
|
20 |
21 |
var symbolListComponent;
|
... | ... | |
32 |
33 |
var iconsDisplayed = false;
|
33 |
34 |
|
34 |
35 |
var highlighted = false;
|
35 |
|
var highlightedRequired = false;
|
36 |
|
var highlightedProvided = false;
|
37 |
36 |
var highlightedRequiredNeighbours = false;
|
38 |
37 |
var highlightedProvidedNeighbours = false;
|
|
38 |
var highlightedArchetypeNeighbours = false;
|
39 |
39 |
var found = false;
|
40 |
40 |
var dimmed = false;
|
41 |
41 |
|
42 |
42 |
var inEdgeList = [];
|
43 |
43 |
var outEdgeList = [];
|
44 |
44 |
var symbolList = [];
|
|
45 |
var relatedArchetypeMap = {};
|
45 |
46 |
|
46 |
47 |
/**
|
47 |
48 |
* Adds a new edge ending in the vertex. Its ending point is moved to the current position of the vertex.
|
... | ... | |
86 |
87 |
};
|
87 |
88 |
|
88 |
89 |
/**
|
89 |
|
*
|
90 |
|
* @param {array} symbol Node symbol to be displayed next to the vertex.
|
|
90 |
* @returns {integer} Number of incoming/outgoing edges.
|
|
91 |
*/
|
|
92 |
this.countEdges = function() {
|
|
93 |
return inEdgeList.length + outEdgeList.length;
|
|
94 |
};
|
|
95 |
|
|
96 |
/**
|
|
97 |
* Increments counter of instances of a vertex archetype by one.
|
|
98 |
* @param {integer} archetypeIndex Index of the vertex archetype.
|
|
99 |
*/
|
|
100 |
this.incrementRelatedArchetype = function(archetypeIndex) {
|
|
101 |
if (!relatedArchetypeMap.hasOwnProperty(archetypeIndex)) {
|
|
102 |
relatedArchetypeMap[archetypeIndex] = 0;
|
|
103 |
}
|
|
104 |
|
|
105 |
relatedArchetypeMap[archetypeIndex]++;
|
|
106 |
};
|
|
107 |
|
|
108 |
/**
|
|
109 |
* @returns {object} Map with archetype indexes as keys and counters of their instances as values.
|
|
110 |
*/
|
|
111 |
this.getRelatedArchetypeMap = function() {
|
|
112 |
return relatedArchetypeMap;
|
|
113 |
};
|
|
114 |
|
|
115 |
/**
|
|
116 |
* @returns {integer} Number of unique vertex archetypes related to the vertex.
|
|
117 |
*/
|
|
118 |
this.countRelatedArchetypes = function() {
|
|
119 |
return Object.keys(relatedArchetypeMap).length;
|
|
120 |
};
|
|
121 |
|
|
122 |
/**
|
|
123 |
* Adds symbol to the list of symbols displayed next to the vertex.
|
|
124 |
* @param {array} symbol Node symbol to be added.
|
91 |
125 |
*/
|
92 |
126 |
this.addSymbol = function(symbol) {
|
93 |
127 |
symbolList.push(symbol);
|
... | ... | |
108 |
142 |
|
109 |
143 |
symbolListComponent.removeChild(symbol);
|
110 |
144 |
};
|
111 |
|
|
112 |
|
this.countEdges = function() {
|
113 |
|
return inEdgeList.length + outEdgeList.length;
|
114 |
|
};
|
115 |
145 |
|
116 |
146 |
/**
|
117 |
147 |
* @returns {Coordinates} Current position of the vertex.
|
... | ... | |
240 |
270 |
}
|
241 |
271 |
};
|
242 |
272 |
|
|
273 |
/**
|
|
274 |
* Toggles inner state of the vertex marking whether highlighting of its requirements is active.
|
|
275 |
* @param {boolean} newValue True to highlight the neighbours, false to unhighlight.
|
|
276 |
*/
|
|
277 |
this.setHighlightedRequiredNeighbours = function(newValue) {
|
|
278 |
highlightedRequiredNeighbours = newValue;
|
|
279 |
};
|
|
280 |
|
|
281 |
/**
|
|
282 |
* Toggles inner state of the vertex marking whether highlighting of its dependents is active.
|
|
283 |
* @param {boolean} newValue True to highlight the neighbours, false to unhighlight.
|
|
284 |
*/
|
|
285 |
this.setHighlightedProvidedNeighbours = function(newValue) {
|
|
286 |
highlightedProvidedNeighbours = newValue;
|
|
287 |
};
|
|
288 |
|
|
289 |
/**
|
|
290 |
* Toggles inner state of the vertex marking whether highlighting of instances of a vertex archetype is active.
|
|
291 |
* @param {boolean} newValue True to highlight the neighbours, false to unhighlight.
|
|
292 |
*/
|
|
293 |
this.setHighlightedArchetypeNeighbours = function(newValue) {
|
|
294 |
highlightedArchetypeNeighbours = newValue;
|
|
295 |
};
|
|
296 |
|
243 |
297 |
/**
|
244 |
298 |
* Toggles highlighting of the vertex to mark it as requirement of some other node.
|
245 |
299 |
* @param {boolean} newValue True to highlight, false to unhighlight.
|
246 |
300 |
*/
|
247 |
301 |
this.setHighlightedRequired = function(newValue) {
|
248 |
|
highlightedRequired = newValue;
|
249 |
|
|
250 |
302 |
if (newValue) {
|
251 |
303 |
rootElement.classList.add('node--highlighted-required');
|
252 |
304 |
} else {
|
... | ... | |
263 |
315 |
* @param {boolean} newValue True to highlight, false to unhighlight.
|
264 |
316 |
*/
|
265 |
317 |
this.setHighlightedProvided = function(newValue) {
|
266 |
|
highlightedProvided = newValue;
|
267 |
|
|
268 |
318 |
if (newValue) {
|
269 |
319 |
rootElement.classList.add('node--highlighted-provided');
|
270 |
320 |
} else {
|
... | ... | |
277 |
327 |
};
|
278 |
328 |
|
279 |
329 |
/**
|
280 |
|
* Toggles highlighting of the vertex when only its requirements should be highlighted. Anytime this value is changed, generic
|
281 |
|
* {@link Vertex#setHighlighted} method should be called too.
|
282 |
|
* @param {boolean} newValue True to highlight the vertex when only its requirements should be highlighted, false to unhighlight.
|
|
330 |
* Toggles highlighting of the vertex to mark it as instance of archetype related to some other node.
|
|
331 |
* @param {boolean} newValue True to highlight, false to unhighlight.
|
283 |
332 |
*/
|
284 |
|
this.setHighlightedRequiredNeighbours = function(newValue) {
|
285 |
|
highlightedRequiredNeighbours = newValue;
|
286 |
|
|
|
333 |
this.setHighlightedArchetype = function(newValue) {
|
287 |
334 |
if (newValue) {
|
288 |
|
rootElement.classList.add('node--highlighted-required-neighbours');
|
|
335 |
rootElement.classList.add('node--highlighted-archetype');
|
289 |
336 |
} else {
|
290 |
|
rootElement.classList.remove('node--highlighted-required-neighbours');
|
|
337 |
rootElement.classList.remove('node--highlighted-archetype');
|
291 |
338 |
}
|
292 |
|
};
|
293 |
339 |
|
294 |
|
/**
|
295 |
|
* Toggles highlighting of the vertex when only its dependents should be highlighted. Anytime this value is changed, generic
|
296 |
|
* {@link Vertex#setHighlighted} method should be called too.
|
297 |
|
* @param {boolean} newValue True to highlight the vertex when only its dependents should be highlighted, false to unhighlight.
|
298 |
|
*/
|
299 |
|
this.setHighlightedProvidedNeighbours = function(newValue) {
|
300 |
|
highlightedProvidedNeighbours = newValue;
|
301 |
|
|
302 |
|
if (newValue) {
|
303 |
|
rootElement.classList.add('node--highlighted-provided-neighbours');
|
304 |
|
} else {
|
305 |
|
rootElement.classList.remove('node--highlighted-provided-neighbours');
|
|
340 |
if (group !== null) {
|
|
341 |
group.setHighlightedArchetype(newValue);
|
306 |
342 |
}
|
307 |
343 |
};
|
308 |
344 |
|
... | ... | |
390 |
426 |
* @returns {Element} HTML or SVG DOM element depending on whether the vertex is excluded.
|
391 |
427 |
*/
|
392 |
428 |
this.render = function() {
|
|
429 |
size.width += this.countRelatedArchetypes() * relatedArchetypeIconWidth;
|
|
430 |
|
393 |
431 |
rootElement = excluded ? renderExcluded.call(this) : renderIncluded.call(this);
|
394 |
432 |
|
395 |
433 |
this.setHighlighted(highlighted);
|
396 |
|
this.setHighlightedRequiredNeighbours(highlightedRequiredNeighbours);
|
397 |
|
this.setHighlightedProvidedNeighbours(highlightedProvidedNeighbours);
|
398 |
434 |
|
399 |
435 |
return rootElement;
|
400 |
436 |
};
|
... | ... | |
447 |
483 |
// archetype icon
|
448 |
484 |
var archetypeIcon = app.dom.createSvgElement('g', {
|
449 |
485 |
'class': 'archetype',
|
450 |
|
'transform': 'translate(7, 6)',
|
|
486 |
'transform': 'translate(8, 8)',
|
451 |
487 |
});
|
452 |
488 |
archetypeIcon.addEventListener('click', archetypeClick.bind(this));
|
453 |
489 |
|
... | ... | |
464 |
500 |
nameText.appendChild(document.createTextNode(this.name));
|
465 |
501 |
rootElement.appendChild(nameText);
|
466 |
502 |
|
|
503 |
// related archetype icons
|
|
504 |
var relatedArchetypeListContainer = app.dom.createSvgElement('g', {
|
|
505 |
'transform': `translate(${size.width - this.countRelatedArchetypes() * relatedArchetypeIconWidth}, 0)`,
|
|
506 |
});
|
|
507 |
rootElement.appendChild(relatedArchetypeListContainer);
|
|
508 |
|
|
509 |
var i = 0;
|
|
510 |
for (var archetypeIndex in relatedArchetypeMap) {
|
|
511 |
var relatedArchetype = app.utils.createSvgElement('g', {
|
|
512 |
'class': 'related-archetype',
|
|
513 |
'transform': `translate(${i * relatedArchetypeIconWidth}, 8)`,
|
|
514 |
});
|
|
515 |
relatedArchetype.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex)));
|
|
516 |
|
|
517 |
relatedArchetype.innerHTML = app.archetype.icon[app.archetype.vertex[archetypeIndex].name];
|
|
518 |
|
|
519 |
relatedArchetypeListContainer.appendChild(relatedArchetype);
|
|
520 |
|
|
521 |
i++;
|
|
522 |
}
|
|
523 |
|
467 |
524 |
// symbol list
|
468 |
525 |
symbolListComponent = new VertexSymbolList;
|
469 |
526 |
rootElement.appendChild(symbolListComponent.render());
|
... | ... | |
496 |
553 |
});
|
497 |
554 |
svg.appendChild(group);
|
498 |
555 |
|
499 |
|
// required
|
500 |
|
var required = app.utils.createSvgElement('g', {
|
501 |
|
'class': 'required-counter',
|
|
556 |
// related
|
|
557 |
var i = 0;
|
|
558 |
for (var archetypeIndex in relatedArchetypeMap) {
|
|
559 |
var relatedArchetype = app.dom.createSvgElement('g', {
|
|
560 |
'class': 'related-archetype',
|
|
561 |
'transform': `translate(0, ${i * 20})`,
|
502 |
562 |
});
|
503 |
|
required.addEventListener('click', requiredClick.bind(this));
|
504 |
|
group.appendChild(required);
|
505 |
|
|
506 |
|
required.appendChild(app.utils.createSvgElement('line', {
|
507 |
|
'x1': -50,
|
508 |
|
'y1': 5,
|
509 |
|
'x2': -42,
|
510 |
|
'y2': 5,
|
511 |
|
'stroke': 'black',
|
512 |
|
'class': 'outer-floater',
|
513 |
|
}));
|
514 |
|
required.appendChild(app.utils.createSvgElement('line', {
|
515 |
|
'x1': -20,
|
516 |
|
'y1': 5,
|
517 |
|
'x2': -14,
|
518 |
|
'y2': 5,
|
519 |
|
'stroke': 'black',
|
520 |
|
}));
|
521 |
|
required.appendChild(app.utils.createSvgElement('rect', {
|
522 |
|
'x': -58,
|
523 |
|
'y': 1,
|
524 |
|
'width': 8,
|
525 |
|
'height': 8,
|
526 |
|
'class': 'outer-port',
|
527 |
|
}));
|
528 |
|
required.appendChild(app.utils.createSvgElement('path', {
|
529 |
|
'class': 'lollipop',
|
530 |
|
'd': 'M-31,-5 C-16,-5 -16,15 -31,16',
|
531 |
|
}));
|
|
563 |
relatedArchetype.addEventListener('click', relatedArchetypeClick.bind(this, parseInt(archetypeIndex)));
|
532 |
564 |
|
533 |
|
var requiredCounterText = app.utils.createSvgElement('text', {
|
534 |
|
'x': -36,
|
535 |
|
'y': 10,
|
536 |
|
});
|
537 |
|
requiredCounterText.appendChild(document.createTextNode(props.importedPackages.length));
|
538 |
|
required.appendChild(requiredCounterText);
|
|
565 |
relatedArchetype.innerHTML = app.archetype.icon[app.archetype.vertex[archetypeIndex].name];
|
539 |
566 |
|
540 |
|
// provided
|
541 |
|
var provided = app.utils.createSvgElement('g', {
|
542 |
|
'class': 'provided-counter',
|
543 |
|
});
|
544 |
|
provided.addEventListener('click', providedClick.bind(this));
|
545 |
|
group.appendChild(provided);
|
546 |
|
|
547 |
|
provided.appendChild(app.utils.createSvgElement('line', {
|
548 |
|
'x1': -50,
|
549 |
|
'y1': 35,
|
550 |
|
'x2': -44,
|
551 |
|
'y2': 35,
|
552 |
|
'stroke': 'black',
|
553 |
|
'class': 'outer-floater',
|
554 |
|
}));
|
555 |
|
provided.appendChild(app.utils.createSvgElement('line', {
|
556 |
|
'x1': -20,
|
557 |
|
'y1': 35,
|
558 |
|
'x2': -14,
|
559 |
|
'y2': 35,
|
560 |
|
'stroke': 'black',
|
561 |
|
}));
|
562 |
|
provided.appendChild(app.utils.createSvgElement('rect', {
|
563 |
|
'x': -58,
|
564 |
|
'y': 31,
|
565 |
|
'width': 8,
|
566 |
|
'height': 8,
|
567 |
|
'class': 'outer-port',
|
568 |
|
}));
|
569 |
|
provided.appendChild(app.utils.createSvgElement('circle', {
|
570 |
|
'class': 'lollipop',
|
571 |
|
'cx': -32,
|
572 |
|
'cy': 35,
|
573 |
|
'r': 11,
|
574 |
|
}));
|
|
567 |
group.appendChild(relatedArchetype);
|
575 |
568 |
|
576 |
|
var providedCounterText = app.utils.createSvgElement('text', {
|
577 |
|
'x': -36,
|
578 |
|
'y': 40,
|
579 |
|
});
|
580 |
|
providedCounterText.appendChild(document.createTextNode(props.exportedPackages.length));
|
581 |
|
provided.appendChild(providedCounterText);
|
|
569 |
i++;
|
|
570 |
}
|
582 |
571 |
|
583 |
572 |
// name
|
584 |
573 |
var nameText = app.utils.createHtmlElement('div', {
|
... | ... | |
646 |
635 |
this.setHighlightedRequiredNeighbours(highlighted);
|
647 |
636 |
this.setHighlightedProvidedNeighbours(highlighted);
|
648 |
637 |
|
649 |
|
highlightNeighbours.call(this);
|
|
638 |
prepareHighlighting.call(this);
|
|
639 |
highlightRequiredNeighbours.call(this);
|
|
640 |
highlightProvidedNeighbours.call(this);
|
650 |
641 |
return;
|
651 |
642 |
}
|
652 |
643 |
|
... | ... | |
660 |
651 |
this.setHighlighted(!highlighted);
|
661 |
652 |
this.setHighlightedRequiredNeighbours(highlighted);
|
662 |
653 |
this.setHighlightedProvidedNeighbours(highlighted);
|
663 |
|
|
664 |
|
highlightNeighbours.call(this);
|
|
654 |
|
|
655 |
prepareHighlighting.call(this);
|
|
656 |
highlightRequiredNeighbours.call(this);
|
|
657 |
highlightProvidedNeighbours.call(this);
|
665 |
658 |
break;
|
666 |
659 |
|
667 |
660 |
case 'exclude':
|
... | ... | |
673 |
666 |
}
|
674 |
667 |
|
675 |
668 |
/**
|
676 |
|
* Highlights the vertex as a requirement.
|
677 |
|
*/
|
678 |
|
function requiredClick() {
|
679 |
|
this.setHighlighted(!highlighted);
|
680 |
|
this.setHighlightedRequiredNeighbours(highlighted);
|
681 |
|
this.setHighlightedProvidedNeighbours(false);
|
682 |
|
|
683 |
|
highlightRequiredNeighbours.call(this);
|
684 |
|
}
|
685 |
|
|
686 |
|
/**
|
687 |
|
* Highlights the vertex as a dependent.
|
|
669 |
* Reveals vertex popover.
|
|
670 |
* @param {MouseEvent} e Click event.
|
688 |
671 |
*/
|
689 |
|
function providedClick() {
|
690 |
|
this.setHighlighted(!highlighted);
|
691 |
|
this.setHighlightedRequiredNeighbours(false);
|
692 |
|
this.setHighlightedProvidedNeighbours(highlighted);
|
|
672 |
function archetypeClick(e) {
|
|
673 |
e.stopPropagation();
|
693 |
674 |
|
694 |
|
highlightProvidedNeighbours.call(this);
|
|
675 |
app.viewportComponent.vertexPopoverComponent.setContent(this.name + ` (${app.archetype.vertex[this.archetype].name})`, props.attributes);
|
|
676 |
app.viewportComponent.vertexPopoverComponent.setPosition(new Coordinates(e.clientX, e.clientY));
|
|
677 |
app.viewportComponent.vertexPopoverComponent.open();
|
695 |
678 |
}
|
696 |
679 |
|
697 |
680 |
/**
|
698 |
|
* Reveals vertex popover.
|
699 |
|
* @param {Event} e Click event.
|
|
681 |
* Archetype icon click interaction. Toggles highlighting of neighbour vertices which are instances of a vertex archetype.
|
|
682 |
* @param {integer} archetypeIndex Index of the vertex archetype.
|
|
683 |
* @param {MouseEvent} e Click event.
|
700 |
684 |
*/
|
701 |
|
function archetypeClick(e) {
|
|
685 |
function relatedArchetypeClick(archetypeIndex, e) {
|
702 |
686 |
e.stopPropagation();
|
703 |
687 |
|
704 |
|
app.viewportComponent.vertexPopoverComponent.setContent(this.name + ` (${this.archetype.name})`, props.exportedPackages);
|
705 |
|
app.viewportComponent.vertexPopoverComponent.setPosition(new Coordinates(e.clientX, e.clientY));
|
706 |
|
app.viewportComponent.vertexPopoverComponent.open();
|
|
688 |
this.setHighlighted(!highlighted);
|
|
689 |
this.setHighlightedArchetypeNeighbours(highlighted);
|
|
690 |
|
|
691 |
prepareHighlighting.call(this);
|
|
692 |
highlightArchetypeNeighbours.call(this, archetypeIndex);
|
707 |
693 |
}
|
708 |
694 |
|
709 |
695 |
/**
|
710 |
696 |
* Displays symbol of the vertex next to all nodes that it is connected with.
|
711 |
|
* @param {Event} e Click event.
|
|
697 |
* @param {MouseEvent} e Click event.
|
712 |
698 |
*/
|
713 |
699 |
function showIconClick(e) {
|
714 |
700 |
iconsDisplayed = !iconsDisplayed;
|
... | ... | |
815 |
801 |
document.body.removeEventListener('mouseleave', mouseUp);
|
816 |
802 |
}
|
817 |
803 |
}
|
818 |
|
|
|
804 |
|
819 |
805 |
/**
|
820 |
|
* Highlights all neighbours of the vertex. They are either highlighted as required or provided, or dimmed.
|
|
806 |
* * Prepares highlighting of all graph components so that only the wished ones need to be modified.
|
821 |
807 |
*/
|
822 |
|
function highlightNeighbours() {
|
|
808 |
function prepareHighlighting() {
|
823 |
809 |
this.setDimmed(false);
|
|
810 |
|
824 |
811 |
this.setHighlightedRequired(false);
|
825 |
812 |
this.setHighlightedProvided(false);
|
|
813 |
this.setHighlightedArchetype(false);
|
826 |
814 |
|
827 |
815 |
if (highlighted) {
|
828 |
816 |
// dim and unhighlight all nodes but this
|
... | ... | |
834 |
822 |
node.setHighlighted(false);
|
835 |
823 |
node.setHighlightedRequired(false);
|
836 |
824 |
node.setHighlightedProvided(false);
|
837 |
|
node.setHighlightedRequiredNeighbours(false);
|
838 |
|
node.setHighlightedProvidedNeighbours(false);
|
|
825 |
node.setHighlightedArchetype(false);
|
839 |
826 |
}, this);
|
840 |
827 |
|
841 |
828 |
// dim and unhighlight all edges
|
842 |
829 |
app.edgeList.forEach(function(edge) {
|
843 |
|
edge.setHidden(edge.getFrom().isExcluded() || edge.getTo().isExcluded());
|
844 |
830 |
edge.setDimmed(true);
|
845 |
831 |
|
846 |
832 |
edge.setHighlighted(false);
|
... | ... | |
848 |
834 |
edge.setHighlightedProvided(false);
|
849 |
835 |
});
|
850 |
836 |
|
851 |
|
// highlight required neighbours
|
852 |
|
inEdgeList.forEach(function(edge) {
|
853 |
|
edge.setHidden(false);
|
854 |
|
edge.setDimmed(false);
|
855 |
|
edge.setHighlightedRequired(true);
|
856 |
|
|
857 |
|
edge.getFrom().setDimmed(false);
|
858 |
|
edge.getFrom().setHighlightedRequired(true);
|
859 |
|
});
|
860 |
|
|
861 |
|
// highlight provided neighbours
|
862 |
|
outEdgeList.forEach(function(edge) {
|
863 |
|
edge.setHidden(false);
|
864 |
|
edge.setDimmed(false);
|
865 |
|
edge.setHighlightedProvided(true);
|
866 |
|
|
867 |
|
edge.getTo().setDimmed(false);
|
868 |
|
edge.getTo().setHighlightedProvided(true);
|
869 |
|
});
|
870 |
|
|
871 |
837 |
} else {
|
872 |
838 |
app.nodeList.forEach(function(node) {
|
|
839 |
if (node === this) return;
|
|
840 |
|
873 |
841 |
node.setDimmed(false);
|
874 |
842 |
|
875 |
843 |
node.setHighlighted(false);
|
876 |
844 |
node.setHighlightedRequired(false);
|
877 |
845 |
node.setHighlightedProvided(false);
|
878 |
|
node.setHighlightedRequiredNeighbours(false);
|
879 |
|
node.setHighlightedProvidedNeighbours(false);
|
|
846 |
node.setHighlightedArchetype(false);
|
880 |
847 |
}, this);
|
881 |
848 |
|
882 |
849 |
app.edgeList.forEach(function(edge) {
|
883 |
850 |
edge.setHidden(edge.getFrom().isExcluded() || edge.getTo().isExcluded());
|
|
851 |
|
884 |
852 |
edge.setDimmed(false);
|
885 |
853 |
|
886 |
854 |
edge.setHighlighted(false);
|
... | ... | |
894 |
862 |
* Highlights only neighbours of the vertex that are required.
|
895 |
863 |
*/
|
896 |
864 |
function highlightRequiredNeighbours() {
|
897 |
|
if (highlighted) {
|
898 |
|
inEdgeList.forEach(function(edge) {
|
899 |
|
edge.setHidden(false);
|
900 |
|
edge.setHighlightedRequired(true);
|
901 |
|
edge.getFrom().setHighlightedRequired(true);
|
902 |
|
});
|
|
865 |
if (highlightedRequiredNeighbours === false) return;
|
903 |
866 |
|
904 |
|
} else {
|
905 |
|
inEdgeList.forEach(function(edge) {
|
906 |
|
edge.setHidden(true);
|
907 |
|
edge.setHighlightedRequired(false);
|
908 |
|
edge.getFrom().setHighlightedRequired(false);
|
909 |
|
});
|
910 |
|
}
|
|
867 |
inEdgeList.forEach(function(edge) {
|
|
868 |
edge.setHidden(false);
|
|
869 |
|
|
870 |
edge.setDimmed(false);
|
|
871 |
edge.getFrom().setDimmed(false);
|
|
872 |
|
|
873 |
edge.setHighlightedRequired(true);
|
|
874 |
edge.getFrom().setHighlightedRequired(true);
|
|
875 |
});
|
911 |
876 |
}
|
912 |
877 |
|
913 |
878 |
/**
|
914 |
879 |
* Highlights only neighbours of the vertex that are provided.
|
915 |
880 |
*/
|
916 |
881 |
function highlightProvidedNeighbours() {
|
917 |
|
if (highlighted) {
|
918 |
|
outEdgeList.filter(function(edge) {
|
919 |
|
return !edge.getTo().isExcluded();
|
920 |
|
}).forEach(function(edge) {
|
921 |
|
edge.setHidden(false);
|
922 |
|
edge.setHighlightedProvided(true);
|
923 |
|
edge.getTo().setHighlightedProvided(true);
|
924 |
|
});
|
|
882 |
if (highlightedProvidedNeighbours === false) return;
|
925 |
883 |
|
926 |
|
} else {
|
927 |
|
outEdgeList.filter(function(edge) {
|
928 |
|
return !edge.getTo().isExcluded();
|
929 |
|
}).forEach(function(edge) {
|
930 |
|
edge.setHidden(true);
|
931 |
|
edge.setHighlightedProvided(false);
|
932 |
|
edge.getTo().setHighlightedProvided(false);
|
933 |
|
});
|
934 |
|
}
|
|
884 |
outEdgeList.forEach(function(edge) {
|
|
885 |
edge.setHidden(false);
|
|
886 |
|
|
887 |
edge.setDimmed(false);
|
|
888 |
edge.getTo().setDimmed(false);
|
|
889 |
|
|
890 |
edge.setHighlightedProvided(true);
|
|
891 |
edge.getTo().setHighlightedProvided(true);
|
|
892 |
});
|
|
893 |
}
|
|
894 |
|
|
895 |
/**
|
|
896 |
* Highlights only neighbours of the vertex that are instances of the archetype.
|
|
897 |
* @param {integer} archetypeIndex Index of the vertex archetype.
|
|
898 |
*/
|
|
899 |
function highlightArchetypeNeighbours(archetypeIndex) {
|
|
900 |
if (highlightedArchetypeNeighbours === false) return;
|
|
901 |
|
|
902 |
inEdgeList.filter(function(edge) {
|
|
903 |
return edge.getFrom().archetype === archetypeIndex;
|
|
904 |
}).forEach(function(edge) {
|
|
905 |
edge.setHidden(false);
|
|
906 |
|
|
907 |
edge.setDimmed(false);
|
|
908 |
edge.getFrom().setDimmed(false);
|
|
909 |
|
|
910 |
edge.getFrom().setHighlightedArchetype(true);
|
|
911 |
});
|
|
912 |
|
|
913 |
outEdgeList.filter(function(edge) {
|
|
914 |
return edge.getTo().archetype === archetypeIndex;
|
|
915 |
}).forEach(function(edge) {
|
|
916 |
edge.setHidden(false);
|
|
917 |
|
|
918 |
edge.setDimmed(false);
|
|
919 |
edge.getTo().setDimmed(false);
|
|
920 |
|
|
921 |
edge.getTo().setHighlightedArchetype(true);
|
|
922 |
});
|
935 |
923 |
}
|
936 |
924 |
}
|
Vertex related archetypes highlighting, refactoring of the whole highlighting functionality