private calculateVerticalLayout()

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