From 8497dd7829b438073cbf2d8efeea875d24c4a986 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 15 Jan 2023 08:54:58 +0000 Subject: [PATCH] Move panel splitting logic (SplitLeft/SplitRight) to main SplitContainer class --- Terminal.Gui/Views/SplitContainer.cs | 80 ++++++++++++++++++++ UICatalog/Scenarios/SplitContainerNesting.cs | 67 +++++++--------- 2 files changed, 108 insertions(+), 39 deletions(-) diff --git a/Terminal.Gui/Views/SplitContainer.cs b/Terminal.Gui/Views/SplitContainer.cs index f3018d9f3..c5d820f23 100644 --- a/Terminal.Gui/Views/SplitContainer.cs +++ b/Terminal.Gui/Views/SplitContainer.cs @@ -245,6 +245,81 @@ namespace Terminal.Gui { } } + /// + /// Converts from a regular + /// container to a new nested . If + /// is already a then returns false. + /// + /// After successful splitting, the returned container's + /// will contain the original content (if any) while will be empty and available + /// for adding to. + /// The new now showing in + /// or the existing one if it was already been converted before. + /// if a was converted to a new nested + /// . if it was already a nested + /// + public bool TrySplitPanel1(out SplitContainer result) + { + return TrySplit ( + () => this.Panel1, + (n) => this.Panel1 = n, + out result); + } + + /// + /// Converts from a regular + /// container to a new nested . If + /// is already a then returns false. + /// + /// After successful splitting, the returned container's + /// will contain the original content (if any) while will be empty and available + /// for adding to. + /// The new now showing in + /// or the existing one if it was already been converted before. + /// if a was converted to a new nested + /// . if it was already a nested + /// + public bool TrySplitPanel2 (out SplitContainer result) + { + return TrySplit ( + () => this.Panel2, + (n) => this.Panel2 = n, + out result); + } + private bool TrySplit( + Func getter, + Action newSplitContainerSetter, + out SplitContainer result) + { + // Get the current panel contents (Panel1 or Panel2) + var toMove = getter(); + + if (toMove is SplitContainer existing) { + result = existing; + return false; + } + + var newContainer = new SplitContainer { + Width = Dim.Fill (), + Height = Dim.Fill (), + }; + + // Replace current child contents + Remove (toMove); + Add (newContainer); + + // Set Panel (1 or 2) to the new container + newSplitContainerSetter(newContainer); + + // Set the original content into the first panel of the new container + newContainer.Add (toMove); + newContainer.Panel1 = toMove; + + result = newContainer; + return true; + } + + private List GetAllChildSplitContainerLineViewRecursively (View v) { var lines = new List(); @@ -372,6 +447,11 @@ namespace Terminal.Gui { var availableSpace = Orientation == Orientation.Horizontal ? this.Bounds.Height : this.Bounds.Width; + // we probably haven't finished layout even if IsInitialized is true :( + if(availableSpace <= 0) { + return pos; + } + var idealPosition = pos.Anchor (availableSpace); // bad position because not enough space for Panel1 diff --git a/UICatalog/Scenarios/SplitContainerNesting.cs b/UICatalog/Scenarios/SplitContainerNesting.cs index 3be97ef73..d0dae060f 100644 --- a/UICatalog/Scenarios/SplitContainerNesting.cs +++ b/UICatalog/Scenarios/SplitContainerNesting.cs @@ -97,7 +97,7 @@ namespace UICatalog.Scenarios { var root = CreateSplitContainer (1,startHorizontal ? Terminal.Gui.Graphs.Orientation.Horizontal : - Terminal.Gui.Graphs.Orientation.Vertical, false); + Terminal.Gui.Graphs.Orientation.Vertical); root.Panel1.Add (CreateTextView (1)); root.Panel2.Add (CreateTextView (2)); @@ -142,11 +142,11 @@ namespace UICatalog.Scenarios { } if (!(to.Panel1 is SplitContainer)) { - SplitLeft (to); + Split(to,true); } if (!(to.Panel2 is SplitContainer)) { - SplitRight (to); + Split(to,false); } if (to.Panel1 is SplitContainer && to.Panel2 is SplitContainer) { @@ -156,47 +156,42 @@ namespace UICatalog.Scenarios { } } - private void SplitLeft(SplitContainer to) + private void Split(SplitContainer to, bool left) { if (panelsCreated == panelsToCreate) { return; } + SplitContainer newContainer; + + if (left) { + to.TrySplitPanel1 (out newContainer); + + } + else { + to.TrySplitPanel2 (out newContainer); + } + + panelsCreated++; + // we can split Panel1 - var tv = (TextView)to.Panel1.Subviews.Single (); + SetPanelTitles (newContainer, panelsCreated); - panelsCreated++; - - var newContainer = CreateSplitContainer (panelsCreated, to.Orientation, true); - - to.Remove (to.Panel1); - to.Add (newContainer); - to.Panel1 = newContainer; - - newContainer.Panel1.Add (tv); + // Flip orientation + newContainer.Orientation = newContainer.Orientation == Orientation.Vertical ? + Orientation.Horizontal : + Orientation.Vertical; + newContainer.Panel2.Add (CreateTextView (panelsCreated)); } - private void SplitRight(SplitContainer to) + + private void SetPanelTitles (SplitContainer container, int containerNumber) { - if (panelsCreated == panelsToCreate) { - return; - } - - // we can split Panel2 - var tv = (TextView)to.Panel2.Subviews.Single (); - panelsCreated++; - - var newContainer = CreateSplitContainer (panelsCreated, to.Orientation, true); - - to.Remove (to.Panel2); - to.Add (newContainer); - to.Panel2 = newContainer; - - newContainer.Panel2.Add (tv); - newContainer.Panel1.Add (CreateTextView (panelsCreated)); + container.Panel1Title = cbTitles.Checked ? $"Panel {containerNumber}" : string.Empty; + container.Panel2Title = cbTitles.Checked ? $"Panel {containerNumber + 1}" : string.Empty; } - private SplitContainer CreateSplitContainer (int titleNumber, Orientation orientation, bool flip) + private SplitContainer CreateSplitContainer (int titleNumber, Orientation orientation) { var toReturn = new SplitContainer { Width = Dim.Fill (), @@ -205,13 +200,7 @@ namespace UICatalog.Scenarios { Orientation = orientation }; - if (flip) { - toReturn.Orientation = toReturn.Orientation == Orientation.Vertical ? - Orientation.Horizontal : - Orientation.Vertical; - } - toReturn.Panel1Title = cbTitles.Checked ? $"Panel {titleNumber}" : string.Empty; - toReturn.Panel2Title = cbTitles.Checked ? $"Panel {titleNumber+1}" : string.Empty; + SetPanelTitles (toReturn, titleNumber); return toReturn; }