Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions src/Dock.Model/FactoryBase.Dockable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ namespace Dock.Model;
/// </summary>
public abstract partial class FactoryBase
{
private const double DefaultFloatingWidth = 300;
private const double DefaultFloatingHeight = 400;
private const double MinimumTrackedFloatingSize = 16;

/// <inheritdoc/>
public virtual void AddDockable(IDock dock, IDockable dockable)
{
Expand Down Expand Up @@ -624,6 +628,21 @@ private static bool IsValidSize(double value)
return !double.IsNaN(value) && !double.IsInfinity(value) && value > 0;
}

private static double ResolveFloatingSize(double dockableSize, double ownerSize, double fallbackSize)
{
if (IsValidSize(dockableSize) && dockableSize > MinimumTrackedFloatingSize)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Avoid discarding persisted float sizes under 32px

The new ResolveFloatingSize threshold treats any tracked size <= 32 as uninitialized, so FloatDockable/FloatAllDockables now overwrite legitimate small persisted dimensions every time a dockable is floated again. In practice, if a user intentionally resizes a floating tool/document window to something narrow (for example 24px) and later docks then re-floats it, this code forces owner/default sizing instead of restoring the saved size, which is a regression from the previous NaN-only fallback behavior.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 926f6bd0.

I narrowed the heuristic so we only treat clearly bogus initial tracked sizes as uninitialized by dropping the cutoff from 32 to 16. That preserves legitimate small persisted float sizes like 24x24 while still fixing the first-float tiny-window case.

I also added a regression test covering the preserved-small-size case:

  • FloatDockable_PreservesSmallTrackedDocumentBoundsAboveTinyThreshold

And re-ran the focused sizing tests.

{
return dockableSize;
}

if (IsValidSize(ownerSize) && ownerSize > MinimumTrackedFloatingSize)
{
return ownerSize;
}

return fallbackSize;
}

/// <inheritdoc/>
public virtual void PinDockable(IDockable dockable)
{
Expand Down Expand Up @@ -1016,14 +1035,8 @@ public virtual void FloatDockable(IDockable dockable, DockWindowOptions? options
{
dockablePointerScreenY = !double.IsNaN(dockableY) ? dockableY : !double.IsNaN(ownerY) ? ownerY : 0;
}
if (double.IsNaN(dockableWidth))
{
dockableWidth = double.IsNaN(ownerWidth) ? 300 : ownerWidth;
}
if (double.IsNaN(dockableHeight))
{
dockableHeight = double.IsNaN(ownerHeight) ? 400 : ownerHeight;
}
dockableWidth = ResolveFloatingSize(dockableWidth, ownerWidth, DefaultFloatingWidth);
dockableHeight = ResolveFloatingSize(dockableHeight, ownerHeight, DefaultFloatingHeight);

PrepareWindowOptionsForDockable(dockable, options);
SplitToWindow(dock, dockable, dockablePointerScreenX, dockablePointerScreenY, dockableWidth, dockableHeight, options);
Expand Down Expand Up @@ -1070,8 +1083,8 @@ public virtual void FloatAllDockables(IDockable dockable, DockWindowOptions? opt
pointerY = !double.IsNaN(ownerY) ? ownerY : 0;
}

var width = double.IsNaN(ownerWidth) ? 300 : ownerWidth;
var height = double.IsNaN(ownerHeight) ? 400 : ownerHeight;
var width = ResolveFloatingSize(double.NaN, ownerWidth, DefaultFloatingWidth);
var height = ResolveFloatingSize(double.NaN, ownerHeight, DefaultFloatingHeight);

IDock targetDock = dock switch
{
Expand Down
60 changes: 60 additions & 0 deletions tests/Dock.Avalonia.HeadlessTests/FactoryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ namespace Dock.Avalonia.HeadlessTests;

public class FactoryTests
{
private sealed class RecordingFloatFactory : TestFactory
{
public double? SplitWidth { get; private set; }
public double? SplitHeight { get; private set; }

public override void SplitToWindow(IDock dock, IDockable dockable, double x, double y, double width, double height, DockWindowOptions? options)
{
SplitWidth = width;
SplitHeight = height;
}
}

[AvaloniaFact]
public void TestFactory_Ctor()
{
Expand Down Expand Up @@ -199,6 +211,54 @@ public void DockingState_Transitions_Cover_Docked_Pinned_Document_Floating_And_H
Assert.Equal(DockingWindowState.Document | DockingWindowState.Floating, document.DockingState);
}

[AvaloniaFact]
public void FloatDockable_UsesOwnerSize_WhenTrackedDocumentBoundsAreTiny()
{
var factory = new RecordingFloatFactory();
var root = factory.CreateRootDock();
root.VisibleDockables = factory.CreateList<IDockable>();
root.HiddenDockables = factory.CreateList<IDockable>();
root.Windows = factory.CreateList<IDockWindow>();

var documentDock = factory.CreateDocumentDock();
documentDock.VisibleDockables = factory.CreateList<IDockable>();
documentDock.SetVisibleBounds(0, 0, 900, 700);
factory.AddDockable(root, documentDock);

var document = factory.CreateDocument();
document.SetVisibleBounds(0, 0, 10, 10);
factory.AddDockable(documentDock, document);

factory.FloatDockable(document);

Assert.Equal(900, factory.SplitWidth);
Assert.Equal(700, factory.SplitHeight);
}

[AvaloniaFact]
public void FloatDockable_PreservesSmallTrackedDocumentBoundsAboveTinyThreshold()
{
var factory = new RecordingFloatFactory();
var root = factory.CreateRootDock();
root.VisibleDockables = factory.CreateList<IDockable>();
root.HiddenDockables = factory.CreateList<IDockable>();
root.Windows = factory.CreateList<IDockWindow>();

var documentDock = factory.CreateDocumentDock();
documentDock.VisibleDockables = factory.CreateList<IDockable>();
documentDock.SetVisibleBounds(0, 0, 900, 700);
factory.AddDockable(root, documentDock);

var document = factory.CreateDocument();
document.SetVisibleBounds(0, 0, 24, 24);
factory.AddDockable(documentDock, document);

factory.FloatDockable(document);

Assert.Equal(24, factory.SplitWidth);
Assert.Equal(24, factory.SplitHeight);
}


[AvaloniaFact]
public void DockingState_HiddenContainer_Propagates_To_Descendants()
Expand Down
Loading