private calculateHorizontalLayout()

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;
    }