private LinearLayoutBuilder StartFlowLayout(LinearLayoutDirection layoutDirection, LinearLayoutDirection?flowDirection = null)
        {
            var layout = builder.LinearLayout(layoutDirection, flowDirection);

            layout.Flow = true;
            return(layout);
        }
        /*
         * Calculates transform matrix from layout coordinate system to view coordinate system.
         */
        private static Matrix2d LayoutTransform(RectangleF bounds, LinearLayoutDirection layoutDirection, LinearLayoutDirection flowDirection)
        {
            switch (layoutDirection)
            {
            case LinearLayoutDirection.LeftRight:
                switch (flowDirection)
                {
                case LinearLayoutDirection.TopBottom:
                    return(new Matrix2d());

                case LinearLayoutDirection.BottomTop:
                    return(Matrix2d.Translation(0, bounds.Height) * Matrix2d.Stretch(1, -1));
                }
                break;

            case LinearLayoutDirection.RightLeft:
                switch (flowDirection)
                {
                case LinearLayoutDirection.TopBottom:
                    return(Matrix2d.Translation(bounds.Width, 0) * Matrix2d.Stretch(-1, 1));

                case LinearLayoutDirection.BottomTop:
                    return(Matrix2d.Translation(bounds.Width, bounds.Height) * Matrix2d.Stretch(-1, -1));
                }
                break;

            case LinearLayoutDirection.TopBottom:
                switch (flowDirection)
                {
                case LinearLayoutDirection.LeftRight:
                    return(Matrix2d.Rotation(90) * Matrix2d.Stretch(1, -1));

                case LinearLayoutDirection.RightLeft:
                    return(Matrix2d.Translation(bounds.Width, 0) * Matrix2d.Rotation(90));
                }
                break;

            case LinearLayoutDirection.BottomTop:
                switch (flowDirection)
                {
                case LinearLayoutDirection.LeftRight:
                    return(Matrix2d.Translation(0, bounds.Height) * Matrix2d.Rotation(-90));

                case LinearLayoutDirection.RightLeft:
                    return(Matrix2d.Translation(bounds.Width, bounds.Height) * Matrix2d.Stretch(-1, 1) * Matrix2d.Rotation(-90));
                }
                break;
            }
            var message = $"Layout direction {layoutDirection} is not compatible with flow direction {flowDirection}";

            throw new ArgumentException(message);
        }
        public LinearLayoutBuilder(LayoutBuilder layoutBuilder, LinearLayoutDirection layoutDirection, LinearLayoutDirection?flowDirection = null, RectangleF?bounds = null)
        {
            Assert.Argument(layoutBuilder, nameof(layoutBuilder)).NotNull();
            flowDirection  = flowDirection ?? DefaultFlowDirection(layoutDirection);
            _layoutBuilder = layoutBuilder;
            _maxSize       = 0;
            var layoutBounds = bounds ?? _layoutBuilder.OuterBounds;

            _layoutBounds      = new RectangleF(layoutBounds.Location, SizeF.Empty);
            _layoutToView      = LayoutTransform(layoutBounds, layoutDirection, flowDirection.Value);
            _viewToLayout      = _layoutToView.Inverted();
            _layoutSpaceBounds = _viewToLayout.Transform(layoutBounds);
            _layoutOrigin      = _layoutSpaceBounds.Location;
        }
        private static LinearLayoutDirection DefaultFlowDirection(LinearLayoutDirection layoutDirection)
        {
            switch (layoutDirection)
            {
            case LinearLayoutDirection.LeftRight:
                return(LinearLayoutDirection.TopBottom);

            case LinearLayoutDirection.TopBottom:
                return(LinearLayoutDirection.LeftRight);

            case LinearLayoutDirection.RightLeft:
                return(LinearLayoutDirection.TopBottom);

            case LinearLayoutDirection.BottomTop:
                return(LinearLayoutDirection.LeftRight);

            default:
                throw new ArgumentException("Unknown layout direction");
            }
        }