import { isDefined } from 'ts-is-present';
import { Edge } from '../types/Edge';
import { Link } from '../renderables/Link';
import { Labeller } from './Labeller';
type LabelPlacement = 'center' | 'join' | 'spread';
class LinkLabeller extends Labeller {
private _linkMap: Map;
private _placement: LabelPlacement;
constructor () {
super();
this._linkMap = new Map();
this._placement = 'spread';
}
getPlacement (): LabelPlacement {
return this._placement;
}
setLinkMap (links: Map) {
this._linkMap = links;
}
setPlacement (placement: LabelPlacement): void {
this._placement = placement;
}
update (): void {
if (this._placement === 'center') this._buildCenterLabels();
if (this._placement === 'join') this._buildJoinLabels();
if (this._placement === 'spread') this._buildSpreadLabels();
}
_bezierBounds (np: number): [number, number] {
if (np < 1) return [0.5, 0];
const dt = Math.min(0.8 / (np - 1), 0.1);
const size = Math.min(dt * (np - 1), 0.8);
const b = 0.5 - size / 2;
return [b, dt];
}
_buildCenterLabels (): void {
this._linkMap.forEach((edges: Edge[], link: Link) => {
link.labels = edges
.filter(edge => isDefined(edge.label))
.map(edge => ({
t: 0.5,
text: edge.label!
}));
})
}
_buildJoinLabels (): void {
this._linkMap.forEach((edges: Edge[], link: Link) => {
link.labels = [{
text: buildCombinedLabel(edges),
t: 0.5
}];
});
}
_buildSpreadLabels (): void {
this._linkMap.forEach((edges: Edge[], link: Link) => {
if (edges.length) {
const [b, dt] = this._bezierBounds(edges.length);
link.labels = edges
.filter(edge => isDefined(edge.label))
.map((edge, index) => ({
t: b + index * dt,
text: edge.label!
}));
}
});
}
}
function buildCombinedLabel (edges: Edge[]): string {
return edges
.map(edge => edge.label)
.filter(isDefined)
.join(', ');
}
export {
LabelPlacement,
LinkLabeller
}