<commit_before>
// TODO: If window is made embedded, remove window sizing nodes

namespace WM
{
    export enum Side
    {
        Left,
        Right,
        Top,
        Bottom,
        None,
    }

    class Rect
    {
        // Only for DebugLog
        Title: string;

        // Source control for copying simulation back
        Control: Control;

        Left: number;
        Right: number;
    }

    class SizeConstraint
    {
        Rect: Rect;
        Size: number;
    }

    class ContainerConstraint
    {
        Rect: Rect;
        Side: Side;
        Position: number;
    }

    class BufferConstraint
    {
        Rect0: Rect;
        Side0: Side;
        Rect1: Rect;
        Side1: Side;
    }

    class Sizer
    {
        ContainerRestSize: number;
        ContainerSize: number;

        Rects: Rect[] = [];

        ContainerConstraints: ContainerConstraint[] = [];
        BufferConstraints: BufferConstraint[] = [];
        SizeConstraints: SizeConstraint[] = [];

        Build(container: Container, control_graph: ControlGraph)
        {
            this.ContainerRestSize = container.ControlParentNode.Size.x;

            // Build the rect list
            for (let control of container.Controls)
            {
                // Anything that's not a control (e.g. a Ruler) still needs an entry in the array, even if it's empty
                if (!(control instanceof Container))
                {
                    this.Rects.push(null);
                    continue;
                }

                // Set initial parameters
                let rect = new Rect();
                rect.Control = control;
                rect.Left = control.TopLeft.x;
                rect.Right = control.BottomRight.x;
                this.Rects.push(rect);

                if (control instanceof Window)
                    rect.Title = (<Window>control).Title;

                // Add a size constraint for each rect
                let size_constraint = new SizeConstraint();
                size_constraint.Rect = rect;
                size_constraint.Size = rect.Right - rect.Left;
                this.SizeConstraints.push(size_constraint);
            }

            // Build the container constraints list
            for (let i = 0; i < container.Controls.length; i++)
            {
                if (control_graph.RefInfos[i * 4 + Side.Left].References(container))
                {
                    let constraint = new ContainerConstraint();
                    constraint.Rect = this.Rects[i];
                    constraint.Side = Side.Left;
                    constraint.Position = 0;
                    this.ContainerConstraints.push(constraint);
                }
                if (control_graph.RefInfos[i * 4 + Side.Right].References(container))
                {
                    let constraint = new ContainerConstraint();
                    constraint.Rect = this.Rects[i];
                    constraint.Side = Side.Right;
                    constraint.Position = this.ContainerRestSize;
                    this.ContainerConstraints.push(constraint);
                }
            }

            // Build the buffer constraints list
            for (let ref of control_graph.Refs)
            {
                // Only want horizontal refs
                if (ref.Side != Side.Left && ref.Side != Side.Right)
                    continue;

                // There are two refs for each connection; ensure only one of them is used
                if (ref.FromIndex < ref.ToIndex)
                {
                    let constraint = new BufferConstraint();
                    constraint.Rect0 = this.Rects[ref.FromIndex];
                    constraint.Side0 = ref.Side;
                    constraint.Rect1 = this.Rects[ref.ToIndex];
                    constraint.Side1 = ref.Side ^ 1;
                    this.BufferConstraints.push(constraint);
                }
            }
        }

        ChangeSize(new_size: number)
        {
            // Update container constraints with new size
            this.ContainerSize = new_size;
            let half_delta_size = (this.ContainerRestSize - new_size) / 2;
            let left_offset = half_delta_size + Container.SnapBorderSize;
            let right_offset = this.ContainerRestSize - left_offset;
            for (let constraint of this.ContainerConstraints)
            {
                if (constraint.Side == Side.Left)
                    constraint.Position = left_offset;
                else
                    constraint.Position = right_offset;
            }

            for (let i = 0; i < 5; i++)
            {
                this.ApplySizeConstraints();
                this.ApplyContainerConstraints();
                this.ApplyBufferConstraints();
            }

            // Copy simulation back to the controls
            for (let rect of this.Rects)
            {
                rect.Control.Position = new int2(rect.Left - half_delta_size, rect.Control.Position.y);
                rect.Control.Size = new int2(rect.Right - rect.Left, rect.Control.Size.y);
            }
        }

        private ApplyContainerConstraints()
        {
            for (let constraint of this.ContainerConstraints)
            {
                if (constraint.Side == Side.Left)
                    constraint.Rect.Left = constraint.Position;
                else
                    constraint.Rect.Right = constraint.Position;
            }
        }

        private ApplySizeConstraints()
        {
            // TODO: Grow left/right away from the container constraints?

            for (let constraint of this.SizeConstraints)
            {
                let size = constraint.Rect.Right - constraint.Rect.Left;
                let center = (constraint.Rect.Left + constraint.Rect.Right) * 0.5;
                let half_delta_size = (constraint.Size - size) * 0.5;
                constraint.Rect.Left = center - size * 0.5 - half_delta_size * 0.1;
                constraint.Rect.Right = center + size * 0.5 + half_delta_size * 0.1;
            }
        }

        private ApplyBufferConstraints()
        {
            for (let constraint of this.BufferConstraints)
            {
                if (constraint.Side0 == Side.Left)
                {<commit_msg>Playing around with minimum size constraints<commit_after>
// TODO: If window is made embedded, remove window sizing nodes

namespace WM
{
    export enum Side
    {
        Left,
        Right,
        Top,
        Bottom,
        None,
    }

    class Rect
    {
        // Only for DebugLog
        Title: string;

        // Source control for copying simulation back
        Control: Control;

        Left: number;
        Right: number;
    }

    class SizeConstraint
    {
        Rect: Rect;
        Size: number;
    }

    class ContainerConstraint
    {
        Rect: Rect;
        Side: Side;
        Position: number;
    }

    class BufferConstraint
    {
        Rect0: Rect;
        Side0: Side;
        Rect1: Rect;
        Side1: Side;
    }

    class Sizer
    {
        ContainerRestSize: number;
        ContainerSize: number;

        Rects: Rect[] = [];

        ContainerConstraints: ContainerConstraint[] = [];
        BufferConstraints: BufferConstraint[] = [];
        SizeConstraints: SizeConstraint[] = [];

        Build(container: Container, control_graph: ControlGraph)
        {
            this.ContainerRestSize = container.ControlParentNode.Size.x;

            // Build the rect list
            for (let control of container.Controls)
            {
                // Anything that's not a control (e.g. a Ruler) still needs an entry in the array, even if it's empty
                if (!(control instanceof Container))
                {
                    this.Rects.push(null);
                    continue;
                }

                // Set initial parameters
                let rect = new Rect();
                rect.Control = control;
                rect.Left = control.TopLeft.x;
                rect.Right = control.BottomRight.x;
                this.Rects.push(rect);

                if (control instanceof Window)
                    rect.Title = (<Window>control).Title;

                // Add a size constraint for each rect
                let size_constraint = new SizeConstraint();
                size_constraint.Rect = rect;
                size_constraint.Size = rect.Right - rect.Left;
                this.SizeConstraints.push(size_constraint);
            }

            // Build the container constraints list
            for (let i = 0; i < container.Controls.length; i++)
            {
                if (control_graph.RefInfos[i * 4 + Side.Left].References(container))
                {
                    let constraint = new ContainerConstraint();
                    constraint.Rect = this.Rects[i];
                    constraint.Side = Side.Left;
                    constraint.Position = 0;
                    this.ContainerConstraints.push(constraint);
                }
                if (control_graph.RefInfos[i * 4 + Side.Right].References(container))
                {
                    let constraint = new ContainerConstraint();
                    constraint.Rect = this.Rects[i];
                    constraint.Side = Side.Right;
                    constraint.Position = this.ContainerRestSize;
                    this.ContainerConstraints.push(constraint);
                }
            }

            // Build the buffer constraints list
            for (let ref of control_graph.Refs)
            {
                // Only want horizontal refs
                if (ref.Side != Side.Left && ref.Side != Side.Right)
                    continue;

                // There are two refs for each connection; ensure only one of them is used
                if (ref.FromIndex < ref.ToIndex)
                {
                    let constraint = new BufferConstraint();
                    constraint.Rect0 = this.Rects[ref.FromIndex];
                    constraint.Side0 = ref.Side;
                    constraint.Rect1 = this.Rects[ref.ToIndex];
                    constraint.Side1 = ref.Side ^ 1;
                    this.BufferConstraints.push(constraint);
                }
            }
        }

        ChangeSize(new_size: number)
        {
            // Update container constraints with new size
            this.ContainerSize = new_size;
            let half_delta_size = (this.ContainerRestSize - new_size) / 2;
            let left_offset = half_delta_size + Container.SnapBorderSize;
            let right_offset = this.ContainerRestSize - left_offset;
            for (let constraint of this.ContainerConstraints)
            {
                if (constraint.Side == Side.Left)
                    constraint.Position = left_offset;
                else
                    constraint.Position = right_offset;
            }

            for (let i = 0; i < 10; i++)
            {
                this.ApplySizeConstraints();

                this.ApplyMinimumSizeConstraints();
                this.ApplyContainerConstraints();
                this.ApplyBufferConstraints();
                
                this.ApplyMinimumSizeConstraints();
                this.ApplyContainerConstraints();
                this.ApplyBufferConstraints();
            }

            // Copy simulation back to the controls
            for (let rect of this.Rects)
            {
                rect.Control.Position = new int2(rect.Left - half_delta_size, rect.Control.Position.y);
                rect.Control.Size = new int2(rect.Right - rect.Left, rect.Control.Size.y);
            }
        }

        private ApplyContainerConstraints()
        {
            for (let constraint of this.ContainerConstraints)
            {
                if (constraint.Side == Side.Left)
                    constraint.Rect.Left = constraint.Position;
                else
                    constraint.Rect.Right = constraint.Position;
            }
        }

        private ApplySizeConstraints()
        {
            // TODO: Grow left/right away from the container constraints?

            for (let constraint of this.SizeConstraints)
            {
                let rect = constraint.Rect;
                let size = rect.Right - rect.Left;
                let center = (rect.Left + rect.Right) * 0.5;
                let half_delta_size = (constraint.Size - size) * 0.5;
                let half_border_size = size * 0.5 + half_delta_size * 0.1;
                rect.Left = center - half_border_size;
                rect.Right = center + half_border_size;

                if (rect.Right - rect.Left < 20)
                {
                    rect.Left = center - 10;
                    rect.Right = center + 10;
                }
            }
        }

        private ApplyMinimumSizeConstraints()
        {
            for (let constraint of this.SizeConstraints)
            {
                let rect = constraint.Rect;

                if (rect.Right - rect.Left < 20)
                {
                    let center = (rect.Left + rect.Right) * 0.5;
                    rect.Left = center - 10;
                    rect.Right = center + 10;
                }
            }
        }

        private ApplyBufferConstraints()
        {
            for (let constraint of this.BufferConstraints)
            {
                if (constraint.Side0 == Side.Left)
                {
{'fraction_non_alphanumeric': 0.08250092489826119, 'fraction_numerical': 0.005401405845357011, 'mean_word_length': 1.2796424354865914, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5290011', 'n_tokens_mistral': 3352, 'n_tokens_neox': 3087, 'n_words': 809}