in src/legend/svgLegend.ts [729:824]
private calculateHorizontalLayout(dataPoints: LegendDataPoint[], title: TitleLayout, navigationArrows: NavigationArrow[]): number {
let fontSizeBiggerThanDefault = this.legendFontSizeMarginDifference > 0;
let fontSizeMargin = fontSizeBiggerThanDefault
? SVGLegend.TextAndIconPadding + this.legendFontSizeMarginDifference
: SVGLegend.TextAndIconPadding;
let occupiedWidth = 0;
const firstDataPointMarkerShape: MarkerShape = dataPoints && dataPoints[0] && dataPoints[0].markerShape;
let iconTotalItemPadding = this.getMarkerShapeWidth(firstDataPointMarkerShape) + fontSizeMargin * 1.5;
let numberOfItems: number = dataPoints.length;
// get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text
let defaultTextProperties = SVGLegend.getTextProperties("", this.data.fontSize, this.data.fontFamily);
let verticalCenter = this.viewport.height / 2;
let textYCoordinate = verticalCenter + textMeasurementService.estimateSvgTextHeight(defaultTextProperties) / 2
- textMeasurementService.estimateSvgTextBaselineDelta(defaultTextProperties);
if (title) {
occupiedWidth += title.width;
// get the Y coordinate which is the middle of the container + the middle of the text height - the delta of the text
title.y = verticalCenter
+ title.height / 2
- textMeasurementService.estimateSvgTextBaselineDelta(SVGLegend.getTextProperties(title.text, this.data.fontSize, this.data.fontFamily));
}
// if an arrow should be added, we add space for it
if (this.legendDataStartIndex > 0) {
occupiedWidth += SVGLegend.LegendArrowOffset;
}
// Calculate the width for each of the legend items
let dataPointsLength = dataPoints.length;
let availableWidth = this.parentViewport.width - occupiedWidth;
let legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(
dataPoints,
availableWidth,
iconTotalItemPadding,
this.data.fontSize,
this.data.fontFamily,
);
numberOfItems = legendItems.length;
// If we can"t show all the legend items, subtract the "next" arrow space from the available space and re-run the width calculations
if (numberOfItems !== dataPointsLength) {
availableWidth -= SVGLegend.LegendArrowOffset;
legendItems = SVGLegend.calculateHorizontalLegendItemsWidths(
dataPoints,
availableWidth,
iconTotalItemPadding,
this.data.fontSize,
this.data.fontFamily,
);
numberOfItems = legendItems.length;
}
for (let legendItem of legendItems) {
const { dataPoint } = legendItem;
const markerShapeWidth: number = this.getMarkerShapeWidth(dataPoint.markerShape);
dataPoint.glyphPosition = {
// the space taken so far + the radius + the margin / radiusFactor to prevent huge spaces
x: occupiedWidth + markerShapeWidth / 2 + (this.legendFontSizeMarginDifference / this.getLegendIconFactor(dataPoint.markerShape)),
// The middle of the container but a bit lower due to text not being in the middle (qP for example making middle between q and P)
y: this.viewport.height * SVGLegend.LegendIconYRatio,
};
const fixedTextShift = (fontSizeMargin / (this.getLegendIconFactor(dataPoint.markerShape) / 2)) + markerShapeWidth;
dataPoint.textPosition = {
x: occupiedWidth + fixedTextShift,
y: textYCoordinate,
};
// If we're over the max width, process it so it fits
if (legendItem.desiredOverMaxWidth) {
let textWidth = legendItem.width - iconTotalItemPadding;
dataPoint.label = textMeasurementService.getTailoredTextOrDefault(legendItem.textProperties, textWidth);
}
occupiedWidth += legendItem.width;
}
this.visibleLegendWidth = occupiedWidth;
this.updateNavigationArrowLayout(navigationArrows, dataPointsLength, numberOfItems);
return numberOfItems;
}