diff --git a/src/Dock.Model/FactoryBase.Dockable.cs b/src/Dock.Model/FactoryBase.Dockable.cs index e002a05d0..6b4629972 100644 --- a/src/Dock.Model/FactoryBase.Dockable.cs +++ b/src/Dock.Model/FactoryBase.Dockable.cs @@ -1,4 +1,5 @@ -using Dock.Model.Controls; +using System.Linq; +using Dock.Model.Controls; using Dock.Model.Core; namespace Dock.Model; @@ -13,8 +14,7 @@ public virtual void AddDockable(IDock dock, IDockable dockable) { InitDockable(dockable, dock); dock.VisibleDockables ??= CreateList(); - dock.VisibleDockables.Add(dockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + AddVisibleDockable(dock, dockable); OnDockableAdded(dockable); } @@ -25,8 +25,7 @@ public virtual void InsertDockable(IDock dock, IDockable dockable, int index) { InitDockable(dockable, dock); dock.VisibleDockables ??= CreateList(); - dock.VisibleDockables.Insert(index, dockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + InsertVisibleDockable(dock, index, dockable); OnDockableAdded(dockable); } } @@ -45,8 +44,7 @@ public virtual void RemoveDockable(IDockable dockable, bool collapse) return; } - dock.VisibleDockables.Remove(dockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + RemoveVisibleDockable(dock, dockable); OnDockableRemoved(dockable); var indexActiveDockable = index > 0 ? index - 1 : 0; @@ -102,11 +100,9 @@ public virtual void MoveDockable(IDock dock, IDockable sourceDockable, IDockable if (sourceIndex >= 0 && targetIndex >= 0 && sourceIndex != targetIndex) { - dock.VisibleDockables.RemoveAt(sourceIndex); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + RemoveVisibleDockableAt(dock, sourceIndex); OnDockableRemoved(sourceDockable); - dock.VisibleDockables.Insert(targetIndex, sourceDockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + InsertVisibleDockable(dock, targetIndex, sourceDockable); OnDockableAdded(sourceDockable); OnDockableMoved(sourceDockable); dock.ActiveDockable = sourceDockable; @@ -177,11 +173,9 @@ public virtual void MoveDockable(IDock sourceDock, IDock targetDock, IDockable s var sourceIndex = sourceDock.VisibleDockables.IndexOf(sourceDockable); if (sourceIndex < targetIndex) { - targetDock.VisibleDockables.Insert(targetIndex + 1, sourceDockable); - targetDock.IsEmpty = targetDock.VisibleDockables.Count == 0; + InsertVisibleDockable(targetDock, targetIndex + 1, sourceDockable); OnDockableAdded(sourceDockable); - targetDock.VisibleDockables.RemoveAt(sourceIndex); - targetDock.IsEmpty = targetDock.VisibleDockables.Count == 0; + RemoveVisibleDockableAt(targetDock, sourceIndex); OnDockableRemoved(sourceDockable); OnDockableMoved(sourceDockable); } @@ -190,11 +184,9 @@ public virtual void MoveDockable(IDock sourceDock, IDock targetDock, IDockable s var removeIndex = sourceIndex + 1; if (targetDock.VisibleDockables.Count + 1 > removeIndex) { - targetDock.VisibleDockables.Insert(targetIndex, sourceDockable); - targetDock.IsEmpty = targetDock.VisibleDockables.Count == 0; + InsertVisibleDockable(targetDock, targetIndex, sourceDockable); OnDockableAdded(sourceDockable); - targetDock.VisibleDockables.RemoveAt(removeIndex); - targetDock.IsEmpty = targetDock.VisibleDockables.Count == 0; + RemoveVisibleDockableAt(targetDock, removeIndex); OnDockableRemoved(sourceDockable); OnDockableMoved(sourceDockable); } @@ -203,8 +195,7 @@ public virtual void MoveDockable(IDock sourceDock, IDock targetDock, IDockable s else { RemoveDockable(sourceDockable, true); - targetDock.VisibleDockables.Insert(targetIndex, sourceDockable); - targetDock.IsEmpty = targetDock.VisibleDockables.Count == 0; + InsertVisibleDockable(targetDock, targetIndex, sourceDockable); OnDockableAdded(sourceDockable); OnDockableMoved(sourceDockable); InitDockable(sourceDockable, targetDock); @@ -230,11 +221,9 @@ public virtual void SwapDockable(IDock dock, IDockable sourceDockable, IDockable var originalTargetDockable = dock.VisibleDockables[targetIndex]; dock.VisibleDockables[targetIndex] = originalSourceDockable; - dock.IsEmpty = dock.VisibleDockables.Count == 0; OnDockableRemoved(originalTargetDockable); OnDockableAdded(originalSourceDockable); dock.VisibleDockables[sourceIndex] = originalTargetDockable; - dock.IsEmpty = dock.VisibleDockables.Count == 0; OnDockableAdded(originalTargetDockable); OnDockableSwapped(originalSourceDockable); OnDockableSwapped(originalTargetDockable); @@ -363,8 +352,7 @@ public virtual void PinDockable(IDockable dockable) if (toolDock.VisibleDockables is not null) { - toolDock.VisibleDockables.Remove(dockable); - toolDock.IsEmpty = toolDock.VisibleDockables.Count == 0; + RemoveVisibleDockable(toolDock, dockable); OnDockableRemoved(dockable); } @@ -468,8 +456,7 @@ public virtual void PinDockable(IDockable dockable) } } - toolDock.VisibleDockables.Add(dockable); - toolDock.IsEmpty = toolDock.VisibleDockables.Count == 0; + AddVisibleDockable(toolDock, dockable); OnDockableAdded(dockable); // TODO: Handle ActiveDockable state. @@ -610,4 +597,70 @@ public virtual void CloseRightDockables(IDockable dockable) CloseDockablesRange(dock, indexOf + 1, dock.VisibleDockables.Count - 1); } + + /// + /// Adds the dockable to the visible dockables list of the dock. + /// + protected void AddVisibleDockable(IDock dock, IDockable dockable) + { + if (dock.VisibleDockables == null) + { + dock.VisibleDockables = CreateList(); + } + dock.VisibleDockables.Add(dockable); + UpdateIsEmpty(dock); + } + + /// + /// Inserts the dockable to the visible dockables list of the dock at the specified index. + /// + protected void InsertVisibleDockable(IDock dock, int index, IDockable dockable) + { + if (dock.VisibleDockables == null) + { + dock.VisibleDockables = CreateList(); + } + dock.VisibleDockables.Insert(index, dockable); + UpdateIsEmpty(dock); + } + + /// + /// Removes the dockable from the visible dockables list of the dock. + /// + protected void RemoveVisibleDockable(IDock dock, IDockable dockable) + { + if (dock.VisibleDockables != null) + { + dock.VisibleDockables.Remove(dockable); + UpdateIsEmpty(dock); + } + } + + /// + /// Removes the dockable at the specified index from the visible dockables list of the dock. + /// + protected void RemoveVisibleDockableAt(IDock dock, int index) + { + if (dock.VisibleDockables != null) + { + dock.VisibleDockables.RemoveAt(index); + UpdateIsEmpty(dock); + } + } + + private void UpdateIsEmpty(IDock dock) + { + bool oldIsEmpty = dock.IsEmpty; + + var newIsEmpty = dock.VisibleDockables == null + || dock.VisibleDockables?.Count == 0 + || dock.VisibleDockables!.All(x => x is IDock { IsEmpty: true } or IProportionalDockSplitter); + + if (oldIsEmpty != newIsEmpty) + { + dock.IsEmpty = newIsEmpty; + if (dock.Owner is IDock parent) + UpdateIsEmpty(parent); + } + } } diff --git a/src/Dock.Model/FactoryBase.Init.cs b/src/Dock.Model/FactoryBase.Init.cs index 634ceb812..9b0ec5096 100644 --- a/src/Dock.Model/FactoryBase.Init.cs +++ b/src/Dock.Model/FactoryBase.Init.cs @@ -54,7 +54,7 @@ public virtual void InitDockable(IDockable dockable, IDockable? owner) InitDockable(child, dockable); } - dock.IsEmpty = dock.VisibleDockables.Count == 0; + UpdateIsEmpty(dock); } } diff --git a/src/Dock.Model/FactoryBase.cs b/src/Dock.Model/FactoryBase.cs index 15fc26aa0..442495695 100644 --- a/src/Dock.Model/FactoryBase.cs +++ b/src/Dock.Model/FactoryBase.cs @@ -125,8 +125,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera split.VisibleDockables = CreateList(); if (split.VisibleDockables is not null) { - split.VisibleDockables.Add(dockable); - split.IsEmpty = split.VisibleDockables.Count == 0; + AddVisibleDockable(split, dockable); OnDockableAdded(dockable); split.ActiveDockable = dockable; } @@ -166,8 +165,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera { if (layout.VisibleDockables is not null) { - layout.VisibleDockables.Add(split); - layout.IsEmpty = layout.VisibleDockables.Count == 0; + AddVisibleDockable(layout, split); OnDockableAdded(split); layout.ActiveDockable = split; } @@ -179,8 +177,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera { if (layout.VisibleDockables is not null) { - layout.VisibleDockables.Add(dock); - layout.IsEmpty = layout.VisibleDockables.Count == 0; + AddVisibleDockable(layout, dock); OnDockableAdded(dock); layout.ActiveDockable = dock; } @@ -189,8 +186,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera } } - layout.VisibleDockables?.Add(splitter); - layout.IsEmpty = layout.VisibleDockables?.Count == 0; + AddVisibleDockable(layout, splitter); OnDockableAdded(splitter); switch (operation) @@ -200,8 +196,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera { if (layout.VisibleDockables is not null) { - layout.VisibleDockables.Add(dock); - layout.IsEmpty = layout.VisibleDockables.Count == 0; + AddVisibleDockable(layout, dock); OnDockableAdded(dock); layout.ActiveDockable = dock; } @@ -213,8 +208,7 @@ public virtual IDock CreateSplitLayout(IDock dock, IDockable dockable, DockOpera { if (layout.VisibleDockables is not null) { - layout.VisibleDockables.Add(split); - layout.IsEmpty = layout.VisibleDockables.Count == 0; + AddVisibleDockable(layout, split); OnDockableAdded(split); layout.ActiveDockable = split; } @@ -242,11 +236,9 @@ public virtual void SplitToDock(IDock dock, IDockable dockable, DockOperation op if (index >= 0) { var layout = CreateSplitLayout(dock, dockable, operation); - ownerDock.VisibleDockables.RemoveAt(index); - ownerDock.IsEmpty = ownerDock.VisibleDockables.Count == 0; + RemoveVisibleDockableAt(ownerDock, index); OnDockableRemoved(dockable); - ownerDock.VisibleDockables.Insert(index, layout); - layout.IsEmpty = layout.VisibleDockables?.Count == 0; + InsertVisibleDockable(ownerDock, index, layout); OnDockableAdded(dockable); InitDockable(layout, ownerDock); ownerDock.ActiveDockable = layout; @@ -276,8 +268,7 @@ public virtual void SplitToDock(IDock dock, IDockable dockable, DockOperation op dock.VisibleDockables = CreateList(); if (dock.VisibleDockables is not null) { - dock.VisibleDockables.Add(dockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + AddVisibleDockable(dock, dockable); OnDockableAdded(dockable); dock.ActiveDockable = dockable; } @@ -309,8 +300,7 @@ public virtual void SplitToDock(IDock dock, IDockable dockable, DockOperation op } if (dock.VisibleDockables is not null) { - dock.VisibleDockables.Add(dockable); - dock.IsEmpty = dock.VisibleDockables.Count == 0; + AddVisibleDockable(dock, dockable); OnDockableAdded(dockable); dock.ActiveDockable = dockable; } @@ -359,8 +349,7 @@ public virtual void SplitToDock(IDock dock, IDockable dockable, DockOperation op root.VisibleDockables = CreateList(); if (root.VisibleDockables is not null && target is not null) { - root.VisibleDockables.Add(target); - root.IsEmpty = root.VisibleDockables.Count == 0; + AddVisibleDockable(root, target); OnDockableAdded(target); root.ActiveDockable = target; root.DefaultDockable = target;