Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layout cycle while drag spliiter #366

Closed
Tulesha opened this issue Oct 7, 2024 · 2 comments · Fixed by #367
Closed

Layout cycle while drag spliiter #366

Tulesha opened this issue Oct 7, 2024 · 2 comments · Fixed by #367

Comments

@Tulesha
Copy link

Tulesha commented Oct 7, 2024

While dragging splitter, application freezes with Layout cycling. You can see this behaviour on video:

Dock.freezes.mp4

Output log prints this:

[Layout]Layout cycle detected. Item 'Avalonia.Controls.ProportionalStackPanel' was enqueued '10' times. (LayoutQueue`1 #29194114)

After research of reason of this bug, I noticed that this behaviour starts after #322 pull request.

As solution for this bug is delete AffectsParentMeasure and AffectsParentArrange in ProportionalStackPanel, and call InvalidateMeasure and InvalidateArrange of the panel in ProportionalStackPanelSplitter.SetTargetProportion method.

Code:
ProportionalStackPanel.cs

...

    static ProportionalStackPanel()
    {
        AffectsParentMeasure<ProportionalStackPanel>(IsCollapsedProperty);
        AffectsParentArrange<ProportionalStackPanel>(IsCollapsedProperty);

        // Delete this two
        // AffectsParentMeasure<ProportionalStackPanel>(ProportionProperty);
        // AffectsParentArrange<ProportionalStackPanel>(ProportionProperty);
    }

...

ProportionalStackPanelSplitter.axaml.cs

...

    private void SetTargetProportion(double dragDelta)
    {
        var panel = GetPanel();
        if (panel == null)
        {
            return;
        }
        
        var target = GetTargetElement(panel);
        if (target is null)
        {
            return;
        }

        var child = FindNextChild(panel);

        var targetElementProportion = ProportionalStackPanel.GetProportion(target);
        var neighbourProportion = child is not null ? ProportionalStackPanel.GetProportion(child) : double.NaN;

        var dProportion = dragDelta / (panel.Orientation == Orientation.Vertical ? panel.Bounds.Height : panel.Bounds.Width);

        if (targetElementProportion + dProportion < 0)
        {
            dProportion = -targetElementProportion;
        }

        if (neighbourProportion - dProportion < 0)
        {
            dProportion = +neighbourProportion;
        }

        targetElementProportion += dProportion;
        neighbourProportion -= dProportion;

        var minProportion = GetValue(MinimumProportionSizeProperty) / (panel.Orientation == Orientation.Vertical ? panel.Bounds.Height : panel.Bounds.Width);

        if (targetElementProportion < minProportion)
        {
            dProportion = targetElementProportion - minProportion;
            neighbourProportion += dProportion;
            targetElementProportion -= dProportion;

        }
        else if (neighbourProportion < minProportion)
        {
            dProportion = neighbourProportion - minProportion;
            neighbourProportion -= dProportion;
            targetElementProportion += dProportion;
        }

        ProportionalStackPanel.SetProportion(target, targetElementProportion);

        if (child is not null)
        {
            ProportionalStackPanel.SetProportion(child, neighbourProportion);
        }

        // Invalidate Measure and Arrange of the panel
        panel.InvalidateMeasure();
        panel.InvalidateArrange();
    }
...

I know that this bug isn't on your side and maybe it will disappear with new version of Avalonia, but it ruins the user experience and is very annoying for now.

Dock Version: 11.1.0.3
OS: Windows 11

@BAndysc
Copy link
Contributor

BAndysc commented Oct 7, 2024

Technically, the bug was on my side, because Proportion is changed from MeasureOverride and InvalidateMeasure from within MeasureOverride is not allowed. Your solution works, but I think the ProportionProperty should stay "AffectsParentMeasure/Arrange", so that changes from the outside could trigger the relayout.
My idea: #367

@Tulesha
Copy link
Author

Tulesha commented Oct 7, 2024

@BAndysc, looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants