in src/legend/svgLegend.ts [861:959]
private calculateVerticalLayout(
dataPoints: LegendDataPoint[],
title: TitleLayout,
navigationArrows: NavigationArrow[],
autoWidth: boolean
): number {
// check if we need more space for the margin, or use the default text padding
let fontSizeBiggerThenDefault = this.legendFontSizeMarginDifference > 0;
let fontFactor = fontSizeBiggerThenDefault ? this.legendFontSizeMarginDifference : 0;
// calculate the size needed after font size change
let verticalLegendHeight = 20 + fontFactor;
let spaceNeededByTitle = 15 + fontFactor;
let extraShiftForTextAlignmentToIcon = 4 + fontFactor;
let totalSpaceOccupiedThusFar = verticalLegendHeight;
// the default space for text and icon radius + the margin after the font size change
const firstDataPointMarkerShape: MarkerShape = dataPoints && dataPoints[0] && dataPoints[0].markerShape;
const fixedHorizontalIconShift: number = SVGLegend.TextAndIconPadding
+ this.getMarkerShapeWidth(firstDataPointMarkerShape) / 2
+ this.legendFontSizeMarginDifference;
let fixedHorizontalTextShift = fixedHorizontalIconShift * 2;
// check how much space is needed
let maxHorizontalSpaceAvaliable = autoWidth
? this.parentViewport.width * SVGLegend.LegendMaxWidthFactor
- fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth
: this.lastCalculatedWidth
- fixedHorizontalTextShift - SVGLegend.LegendEdgeMariginWidth;
let numberOfItems: number = dataPoints.length;
let maxHorizontalSpaceUsed = 0;
let parentHeight = this.parentViewport.height;
if (title) {
totalSpaceOccupiedThusFar += spaceNeededByTitle;
title.x = SVGLegend.TextAndIconPadding;
title.y = spaceNeededByTitle;
maxHorizontalSpaceUsed = title.width || 0;
}
// if an arrow should be added, we add space for it
if (this.legendDataStartIndex > 0)
totalSpaceOccupiedThusFar += SVGLegend.LegendArrowOffset;
let dataPointsLength = dataPoints.length;
for (let i = 0; i < dataPointsLength; i++) {
let dp = dataPoints[i];
let textProperties = SVGLegend.getTextProperties(dp.label, this.data.fontSize, this.data.fontFamily);
dp.glyphPosition = {
x: fixedHorizontalIconShift,
y: (totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon) - textMeasurementService.estimateSvgTextBaselineDelta(textProperties)
};
dp.textPosition = {
x: fixedHorizontalTextShift,
y: totalSpaceOccupiedThusFar + extraShiftForTextAlignmentToIcon
};
// TODO: [PERF] Get rid of this extra measurement, and modify
// getTailoredTextToReturnWidth + Text
let width = textMeasurementService.measureSvgTextWidth(textProperties);
if (width > maxHorizontalSpaceUsed) {
maxHorizontalSpaceUsed = width;
}
if (width > maxHorizontalSpaceAvaliable) {
let text = textMeasurementService.getTailoredTextOrDefault(
textProperties,
maxHorizontalSpaceAvaliable);
dp.label = text;
}
totalSpaceOccupiedThusFar += verticalLegendHeight;
if (totalSpaceOccupiedThusFar > parentHeight) {
numberOfItems = i;
break;
}
}
if (autoWidth) {
if (maxHorizontalSpaceUsed < maxHorizontalSpaceAvaliable) {
this.lastCalculatedWidth = this.viewport.width = Math.ceil(maxHorizontalSpaceUsed + fixedHorizontalTextShift + SVGLegend.LegendEdgeMariginWidth);
} else {
this.lastCalculatedWidth = this.viewport.width = Math.ceil(this.parentViewport.width * SVGLegend.LegendMaxWidthFactor);
}
}
else {
this.viewport.width = this.lastCalculatedWidth;
}
this.visibleLegendHeight = totalSpaceOccupiedThusFar;
navigationArrows.forEach(d => d.x = this.lastCalculatedWidth / 2);
this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);
return numberOfItems;
}