Пример #1
0
        protected internal virtual void ComputeStyleChildren(ProcessLayoutContext ctx)
        {
            var length   = Children.Count;
            var children = Children;

            for (var i = 0; i < length; i++)
            {
                children[i].ComputeStyle(ctx);
            }
        }
Пример #2
0
        private protected Box GetParentBlockBox(ProcessLayoutContext ctx)
        {
            var el = GetParentBlockElement(ctx);

            if (el == null)
            {
                return(ctx.GlobalContext !.GlobalViewPort);
            }

            return(el.ClientRect);
        }
Пример #3
0
        internal StyleValue Normalize(ProcessLayoutContext ctx, Axis axis)
        {
            var value = this;

            switch (Unit)
            {
            case StyleUnit.Percentage:
                value.Number = (ctx.LocalViewPort.Size(axis) / 100) * Number;
                value.Unit   = StyleUnit.Pixel;
                break;
            }
            return(value);
        }
Пример #4
0
        private protected Element?GetParentBlockElement(ProcessLayoutContext ctx)
        {
            var p = Parent;

            while (p != null)
            {
                if (p.ResolvedStyle.Position == StylePosition.Absolute)
                {
                    return(p);
                }

                p = p.Parent;
            }

            return(null);
        }
Пример #5
0
        protected internal virtual void ComputeBoundsChildren(ProcessLayoutContext ctx)
        {
            var length = Children.Count;

            if (length == 0)
            {
                return;
            }

            var children = Children;

            for (var i = 0; i < length; i++)
            {
                var child = children[i];
                child.ProcessLayoutContext.LocalViewPort = ClientRect;
                child.CallComputeBounds(ctx.GlobalContext !);
            }
        }
Пример #6
0
        protected internal virtual void ComputeStyle(ProcessLayoutContext ctx)
        {
            var style    = Style;
            var resolved = ResolvedStyle;

            if (style._BoundingChanged)
            {
                resolved._Size        = style._Size.Normalize(ctx);
                resolved._MinSize     = style._MinSize.Normalize(ctx);
                resolved._MaxSize     = style._MaxSize.Normalize(ctx);
                resolved._Margin      = style._Margin.Normalize(ctx);
                resolved._Padding     = style._Padding.Normalize(ctx);
                resolved._BorderWidth = style._BorderWidth.Normalize(ctx);
                resolved._Anchors     = style._Anchors.Normalize(ctx);
            }

            resolved.Position   = style.Position;
            resolved.Display    = style.Display;
            resolved.Visibility = style.Visibility;

            ComputeStyleChildren(ctx);
        }
Пример #7
0
 internal StyleSize Normalize(ProcessLayoutContext ctx)
 {
     return(new StyleSize(
                Width.Normalize(ctx, Axis.X),
                Height.Normalize(ctx, Axis.Y)));
 }
Пример #8
0
 protected internal virtual void ComputeBounds(ProcessLayoutContext ctx)
 {
     ComputeBoundsSelf(ctx);
     ComputeBoundsChildren(ctx);
 }
Пример #9
0
        protected internal virtual void ComputeBoundsSelf(ProcessLayoutContext ctx)
        {
            if (PassThrough)
            {
                return;
            }

            //OuterRect = ctx.LocalViewPort;

            Box relMargin  = ResolvedStyle._Margin.ToBox();
            Box relBorder  = ResolvedStyle._BorderWidth.ToBox();
            Box relPadding = ResolvedStyle._Padding.ToBox();

            Size relSize    = ResolvedStyle._Size.ToSize();
            Size relMinSize = ResolvedStyle._MinSize.ToSize();
            Size relMaxSize = ResolvedStyle._MaxSize.ToSize();

            // top | left
            Span <bool> normalDirection = stackalloc bool[2];

            // Debug
            const int axisStart = 0;
            const int axisCount = 2;

            const int MIN = 0; // Left or Top
            const int MAX = 2; // Right or Bottom

            /*
             *  Anchors: Left, Top, Right, Bottom
             *
             *  position affects position (x, y) and flow of subsequent elements.
             *  it does not affect the dimensions of the box.
             *
             *  if position == static:
             *  must ignore Anchors!
             *
             *  if position == absolute:
             *  MUST ignore Display, except Display.None
             *
             *  Display affects Box-Calculation
             *
             *  If Display == Inline:
             *  MUST ignore Size, take the inner content as it is.
             *
             */

            var decorationSize = new Size(
                relMargin.LeftRight + relBorder.LeftRight + relPadding.LeftRight,
                relMargin.TopBottom + relBorder.TopBottom + relPadding.TopBottom);

            var flow = ResolvedStyle.Position is StylePosition.Static or StylePosition.Relative;

            if (flow)
            {
                // in flow

                if (ResolvedStyle.Display != StyleDisplay.Inline)
                {
                    // StyleDisplay.Inline are typically Text spans, that are converted to
                    // one ore more TextElementFracment / StyleDisplay.InlineBlock

                    if (Parent == null)
#pragma warning disable HAA0601 // Value type to reference type conversion causing boxing allocation
                    {
                        throw new Exception($"Elements with Display.{ResolvedStyle.Display} must be inside of a block element.");
                    }
#pragma warning restore HAA0601 // Value type to reference type conversion causing boxing allocation

                    var el = GetParentBlockElement(ctx);
                    if (el != null)
                    {
                        Box absAnchors = el.ClientRect;
                        var absCenter  = absAnchors.Center;

                        absAnchors.Width  = relSize.Width + decorationSize.Width;
                        absAnchors.Height = relSize.Height + decorationSize.Height;

                        var pc = el.ProcessLayoutContext;
                        if (absAnchors.Right + pc.RowPosition.X > el.ClientRect.Right || ResolvedStyle.Display == StyleDisplay.Block) // OuterRect.Right
                        {
                            pc.RowElements.Clear();
                            pc.RowPosition.Y += pc.RowHeight;
                            pc.RowPosition.X  = 0;
                            pc.RowHeight      = absAnchors.Height;
                        }
                        else if (absAnchors.Height > pc.RowHeight)
                        {
                            var diff         = absAnchors.Height - pc.RowHeight;
                            var prevElLength = pc.RowElements.Count;
                            for (var i = 0; i < prevElLength; i++)
                            {
                                var prevEl = pc.RowElements[i];
                                prevEl.TranslateY(diff);
                            }
                            pc.RowHeight = absAnchors.Height;
                        }

                        absAnchors.Translate(pc.RowPosition.X, pc.RowPosition.Y + (pc.RowHeight - absAnchors.Height));

                        MarginRect  = absAnchors;
                        BorderRect  = MarginRect.Substract(relMargin);
                        PaddingRect = BorderRect.Substract(relBorder);
                        ClientRect  = PaddingRect.Substract(relPadding);

                        pc.RowPosition.X += absAnchors.Width;
                        //pc.RowHeight = absAnchors.Height;
                        pc.RowElements.Add(this);
                    }
                }
            }
            else // flow == false:
            {
                Box absAnchors = Parent != null ? Parent.ClientRect : ctx.GlobalContext !.GlobalViewPort;
                var absCenter  = absAnchors.Center;

                // Because we don't have flow, both axis behave exactly the same,
                // so we can reduce code
                for (var a = axisStart; a < axisCount; a++)
                {
                    normalDirection[a] = true;
                    var ax = (Axis)a;

                    if (ResolvedStyle._Anchors[MIN + a].HasValue() && ResolvedStyle._Anchors[MAX + a].HasValue())
                    {
                        absAnchors[MIN + a] += ResolvedStyle._Anchors[MIN + a].Number;
                        absAnchors[MAX + a] -= ResolvedStyle._Anchors[MAX + a].Number;
                    }
                    else
                    {
                        var diffHeight = relSize[a] + decorationSize[a];
                        if (ResolvedStyle._Margin[MIN + a].Unit == StyleUnit.Auto &&
                            ResolvedStyle._Margin[MAX + a].Unit == StyleUnit.Auto)
                        {
                            var size     = diffHeight;
                            var halfSize = size / 2;

                            absAnchors[MIN + a] = absCenter[a] - halfSize;
                            absAnchors[MAX + a] = absCenter[a] + halfSize;
                        }
                        else
                        {
                            if (ResolvedStyle._Anchors[MIN + a].HasValue())
                            {
                                absAnchors[MIN + a] += ResolvedStyle._Anchors[MIN + a].Number;
                                absAnchors[MAX + a]  = absAnchors[MIN + a] + diffHeight;
                            }
                            else if (ResolvedStyle._Anchors[MAX + a].HasValue())
                            {
                                normalDirection[a]   = false;
                                absAnchors[MAX + a] -= ResolvedStyle._Anchors[MAX + a].Number;
                                absAnchors[MIN + a]  = absAnchors[MAX + a] - diffHeight;
                            }
                            else
                            {
                                absAnchors[MAX + a] = absAnchors[MIN + a] + diffHeight;
                            }
                        }
                    }
                }

                MarginRect  = absAnchors;
                BorderRect  = MarginRect.Substract(relMargin);
                PaddingRect = BorderRect.Substract(relBorder);
                ClientRect  = PaddingRect.Substract(relPadding);

                for (var a = axisStart; a < axisCount; a++)
                {
                    normalDirection[a] = true;
                    var ax = (Axis)a;

                    if (ResolvedStyle.MaxSize[a].HasValue() && ClientRect.Size(ax) > relMaxSize[a])
                    {
                        var diff = ClientRect.Size(ax) - relMaxSize[a];
                        if (normalDirection[a])
                        {
                            ClientRect[MAX + a]  -= diff;
                            PaddingRect[MAX + a] -= diff;
                            BorderRect[MAX + a]  -= diff;
                            MarginRect[MAX + a]  -= diff;
                        }
                        else
                        {
                            ClientRect[MIN + a]  += diff;
                            PaddingRect[MIN + a] += diff;
                            BorderRect[MIN + a]  += diff;
                            MarginRect[MIN + a]  += diff;
                        }
                    }

                    if (ResolvedStyle.MinSize[a].HasValue() && ClientRect.Size(ax) < relMinSize[a])
                    {
                        var diff = relMinSize[a] - ClientRect.Size(ax);
                        if (normalDirection[a])
                        {
                            ClientRect[MAX + a]  += diff;
                            PaddingRect[MAX + a] += diff;
                            BorderRect[MAX + a]  += diff;
                            MarginRect[MAX + a]  += diff;
                        }
                        else
                        {
                            ClientRect[MIN + a]  -= diff;
                            PaddingRect[MIN + a] -= diff;
                            BorderRect[MIN + a]  -= diff;
                            MarginRect[MIN + a]  -= diff;
                        }
                    }
                }
            } // flow
        }
Пример #10
0
 protected internal virtual void ComputeChildBoundsOffers(ProcessLayoutContext ctx)
 {
 }