diff --git a/Examples/UICatalog/Scenarios/Adornments.cs b/Examples/UICatalog/Scenarios/Adornments.cs index aff70c09c2..5e0efc6287 100644 --- a/Examples/UICatalog/Scenarios/Adornments.cs +++ b/Examples/UICatalog/Scenarios/Adornments.cs @@ -35,7 +35,7 @@ public override void Main () Title = "The _Window", Arrangement = ViewArrangement.Overlapped | ViewArrangement.Movable, - Width = Dim.Fill (Dim.Func (() => editor.Frame.Width)), + Width = Dim.Fill (Dim.Func (_ => editor.Frame.Width)), Height = Dim.Fill () }; app.Add (window); diff --git a/Examples/UICatalog/Scenarios/AllViewsTester.cs b/Examples/UICatalog/Scenarios/AllViewsTester.cs index 71d9edbe56..f967742bcd 100644 --- a/Examples/UICatalog/Scenarios/AllViewsTester.cs +++ b/Examples/UICatalog/Scenarios/AllViewsTester.cs @@ -101,7 +101,7 @@ public override void Main () { Title = "Arrangement [_3]", X = Pos.Right (_classListView) - 1, - Y = Pos.Bottom (_adornmentsEditor) - Pos.Func (() => _adornmentsEditor.Frame.Height == 1 ? 0 : 1), + Y = Pos.Bottom (_adornmentsEditor) - Pos.Func (_ => _adornmentsEditor.Frame.Height == 1 ? 0 : 1), Width = Dim.Width (_adornmentsEditor), Height = Dim.Fill (), AutoSelectViewToEdit = false, @@ -134,7 +134,7 @@ public override void Main () { Title = "ViewportSettings [_5]", X = Pos.Right (_arrangementEditor) - 1, - Y = Pos.Bottom (_layoutEditor) - Pos.Func (() => _layoutEditor.Frame.Height == 1 ? 0 : 1), + Y = Pos.Bottom (_layoutEditor) - Pos.Func (_ => _layoutEditor.Frame.Height == 1 ? 0 : 1), Width = Dim.Width (_layoutEditor), Height = Dim.Auto (), CanFocus = true, @@ -148,7 +148,7 @@ public override void Main () { Title = "View Properties [_6]", X = Pos.Right (_adornmentsEditor) - 1, - Y = Pos.Bottom (_viewportSettingsEditor) - Pos.Func (() => _viewportSettingsEditor.Frame.Height == 1 ? 0 : 1), + Y = Pos.Bottom (_viewportSettingsEditor) - Pos.Func (_ => _viewportSettingsEditor.Frame.Height == 1 ? 0 : 1), Width = Dim.Width (_layoutEditor), Height = Dim.Auto (), CanFocus = true, @@ -171,7 +171,7 @@ public override void Main () _layoutEditor.Width = Dim.Fill ( Dim.Func ( - () => + _ => { if (_eventLog.NeedsLayout) { diff --git a/Examples/UICatalog/Scenarios/Arrangement.cs b/Examples/UICatalog/Scenarios/Arrangement.cs index 6aae631c86..867e36f1da 100644 --- a/Examples/UICatalog/Scenarios/Arrangement.cs +++ b/Examples/UICatalog/Scenarios/Arrangement.cs @@ -66,7 +66,7 @@ public override void Main () View tiledView3 = CreateTiledView (2, Pos.Right (tiledView2) - 1, Pos.Top (tiledView2)); tiledView3.Height = Dim.Height (tiledView1); View tiledView4 = CreateTiledView (3, Pos.Left (tiledView1), Pos.Bottom (tiledView1) - 1); - tiledView4.Width = Dim.Func (() => tiledView3.Frame.Width + tiledView2.Frame.Width + tiledView1.Frame.Width - 2); + tiledView4.Width = Dim.Func (_ => tiledView3.Frame.Width + tiledView2.Frame.Width + tiledView1.Frame.Width - 2); View movableSizeableWithProgress = CreateOverlappedView (2, 10, 8); movableSizeableWithProgress.Title = "Movable _& Sizable"; diff --git a/Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.cs b/Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.cs index 4e7679b6bc..5a7872c334 100644 --- a/Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.cs +++ b/Examples/UICatalog/Scenarios/CharacterMap/CharacterMap.cs @@ -39,7 +39,6 @@ public override void Main () { X = 0, Y = 1, - Width = Dim.Fill (Dim.Func (() => _categoryList!.Frame.Width)), Height = Dim.Fill (), // SchemeName = "Base" @@ -172,6 +171,8 @@ public override void Main () }; top.Add (menu); + _charMap.Width = Dim.Fill (Dim.Func (v => v!.Frame.Width, _categoryList)); + _charMap.SelectedCodePoint = 0; _charMap.SetFocus (); diff --git a/Examples/UICatalog/Scenarios/ConfigurationEditor.cs b/Examples/UICatalog/Scenarios/ConfigurationEditor.cs index cd4a8563aa..a5beca9e98 100644 --- a/Examples/UICatalog/Scenarios/ConfigurationEditor.cs +++ b/Examples/UICatalog/Scenarios/ConfigurationEditor.cs @@ -55,7 +55,7 @@ public override void Main () _tabView = new () { Width = Dim.Fill (), - Height = Dim.Fill (Dim.Func (() => statusBar.Frame.Height)) + Height = Dim.Fill (Dim.Func (_ => statusBar.Frame.Height)) }; win.Add (_tabView, statusBar); diff --git a/Examples/UICatalog/Scenarios/DynamicMenuBar.cs b/Examples/UICatalog/Scenarios/DynamicMenuBar.cs index fc61a7a3b6..b800cc3ef1 100644 --- a/Examples/UICatalog/Scenarios/DynamicMenuBar.cs +++ b/Examples/UICatalog/Scenarios/DynamicMenuBar.cs @@ -598,7 +598,7 @@ public DynamicMenuBarSample () X = Pos.Right (btnPrevious) + 1, Y = Pos.Top (btnPrevious), - Width = Dim.Fill () - Dim.Func (() => btnAdd.Frame.Width + 1), + Width = Dim.Fill () - Dim.Func (_ => btnAdd.Frame.Width + 1), Height = 1 }; diff --git a/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentEditor.cs b/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentEditor.cs index d1243b424b..907cbb42e3 100644 --- a/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentEditor.cs +++ b/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentEditor.cs @@ -100,7 +100,7 @@ private void AdornmentEditor_Initialized (object? sender, EventArgs e) _leftEdit = new () { - X = Pos.Left (_topEdit) - Pos.Func (() => _topEdit.Text.Length) - 2, Y = Pos.Bottom (_topEdit), + X = Pos.Left (_topEdit) - Pos.Func (_ => _topEdit.Text.Length) - 2, Y = Pos.Bottom (_topEdit), Format = _topEdit.Format }; diff --git a/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentsEditor.cs b/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentsEditor.cs index 382865f4b1..74d7acee88 100644 --- a/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentsEditor.cs +++ b/Examples/UICatalog/Scenarios/EditorsAndHelpers/AdornmentsEditor.cs @@ -122,7 +122,7 @@ private void AdornmentsEditor_Initialized (object? sender, EventArgs e) PaddingEditor.Border!.Thickness = PaddingEditor.Border.Thickness with { Bottom = 0 }; Add (PaddingEditor); - Width = Dim.Auto (maximumContentDim: Dim.Func (() => MarginEditor.Frame.Width - 2)); + Width = Dim.Auto (maximumContentDim: Dim.Func (_ => MarginEditor.Frame.Width - 2)); MarginEditor.ExpanderButton!.Collapsed = true; BorderEditor.ExpanderButton!.Collapsed = true; diff --git a/Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs b/Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs index 523c4f1dab..37007997d3 100644 --- a/Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs +++ b/Examples/UICatalog/Scenarios/EditorsAndHelpers/DimEditor.cs @@ -68,7 +68,7 @@ protected override void OnUpdateLayoutSettings () break; case DimFunc func: _valueEdit.Enabled = true; - _value = func.Fn (); + _value = func.Fn (null); _valueEdit!.Text = _value.ToString (); break; case DimPercent percent: @@ -98,7 +98,7 @@ private void DimEditor_Initialized (object? sender, EventArgs e) { X = Pos.Right (label) + 1, Y = 0, - Width = Dim.Func (() => _radioItems.Max (i => i.GetColumns ()) - label.Frame.Width + 1), + Width = Dim.Func (_ => _radioItems.Max (i => i.GetColumns ()) - label.Frame.Width + 1), Text = $"{_value}" }; @@ -141,7 +141,7 @@ private void DimChanged () 0 => Dim.Absolute (_value), 1 => Dim.Auto (), 2 => Dim.Fill (_value), - 3 => Dim.Func (() => _value), + 3 => Dim.Func (_ => _value), 4 => Dim.Percent (_value), _ => Dimension == Dimension.Width ? ViewToEdit.Width : ViewToEdit.Height }; diff --git a/Examples/UICatalog/Scenarios/EditorsAndHelpers/EventLog.cs b/Examples/UICatalog/Scenarios/EditorsAndHelpers/EventLog.cs index b64acc865e..9b59d88126 100644 --- a/Examples/UICatalog/Scenarios/EditorsAndHelpers/EventLog.cs +++ b/Examples/UICatalog/Scenarios/EditorsAndHelpers/EventLog.cs @@ -20,7 +20,7 @@ public EventLog () Y = 0; Width = Dim.Func ( - () => + _ => { if (!IsInitialized) { diff --git a/Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs b/Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs index c67a303d1a..012b2409ef 100644 --- a/Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs +++ b/Examples/UICatalog/Scenarios/EditorsAndHelpers/PosEditor.cs @@ -70,7 +70,7 @@ protected override void OnUpdateLayoutSettings () break; case PosFunc func: _valueEdit.Enabled = true; - _value = func.Fn (); + _value = func.Fn (null); _valueEdit!.Text = _value.ToString (); break; @@ -98,7 +98,7 @@ private void PosEditor_Initialized (object? sender, EventArgs e) { X = Pos.Right (label) + 1, Y = 0, - Width = Dim.Func (() => _radioItems.Max (i => i.GetColumns ()) - label.Frame.Width + 1), + Width = Dim.Func (_ => _radioItems.Max (i => i.GetColumns ()) - label.Frame.Width + 1), Text = $"{_value}" }; @@ -142,7 +142,7 @@ private void PosChanged () 1 => Pos.Align (Alignment.Start), 2 => new PosAnchorEnd (), 3 => Pos.Center (), - 4 => Pos.Func (() => _value), + 4 => Pos.Func (_ => _value), 5 => Pos.Percent (_value), _ => Dimension == Dimension.Width ? ViewToEdit.X : ViewToEdit.Y }; diff --git a/Examples/UICatalog/Scenarios/ListColumns.cs b/Examples/UICatalog/Scenarios/ListColumns.cs index 402e2944db..5861acaada 100644 --- a/Examples/UICatalog/Scenarios/ListColumns.cs +++ b/Examples/UICatalog/Scenarios/ListColumns.cs @@ -252,7 +252,7 @@ public override void Main () top.Add (menu, appWindow, statusBar); appWindow.Y = 1; - appWindow.Height = Dim.Fill(Dim.Func (() => statusBar.Frame.Height)); + appWindow.Height = Dim.Fill(Dim.Func (_ => statusBar.Frame.Height)); // Run - Start the application. Application.Run (top); diff --git a/Examples/UICatalog/Scenarios/ListViewWithSelection.cs b/Examples/UICatalog/Scenarios/ListViewWithSelection.cs index 123e4d54a5..874d061a58 100644 --- a/Examples/UICatalog/Scenarios/ListViewWithSelection.cs +++ b/Examples/UICatalog/Scenarios/ListViewWithSelection.cs @@ -76,7 +76,7 @@ public override void Main () Title = "_ListView", X = 0, Y = Pos.Bottom (_allowMarkingCb), - Width = Dim.Func (() => _listView?.MaxLength ?? 10), + Width = Dim.Func (_ => _listView?.MaxLength ?? 10), Height = Dim.Fill (), AllowsMarking = false, AllowsMultipleSelection = false, diff --git a/Examples/UICatalog/Scenarios/Mouse.cs b/Examples/UICatalog/Scenarios/Mouse.cs index 658789cf6e..cb047614cd 100644 --- a/Examples/UICatalog/Scenarios/Mouse.cs +++ b/Examples/UICatalog/Scenarios/Mouse.cs @@ -109,7 +109,7 @@ void DemoPaddingOnInitialized (object o, EventArgs eventArgs) X = 0, Y = 0, Width = Dim.Fill (), - Height = Dim.Func (() => demo.Padding.Thickness.Top), + Height = Dim.Func (_ => demo.Padding.Thickness.Top), Title = "inPadding", Id = "inPadding" }); diff --git a/Examples/UICatalog/Scenarios/ScrollBarDemo.cs b/Examples/UICatalog/Scenarios/ScrollBarDemo.cs index 7376a7b54d..0a6f0bc705 100644 --- a/Examples/UICatalog/Scenarios/ScrollBarDemo.cs +++ b/Examples/UICatalog/Scenarios/ScrollBarDemo.cs @@ -72,7 +72,7 @@ int GetMaxLabelWidth (int groupId) Text = "_Width/Height:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, AlignmentModes.StartToEnd, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblWidthHeight); @@ -114,7 +114,7 @@ int GetMaxLabelWidth (int groupId) Text = "_Orientation:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblOrientationLabel); @@ -160,7 +160,7 @@ int GetMaxLabelWidth (int groupId) Text = "Scrollable_ContentSize:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblSize); @@ -193,7 +193,7 @@ int GetMaxLabelWidth (int groupId) Text = "_VisibleContentSize:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblVisibleContentSize); @@ -226,7 +226,7 @@ int GetMaxLabelWidth (int groupId) Text = "_Position:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblPosition); @@ -264,7 +264,7 @@ int GetMaxLabelWidth (int groupId) Text = "Options:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblOptions); var autoShow = new CheckBox @@ -282,7 +282,7 @@ int GetMaxLabelWidth (int groupId) Text = "SliderPosition:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblSliderPosition); @@ -299,7 +299,7 @@ int GetMaxLabelWidth (int groupId) Text = "Scrolled:", TextAlignment = Alignment.End, Y = Pos.Align (Alignment.Start, groupId: 1), - Width = Dim.Func (() => GetMaxLabelWidth (1)) + Width = Dim.Func (_ => GetMaxLabelWidth (1)) }; demoFrame.Add (lblScrolled); diff --git a/Examples/UICatalog/Scenarios/Shortcuts.cs b/Examples/UICatalog/Scenarios/Shortcuts.cs index 0ad863e94d..73ec7a5ddb 100644 --- a/Examples/UICatalog/Scenarios/Shortcuts.cs +++ b/Examples/UICatalog/Scenarios/Shortcuts.cs @@ -43,14 +43,14 @@ private void App_Loaded (object? sender, EventArgs e) }; eventLog.Width = Dim.Func ( - () => Math.Min ( - Application.Top.Viewport.Width / 2, - eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0)); + _ => Math.Min ( + Application.Top.Viewport.Width / 2, + eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0)); eventLog.Width = Dim.Func ( - () => Math.Min ( - eventLog.SuperView!.Viewport.Width / 2, - eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0)); + _ => Math.Min ( + eventLog.SuperView!.Viewport.Width / 2, + eventLog?.MaxLength + eventLog!.GetAdornmentsThickness ().Horizontal ?? 0)); Application.Top.Add (eventLog); var alignKeysShortcut = new Shortcut @@ -193,7 +193,7 @@ select peer.Key.ToString ().GetColumns ()).Prepend (max) Id = "appShortcut", X = 0, Y = Pos.Bottom (canFocusShortcut), - Width = Dim.Fill (Dim.Func (() => eventLog.Frame.Width)), + Width = Dim.Fill (Dim.Func (_ => eventLog.Frame.Width)), Title = "A_pp Shortcut", Key = Key.F1, Text = "Width is DimFill", diff --git a/Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs b/Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs index add1555ba3..62c35ac40e 100644 --- a/Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs +++ b/Examples/UICatalog/Scenarios/SingleBackgroundWorker.cs @@ -83,7 +83,7 @@ public MainApp () workerLogTop.Add (_listLog); workerLogTop.Y = 1; - workerLogTop.Height = Dim.Fill (Dim.Func (() => statusBar.Frame.Height)); + workerLogTop.Height = Dim.Fill (Dim.Func (_ => statusBar.Frame.Height)); Add (menu, workerLogTop, statusBar); Title = "MainApp"; diff --git a/Examples/UICatalog/Scenarios/ViewportSettings.cs b/Examples/UICatalog/Scenarios/ViewportSettings.cs index 7e488d0c73..fa801e37c4 100644 --- a/Examples/UICatalog/Scenarios/ViewportSettings.cs +++ b/Examples/UICatalog/Scenarios/ViewportSettings.cs @@ -124,8 +124,8 @@ public override void Main () var view = new ViewportSettingsDemoView { Title = "ViewportSettings Demo View", - Width = Dim.Fill (Dim.Func (() => app.IsInitialized ? adornmentsEditor.Frame.Width + 1 : 1)), - Height = Dim.Fill (Dim.Func (() => app.IsInitialized ? viewportSettingsEditor.Frame.Height : 1)) + Width = Dim.Fill (Dim.Func (_ => app.IsInitialized ? adornmentsEditor.Frame.Width + 1 : 1)), + Height = Dim.Fill (Dim.Func (_ => app.IsInitialized ? viewportSettingsEditor.Frame.Height : 1)) }; app.Add (view); @@ -164,7 +164,7 @@ public override void Main () { X = Pos.Center (), Y = Pos.Bottom (textView) + 1, - Width = Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (() => view.GetContentSize ().Width)), + Width = Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Func (_ => view.GetContentSize ().Width)), Height = Dim.Auto (DimAutoStyle.Content, maximumContentDim: Dim.Percent (20)), }; diff --git a/Examples/UICatalog/Scenarios/Wizards.cs b/Examples/UICatalog/Scenarios/Wizards.cs index e74e54d9ed..f3d4bf8310 100644 --- a/Examples/UICatalog/Scenarios/Wizards.cs +++ b/Examples/UICatalog/Scenarios/Wizards.cs @@ -282,11 +282,11 @@ void Win_Loaded (object sender, EventArgs args) someText.Height = Dim.Fill ( Dim.Func ( - () => someText.SuperView is { IsInitialized: true } - ? someText.SuperView.SubViews - .First (view => view.Y.Has (out _)) - .Frame.Height - : 1)); + v => someText.SuperView is { IsInitialized: true } + ? someText.SuperView.SubViews + .First (view => view.Y.Has (out _)) + .Frame.Height + : 1)); var help = "This is helpful."; fourthStep.Add (someText); diff --git a/Examples/UICatalog/UICatalogTop.cs b/Examples/UICatalog/UICatalogTop.cs index ad87b0a12d..7253d695e8 100644 --- a/Examples/UICatalog/UICatalogTop.cs +++ b/Examples/UICatalog/UICatalogTop.cs @@ -404,20 +404,7 @@ private TableView CreateScenarioList () X = Pos.Right (_categoryList!) - 1, Y = Pos.Bottom (_menuBar!), Width = Dim.Fill (), - Height = Dim.Fill ( - Dim.Func ( - () => - { - if (_statusBar!.NeedsLayout) - { - throw new LayoutException ("DimFunc.Fn aborted because dependent View needs layout."); - - //_statusBar.Layout (); - } - - return _statusBar.Frame.Height; - })), - + Height = Dim.Fill (Dim.Func (v => v!.Frame.Height, _statusBar)), //AllowsMarking = false, CanFocus = true, Title = "_Scenarios", @@ -515,19 +502,7 @@ private ListView CreateCategoryList () X = 0, Y = Pos.Bottom (_menuBar!), Width = Dim.Auto (), - Height = Dim.Fill ( - Dim.Func ( - () => - { - if (_statusBar!.NeedsLayout) - { - throw new LayoutException ("DimFunc.Fn aborted because dependent View needs layout."); - - //_statusBar.Layout (); - } - - return _statusBar.Frame.Height; - })), + Height = Dim.Fill (Dim.Func (v => v!.Frame.Height, _statusBar)), AllowsMarking = false, CanFocus = true, Title = "_Categories", @@ -595,8 +570,8 @@ private StatusBar CreateStatusBar () // ReSharper disable All statusBar.Height = Dim.Auto ( DimAutoStyle.Auto, - minimumContentDim: Dim.Func (() => statusBar.Visible ? 1 : 0), - maximumContentDim: Dim.Func (() => statusBar.Visible ? 1 : 0)); + minimumContentDim: Dim.Func (_ => statusBar.Visible ? 1 : 0), + maximumContentDim: Dim.Func (_ => statusBar.Visible ? 1 : 0)); // ReSharper restore All _shQuit = new () diff --git a/Terminal.Gui/App/Application.Run.cs b/Terminal.Gui/App/Application.Run.cs index 30c1384a3e..32127a49cf 100644 --- a/Terminal.Gui/App/Application.Run.cs +++ b/Terminal.Gui/App/Application.Run.cs @@ -205,6 +205,8 @@ public static RunState Begin (Toplevel toplevel) toplevel.OnLoaded (); + LayoutAndDraw (true); + if (PositionCursor ()) { Driver?.UpdateCursor (); @@ -212,9 +214,6 @@ public static RunState Begin (Toplevel toplevel) NotifyNewRunState?.Invoke (toplevel, new (rs)); - // Force an Idle event so that an Iteration (and Refresh) happen. - Invoke (() => { }); - return rs; } @@ -535,7 +534,7 @@ public static bool RunIteration (ref RunState state, bool firstIteration = false return firstIteration; } - LayoutAndDraw (); + LayoutAndDraw (TopLevels.Any (v => v.NeedsLayout || v.NeedsDraw)); if (PositionCursor ()) { diff --git a/Terminal.Gui/ViewBase/Layout/Dim.cs b/Terminal.Gui/ViewBase/Layout/Dim.cs index 83cc2e42e1..d9bdaf3620 100644 --- a/Terminal.Gui/ViewBase/Layout/Dim.cs +++ b/Terminal.Gui/ViewBase/Layout/Dim.cs @@ -141,12 +141,14 @@ public abstract record Dim : IEqualityOperators public static Dim? Fill (Dim margin) { return new DimFill (margin); } /// - /// Creates a function object that computes the dimension by executing the provided function. + /// Creates a function object that computes the dimension based on the passed view and by executing + /// the provided function. /// The function will be called every time the dimension is needed. /// /// The function to be executed. - /// The returned from the function. - public static Dim Func (Func function) { return new DimFunc (function); } + /// The view where the data will be retrieved. + /// The returned from the function based on the passed view. + public static Dim Func (Func function, View? view = null) { return new DimFunc (function, view); } /// Creates a object that tracks the Height of the specified . /// The height of the other . diff --git a/Terminal.Gui/ViewBase/Layout/DimAuto.cs b/Terminal.Gui/ViewBase/Layout/DimAuto.cs index 6974fd45b2..34ad05b197 100644 --- a/Terminal.Gui/ViewBase/Layout/DimAuto.cs +++ b/Terminal.Gui/ViewBase/Layout/DimAuto.cs @@ -48,7 +48,7 @@ internal override int Calculate (int location, int superviewContentSize, View us us.TextFormatter.ConstrainToSize = us.TextFormatter.FormatAndGetSize (new (int.Min (autoMax, screenX4), screenX4)); } - textSize = us.TextFormatter.ConstrainToWidth!.Value; + textSize = us.TextFormatter.ConstrainToWidth ?? 0; } else { @@ -81,7 +81,7 @@ internal override int Calculate (int location, int superviewContentSize, View us { // TOOD: All the below is a naive implementation. It may be possible to optimize this. - List includedSubViews = us.InternalSubViews.ToList (); + List includedSubViews = us.SubViews.Snapshot ().ToList (); // If [x] it can cause `us.ContentSize` to change. // If [ ] it doesn't need special processing for us to determine `us.ContentSize`. diff --git a/Terminal.Gui/ViewBase/Layout/DimFunc.cs b/Terminal.Gui/ViewBase/Layout/DimFunc.cs index 9047bd96b1..0773dc316f 100644 --- a/Terminal.Gui/ViewBase/Layout/DimFunc.cs +++ b/Terminal.Gui/ViewBase/Layout/DimFunc.cs @@ -2,22 +2,29 @@ namespace Terminal.Gui.ViewBase; /// -/// Represents a function object that computes the dimension by executing the provided function. +/// Represents a function object that computes the dimension based on the passed view and by +/// executing the provided function. /// /// /// This is a low-level API that is typically used internally by the layout system. Use the various static /// methods on the class to create objects instead. /// /// The function that computes the dimension. If this function throws ... -public record DimFunc (Func Fn) : Dim +/// The returned from the function based on the passed view. +public record DimFunc (Func Fn, View? View = null) : Dim { /// /// Gets the function that computes the dimension. /// - public Func Fn { get; } = Fn; + public Func Fn { get; } = Fn; + + /// + /// Gets the passed view that the dimension is based on. + /// + public View? View { get; } = View; /// - public override string ToString () { return $"DimFunc({Fn ()})"; } + public override string ToString () { return $"DimFunc({Fn (View)})"; } - internal override int GetAnchor (int size) { return Fn (); } -} \ No newline at end of file + internal override int GetAnchor (int size) { return Fn (View); } +} diff --git a/Terminal.Gui/ViewBase/Layout/Pos.cs b/Terminal.Gui/ViewBase/Layout/Pos.cs index f213e0941f..09694adc39 100644 --- a/Terminal.Gui/ViewBase/Layout/Pos.cs +++ b/Terminal.Gui/ViewBase/Layout/Pos.cs @@ -220,12 +220,14 @@ public static Pos AnchorEnd (int offset) public static Pos Center () { return new PosCenter (); } /// - /// Creates a object that computes the position by executing the provided function. The function - /// will be called every time the position is needed. + /// Creates a object that computes the position based on the passed view and by executing the + /// provided function. + /// The function will be called every time the position is needed. /// /// The function to be executed. + /// The view where the data will be retrieved. /// The returned from the function. - public static Pos Func (Func function) { return new PosFunc (function); } + public static Pos Func (Func function, View? view = null) { return new PosFunc (function, view); } /// Creates a percentage object /// The percent object. diff --git a/Terminal.Gui/ViewBase/Layout/PosAlign.cs b/Terminal.Gui/ViewBase/Layout/PosAlign.cs index 82187c5730..4d72cc9afb 100644 --- a/Terminal.Gui/ViewBase/Layout/PosAlign.cs +++ b/Terminal.Gui/ViewBase/Layout/PosAlign.cs @@ -117,7 +117,7 @@ internal override int Calculate (int superviewDimension, Dim dim, View us, Dimen } else { - groupViews = us.SuperView!.SubViews.Where (v => HasGroupId (v, dimension, GroupId)).ToList (); + groupViews = us.SuperView!.SubViews.Snapshot ().Where (v => HasGroupId (v, dimension, GroupId)).ToList (); } AlignAndUpdateGroup (GroupId, groupViews, dimension, superviewDimension); diff --git a/Terminal.Gui/ViewBase/Layout/PosFunc.cs b/Terminal.Gui/ViewBase/Layout/PosFunc.cs index a55ff6647f..3900beb463 100644 --- a/Terminal.Gui/ViewBase/Layout/PosFunc.cs +++ b/Terminal.Gui/ViewBase/Layout/PosFunc.cs @@ -4,11 +4,26 @@ namespace Terminal.Gui.ViewBase; /// /// Represents a position that is computed by executing a function that returns an integer position. /// -/// The function that computes the dimension. If this function throws ... -public record PosFunc (Func Fn) : Pos +/// +/// This is a low-level API that is typically used internally by the layout system. Use the various static +/// methods on the class to create objects instead. +/// +/// The function that computes the position. If this function throws ... +/// The returned from the function based on the passed view. +public record PosFunc (Func Fn, View? View = null) : Pos { + /// + /// Gets the function that computes the position. + /// + public Func Fn { get; } = Fn; + + /// + /// Gets the passed view that the position is based on. + /// + public View? View { get; } = View; + /// - public override string ToString () { return $"PosFunc({Fn ()})"; } + public override string ToString () { return $"PosFunc({Fn (View)})"; } - internal override int GetAnchor (int size) { return Fn (); } + internal override int GetAnchor (int size) { return Fn (View); } } \ No newline at end of file diff --git a/Terminal.Gui/ViewBase/View.Drawing.cs b/Terminal.Gui/ViewBase/View.Drawing.cs index a8d2d4bf85..8996797abb 100644 --- a/Terminal.Gui/ViewBase/View.Drawing.cs +++ b/Terminal.Gui/ViewBase/View.Drawing.cs @@ -1,5 +1,6 @@ #nullable enable using System.ComponentModel; +using System.Diagnostics; namespace Terminal.Gui.ViewBase; @@ -12,7 +13,8 @@ public partial class View // Drawing APIs /// If , will be called on each view to force it to be drawn. internal static void Draw (IEnumerable views, bool force) { - IEnumerable viewsArray = views as View [] ?? views.ToArray (); + // **Snapshot once** — every recursion level gets its own frozen array + View [] viewsArray = views.Snapshot (); // The draw context is used to track the region drawn by each view. DrawContext context = new DrawContext (); @@ -111,6 +113,26 @@ public void Draw (DrawContext? context = null) Border?.AdvanceDrawIndicator (); ClearNeedsDraw (); + + if (this is not Adornment && SuperView is not Adornment) + { + // Parent + Debug.Assert (Margin!.Parent == this); + Debug.Assert (Border!.Parent == this); + Debug.Assert (Padding!.Parent == this); + + // SubViewNeedsDraw is set to false by ClearNeedsDraw. + Debug.Assert (SubViewNeedsDraw == false); + Debug.Assert (Margin!.SubViewNeedsDraw == false); + Debug.Assert (Border!.SubViewNeedsDraw == false); + Debug.Assert (Padding!.SubViewNeedsDraw == false); + + // NeedsDraw is set to false by ClearNeedsDraw. + Debug.Assert (NeedsDraw == false); + Debug.Assert (Margin!.NeedsDraw == false); + Debug.Assert (Border!.NeedsDraw == false); + Debug.Assert (Padding!.NeedsDraw == false); + } } // ------------------------------------ @@ -131,6 +153,11 @@ public void Draw (DrawContext? context = null) private void DoDrawAdornmentsSubViews () { + if (Border?.NeedsLayout == true) + { + Border.Layout (); + } + // NOTE: We do not support subviews of Margin? if (Border?.SubViews is { } && Border.Thickness != Thickness.Empty) @@ -151,6 +178,11 @@ private void DoDrawAdornmentsSubViews () SetClip (saved); } + if (Padding?.NeedsLayout == true) + { + Padding.Layout (); + } + if (Padding?.SubViews is { } && Padding.Thickness != Thickness.Empty) { foreach (View subview in Padding.SubViews) @@ -549,7 +581,7 @@ public void DrawSubViews (DrawContext? context = null) } // Draw the subviews in reverse order to leverage clipping. - foreach (View view in InternalSubViews.Where (view => view.Visible).Reverse ()) + foreach (View view in InternalSubViews.Snapshot ().Where (v => v.Visible).Reverse ()) { // TODO: HACK - This forcing of SetNeedsDraw with SuperViewRendersLineCanvas enables auto line join to work, but is brute force. if (view.SuperViewRendersLineCanvas || view.ViewportSettings.HasFlag (ViewportSettingsFlags.Transparent)) @@ -720,8 +752,7 @@ protected virtual void OnDrawComplete (DrawContext? context) { } /// public bool NeedsDraw { - // TODO: Figure out if we can decouple NeedsDraw from NeedsLayout. - get => Visible && (NeedsDrawRect != Rectangle.Empty || NeedsLayout); + get => Visible && (NeedsDrawRect != Rectangle.Empty || Margin?.NeedsDraw == true || Border?.NeedsDraw == true || Padding?.NeedsDraw == true); set { if (value) @@ -806,8 +837,8 @@ public void SetNeedsDraw (Rectangle viewPortRelativeRegion) adornment.Parent?.SetSubViewNeedsDraw (); } - // There was multiple enumeration error here, so calling ToArray - probably a stop gap - foreach (View subview in InternalSubViews) + // There was multiple enumeration error here, so calling new snapshot collection - probably a stop gap + foreach (View subview in InternalSubViews.Snapshot ()) { if (subview.Frame.IntersectsWith (viewPortRelativeRegion)) { @@ -846,22 +877,23 @@ protected void ClearNeedsDraw () NeedsDrawRect = Rectangle.Empty; SubViewNeedsDraw = false; - if (Margin is { } && Margin.Thickness != Thickness.Empty) + if (Margin is { } && (Margin.Thickness != Thickness.Empty || Margin.SubViewNeedsDraw || Margin.NeedsDraw)) { Margin?.ClearNeedsDraw (); } - if (Border is { } && Border.Thickness != Thickness.Empty) + if (Border is { } && (Border.Thickness != Thickness.Empty || Border.SubViewNeedsDraw || Border.NeedsDraw)) { Border?.ClearNeedsDraw (); } - if (Padding is { } && Padding.Thickness != Thickness.Empty) + if (Padding is { } && (Padding.Thickness != Thickness.Empty || Padding.SubViewNeedsDraw || Padding.NeedsDraw)) { Padding?.ClearNeedsDraw (); } - foreach (View subview in SubViews) + // There was multiple enumeration error here, so calling new snapshot collection - probably a stop gap + foreach (View subview in InternalSubViews.Snapshot ()) { subview.ClearNeedsDraw (); } @@ -876,7 +908,6 @@ protected void ClearNeedsDraw () { LineCanvas.Clear (); } - } #endregion NeedsDraw diff --git a/Terminal.Gui/ViewBase/View.Hierarchy.cs b/Terminal.Gui/ViewBase/View.Hierarchy.cs index d7510c2b07..2d86b035ad 100644 --- a/Terminal.Gui/ViewBase/View.Hierarchy.cs +++ b/Terminal.Gui/ViewBase/View.Hierarchy.cs @@ -558,3 +558,22 @@ private void PerformActionForSubView (View subview, Action action) #endregion SubViewOrdering } + +internal static class ViewCollectionHelpers +{ + /// Returns a defensive copy of any . + internal static View [] Snapshot (this IEnumerable source) + { + if (source is IList list) + { + // The list parameter might be the live `_subviews`, so freeze it under a lock + lock (list) + { + return [.. list]; // C# 12 slice copy (= new List(list).ToArray()) + } + } + + // Anything else (LINQ result, iterator block, etc.) we just enumerate. + return source.ToArray (); // Safe because it’s not shared mutable state + } +} diff --git a/Terminal.Gui/ViewBase/View.Layout.cs b/Terminal.Gui/ViewBase/View.Layout.cs index 41339fdf8a..c3c4a407be 100644 --- a/Terminal.Gui/ViewBase/View.Layout.cs +++ b/Terminal.Gui/ViewBase/View.Layout.cs @@ -419,7 +419,10 @@ public bool Layout (Size contentSize) { LayoutSubViews (); - // Debug.Assert(!NeedsLayout); + // A layout was performed so a draw is needed + // NeedsLayout may still be true if a dependent View still needs layout after SubViewsLaidOut event + SetNeedsDraw (); + return true; } @@ -635,7 +638,7 @@ internal void LayoutSubViews () List redo = new (); - foreach (View v in ordered) + foreach (View v in ordered.Snapshot ()) { if (!v.Layout (contentSize)) { @@ -700,7 +703,7 @@ protected virtual void OnSubViewLayout (LayoutEventArgs args) { } /// Override to perform tasks after the has been resized or the layout has /// otherwise changed. /// - protected virtual void OnSubViewsLaidOut (LayoutEventArgs args) { } + protected virtual void OnSubViewsLaidOut (LayoutEventArgs args) { Debug.Assert (!NeedsLayout); } /// Raised after all sub-views have been laid out. /// @@ -761,10 +764,12 @@ public void SetNeedsLayout () // TODO: Optimize this - see Setting_Thickness_Causes_Adornment_SubView_Layout // Use a stack to avoid recursion - Stack stack = new (SubViews); + Stack stack = new (InternalSubViews.Snapshot ().ToList ()); while (stack.Count > 0) { + Debug.Assert (stack.Peek () is { }); + View current = stack.Pop (); if (!current.NeedsLayout) diff --git a/Terminal.Gui/ViewBase/View.ScrollBars.cs b/Terminal.Gui/ViewBase/View.ScrollBars.cs index 9f79bcf98c..4463299f93 100644 --- a/Terminal.Gui/ViewBase/View.ScrollBars.cs +++ b/Terminal.Gui/ViewBase/View.ScrollBars.cs @@ -73,7 +73,7 @@ private void ConfigureVerticalScrollBar (ScrollBar scrollBar) scrollBar.Height = Dim.Fill ( Dim.Func ( - () => + _ => { if (_horizontalScrollBar.IsValueCreated) { @@ -98,7 +98,7 @@ private void ConfigureHorizontalScrollBar (ScrollBar scrollBar) scrollBar.Width = Dim.Fill ( Dim.Func ( - () => + _ => { if (_verticalScrollBar.IsValueCreated) { diff --git a/Terminal.Gui/Views/FileDialogs/FileDialog.cs b/Terminal.Gui/Views/FileDialogs/FileDialog.cs index ae1f7dfea4..deaacbb0b6 100644 --- a/Terminal.Gui/Views/FileDialogs/FileDialog.cs +++ b/Terminal.Gui/Views/FileDialogs/FileDialog.cs @@ -154,7 +154,7 @@ internal FileDialog (IFileSystem fileSystem) X = 0, Y = Pos.Bottom (_btnBack), Width = Dim.Fill (), - Height = Dim.Fill (Dim.Func (() => IsInitialized ? _btnOk.Frame.Height : 1)) + Height = Dim.Fill (Dim.Func (_ => IsInitialized ? _btnOk.Frame.Height : 1)) }; Initialized += (s, e) => @@ -754,7 +754,7 @@ private string AspectGetter (object o) return (Style.IconProvider.GetIconWithOptionalSpace (fsi) + fsi.Name).Trim (); } - private int CalculateOkButtonPosX () + private int CalculateOkButtonPosX (View? _) { if (!IsInitialized || !_btnOk.IsInitialized || !_btnCancel.IsInitialized) { diff --git a/Terminal.Gui/Views/Menu/Menuv2.cs b/Terminal.Gui/Views/Menu/Menuv2.cs index 7a0b0b1f18..1eb5f6cc49 100644 --- a/Terminal.Gui/Views/Menu/Menuv2.cs +++ b/Terminal.Gui/Views/Menu/Menuv2.cs @@ -93,8 +93,8 @@ void MenuItemOnAccepted (object? sender, CommandEventArgs e) } case Line line: // Grow line so we get auto-join line - line.X = Pos.Func (() => -Border!.Thickness.Left); - line.Width = Dim.Fill ()! + Dim.Func (() => Border!.Thickness.Right); + line.X = Pos.Func (_ => -Border!.Thickness.Left); + line.Width = Dim.Fill ()! + Dim.Func (_ => Border!.Thickness.Right); break; } diff --git a/Terminal.Gui/Views/Menuv1/Menu.cs b/Terminal.Gui/Views/Menuv1/Menu.cs index 8969595acd..c4579aab35 100644 --- a/Terminal.Gui/Views/Menuv1/Menu.cs +++ b/Terminal.Gui/Views/Menuv1/Menu.cs @@ -527,7 +527,7 @@ private void Application_RootMouseEvent (object? sender, MouseEventArgs a) private void Application_UnGrabbedMouse (object? sender, ViewEventArgs a) { - if (_host.IsMenuOpen) + if (_host is { IsMenuOpen: true }) { _host.CloseAllMenus (); } diff --git a/Terminal.Gui/Views/MessageBox.cs b/Terminal.Gui/Views/MessageBox.cs index 55a8654414..478d795654 100644 --- a/Terminal.Gui/Views/MessageBox.cs +++ b/Terminal.Gui/Views/MessageBox.cs @@ -394,12 +394,12 @@ params string [] buttons }; d.Width = Dim.Auto (DimAutoStyle.Auto, - minimumContentDim: Dim.Func (() => (int)((Application.Screen.Width - d.GetAdornmentsThickness ().Horizontal) * (DefaultMinimumWidth / 100f))), - maximumContentDim: Dim.Func (() => (int)((Application.Screen.Width - d.GetAdornmentsThickness ().Horizontal) * 0.9f))); + minimumContentDim: Dim.Func (_ => (int)((Application.Screen.Width - d.GetAdornmentsThickness ().Horizontal) * (DefaultMinimumWidth / 100f))), + maximumContentDim: Dim.Func (_ => (int)((Application.Screen.Width - d.GetAdornmentsThickness ().Horizontal) * 0.9f))); d.Height = Dim.Auto (DimAutoStyle.Auto, - minimumContentDim: Dim.Func (() => (int)((Application.Screen.Height - d.GetAdornmentsThickness ().Vertical) * (DefaultMinimumHeight / 100f))), - maximumContentDim: Dim.Func (() => (int)((Application.Screen.Height - d.GetAdornmentsThickness ().Vertical) * 0.9f))); + minimumContentDim: Dim.Func (_ => (int)((Application.Screen.Height - d.GetAdornmentsThickness ().Vertical) * (DefaultMinimumHeight / 100f))), + maximumContentDim: Dim.Func (_ => (int)((Application.Screen.Height - d.GetAdornmentsThickness ().Vertical) * 0.9f))); if (width != 0) diff --git a/Terminal.Gui/Views/NumericUpDown.cs b/Terminal.Gui/Views/NumericUpDown.cs index bb896db57b..cfa5bbc6c3 100644 --- a/Terminal.Gui/Views/NumericUpDown.cs +++ b/Terminal.Gui/Views/NumericUpDown.cs @@ -62,7 +62,7 @@ public NumericUpDown () Text = Value?.ToString () ?? "Err", X = Pos.Right (_down), Y = Pos.Top (_down), - Width = Dim.Auto (minimumContentDim: Dim.Func (() => string.Format (Format, Value).GetColumns())), + Width = Dim.Auto (minimumContentDim: Dim.Func (_ => string.Format (Format, Value).GetColumns())), Height = 1, TextAlignment = Alignment.Center, CanFocus = true, diff --git a/Terminal.Gui/Views/ScrollBar/ScrollBar.cs b/Terminal.Gui/Views/ScrollBar/ScrollBar.cs index 7aadd28499..e6b1eb5908 100644 --- a/Terminal.Gui/Views/ScrollBar/ScrollBar.cs +++ b/Terminal.Gui/Views/ScrollBar/ScrollBar.cs @@ -40,11 +40,11 @@ public ScrollBar () // Set the default width and height based on the orientation - fill Viewport Width = Dim.Auto ( DimAutoStyle.Content, - Dim.Func (() => Orientation == Orientation.Vertical ? 1 : SuperView?.Viewport.Width ?? 0)); + Dim.Func (_ => Orientation == Orientation.Vertical ? 1 : SuperView?.Viewport.Width ?? 0)); Height = Dim.Auto ( DimAutoStyle.Content, - Dim.Func (() => Orientation == Orientation.Vertical ? SuperView?.Viewport.Height ?? 0 : 1)); + Dim.Func (_ => Orientation == Orientation.Vertical ? SuperView?.Viewport.Height ?? 0 : 1)); _decreaseButton = new () { diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index 371245ba09..e4fee2f2a2 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -106,8 +106,8 @@ internal Dim GetWidthDimAuto () { return Dim.Auto ( DimAutoStyle.Content, - minimumContentDim: Dim.Func (() => _minimumNaturalWidth ?? 0), - maximumContentDim: Dim.Func (() => _minimumNaturalWidth ?? 0))!; + minimumContentDim: Dim.Func (_ => _minimumNaturalWidth ?? 0), + maximumContentDim: Dim.Func (_ => _minimumNaturalWidth ?? 0))!; } private AlignmentModes _alignmentModes = AlignmentModes.StartToEnd | AlignmentModes.IgnoreFirstOrLast; @@ -540,7 +540,7 @@ private void SetHelpViewDefaultLayout () HelpView.X = Pos.Align (Alignment.End, AlignmentModes); _maxHelpWidth = HelpView.Text.GetColumns (); - HelpView.Width = Dim.Auto (DimAutoStyle.Text, maximumContentDim: Dim.Func ((() => _maxHelpWidth))); + HelpView.Width = Dim.Auto (DimAutoStyle.Text, maximumContentDim: Dim.Func ((_ => _maxHelpWidth))); HelpView.Height = Dim.Fill (); HelpView.Visible = true; @@ -672,7 +672,7 @@ private void SetKeyViewDefaultLayout () } KeyView.X = Pos.Align (Alignment.End, AlignmentModes); - KeyView.Width = Dim.Auto (DimAutoStyle.Text, minimumContentDim: Dim.Func (() => MinimumKeyTextSize)); + KeyView.Width = Dim.Auto (DimAutoStyle.Text, minimumContentDim: Dim.Func (_ => MinimumKeyTextSize)); KeyView.Height = Dim.Fill (); KeyView.Visible = true; diff --git a/Terminal.Gui/Views/Wizard/Wizard.cs b/Terminal.Gui/Views/Wizard/Wizard.cs index 7fc288b726..3e00e22bba 100644 --- a/Terminal.Gui/Views/Wizard/Wizard.cs +++ b/Terminal.Gui/Views/Wizard/Wizard.cs @@ -490,7 +490,7 @@ private void SizeStep (WizardStep step) step.Height = Dim.Fill ( Dim.Func ( - () => IsInitialized + v => IsInitialized ? SubViews.First (view => view.Y.Has (out _)).Frame.Height + 1 : 1)); // for button frame (+1 for lineView) step.Width = Dim.Fill (); @@ -502,9 +502,9 @@ private void SizeStep (WizardStep step) step.Height = Dim.Fill ( Dim.Func ( - () => IsInitialized - ? SubViews.First (view => view.Y.Has (out _)).Frame.Height + 1 - : 2)); // for button frame (+1 for lineView) + v => IsInitialized + ? SubViews.First (view => view.Y.Has (out _)).Frame.Height + 1 + : 2)); // for button frame (+1 for lineView) step.Width = Dim.Fill (); } } diff --git a/Tests/TerminalGuiFluentTesting/GuiTestContext.cs b/Tests/TerminalGuiFluentTesting/GuiTestContext.cs index 6321a86cbc..37b5577256 100644 --- a/Tests/TerminalGuiFluentTesting/GuiTestContext.cs +++ b/Tests/TerminalGuiFluentTesting/GuiTestContext.cs @@ -25,75 +25,95 @@ public class GuiTestContext : IDisposable internal GuiTestContext (Func topLevelBuilder, int width, int height, V2TestDriver driver) { - IApplication origApp = ApplicationImpl.Instance; - ILogger? origLogger = Logging.Logger; - _logsSb = new (); - _driver = driver; - - _netInput = new (_cts.Token); - _winInput = new (_cts.Token); - - _output.Size = new (width, height); - - var v2 = new ApplicationV2 ( - () => _netInput, - () => _output, - () => _winInput, - () => _output); - - var booting = new SemaphoreSlim (0, 1); - lock (_threadLock) { - // Start the application in a background thread - _runTask = Task.Run ( - () => - { - try - { - ApplicationImpl.ChangeInstance (v2); + IApplication origApp = ApplicationImpl.Instance; + ILogger? origLogger = Logging.Logger; + _logsSb = new (); + _driver = driver; - ILogger logger = LoggerFactory.Create ( - builder => - builder.SetMinimumLevel (LogLevel.Trace) - .AddProvider (new TextWriterLoggerProvider (new StringWriter (_logsSb)))) - .CreateLogger ("Test Logging"); - Logging.Logger = logger; + _netInput = new (_cts.Token); + _winInput = new (_cts.Token); - v2.Init (null, GetDriverName ()); + _output.Size = new (width, height); - booting.Release (); + var v2 = new ApplicationV2 ( + () => _netInput, + () => _output, + () => _winInput, + () => _output); - Toplevel t = topLevelBuilder (); - t.Closed += (s, e) => { _finished = true; }; - Application.Run (t); // This will block, but it's on a background thread now + var booting = new SemaphoreSlim (0, 1); - t.Dispose (); - Application.Shutdown (); - } - catch (OperationCanceledException) - { } - catch (Exception ex) - { - _ex = ex; - } - finally + // Start the application in a background thread + _runTask = Task.Run (() => + { + while (Application.Top is { }) { - ApplicationImpl.ChangeInstance (origApp); - Logging.Logger = origLogger; - _finished = true; + Task.Delay (300).Wait (); } - }, - _cts.Token); - } + }) + .ContinueWith ( + (task, _) => + { + try + { + if (task.IsFaulted) + { + _ex = task.Exception ?? new Exception ("Unknown error in background task"); + } + + // Ensure we are not running on the main thread + if (ApplicationImpl.Instance != origApp) + { + throw new InvalidOperationException ( + "Application instance is not the original one, this should not happen."); + } + + ApplicationImpl.ChangeInstance (v2); + + ILogger logger = LoggerFactory.Create (builder => + builder.SetMinimumLevel (LogLevel.Trace) + .AddProvider ( + new TextWriterLoggerProvider ( + new StringWriter (_logsSb)))) + .CreateLogger ("Test Logging"); + Logging.Logger = logger; + + v2.Init (null, GetDriverName ()); + + booting.Release (); + + Toplevel t = topLevelBuilder (); + t.Closed += (s, e) => { _finished = true; }; + Application.Run (t); // This will block, but it's on a background thread now + + t.Dispose (); + Application.Shutdown (); + } + catch (OperationCanceledException) + { } + catch (Exception ex) + { + _ex = ex; + } + finally + { + ApplicationImpl.ChangeInstance (origApp); + Logging.Logger = origLogger; + _finished = true; + } + }, + _cts.Token); + + // Wait for booting to complete with a timeout to avoid hangs + if (!booting.WaitAsync (TimeSpan.FromSeconds (10)).Result) + { + throw new TimeoutException ("Application failed to start within the allotted time."); + } - // Wait for booting to complete with a timeout to avoid hangs - if (!booting.WaitAsync (TimeSpan.FromSeconds (10)).Result) - { - throw new TimeoutException ("Application failed to start within the allotted time."); + WaitIteration (); } - - WaitIteration (); } private string GetDriverName () diff --git a/Tests/UnitTests/View/Draw/ClearViewportTests.cs b/Tests/UnitTests/View/Draw/ClearViewportTests.cs index 5aa69954fe..94a2117ecb 100644 --- a/Tests/UnitTests/View/Draw/ClearViewportTests.cs +++ b/Tests/UnitTests/View/Draw/ClearViewportTests.cs @@ -114,7 +114,6 @@ public void Clear_ClearsEntireViewport () superView.BeginInit (); superView.EndInit (); superView.LayoutSubViews (); - superView.Draw (); DriverAssert.AssertDriverContentsWithFrameAre ( diff --git a/Tests/UnitTests/Views/LabelTests.cs b/Tests/UnitTests/Views/LabelTests.cs index 374750f2bc..582c457474 100644 --- a/Tests/UnitTests/Views/LabelTests.cs +++ b/Tests/UnitTests/Views/LabelTests.cs @@ -94,7 +94,7 @@ public void HotKey_Command_Does_Not_Accept () public void Text_Set_With_AnchorEnd_Works () { var label = new Label { Y = Pos.Center (), Text = "Say Hello ä½ " }; - label.X = Pos.AnchorEnd (0) - Pos.Func (() => label.TextFormatter.Text.GetColumns ()); + label.X = Pos.AnchorEnd (0) - Pos.Func (_ => label.TextFormatter.Text.GetColumns ()); var win = new Window { Width = Dim.Fill (), Height = Dim.Fill () }; win.Add (label); diff --git a/Tests/UnitTests/Views/TileViewTests.cs b/Tests/UnitTests/Views/TileViewTests.cs index 8981738e71..2c0306c4fe 100644 --- a/Tests/UnitTests/Views/TileViewTests.cs +++ b/Tests/UnitTests/Views/TileViewTests.cs @@ -819,6 +819,10 @@ public void TestDisposal_NoEarlyDisposalsOfUsersViews_DuringRebuildForTileCount Assert.Equal (1, myReusableView.DisposalCount); } ); + + Assert.NotNull (Application.Top); + Application.Top.Dispose (); + Application.Shutdown (); } [Theory] @@ -848,6 +852,10 @@ public void TestDisposal_NoEarlyDisposalsOfUsersViews_DuringRemoveTile (int idx) Assert.True (myReusableView.DisposalCount >= 1); } ); + + Assert.NotNull (Application.Top); + Application.Top.Dispose (); + Application.Shutdown (); } [Fact] @@ -1606,7 +1614,7 @@ public void TestTileView_CannotSetSplitterPosToFuncEtc () var ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Right (tileView))); Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosView", ex.Message); - ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Func (() => 1))); + ex = Assert.Throws (() => tileView.SetSplitterPos (0, Pos.Func (_ => 1))); Assert.Equal ("Only Percent and Absolute values are supported. Passed value was PosFunc", ex.Message); // Also not allowed because this results in a PosCombine diff --git a/Tests/UnitTestsParallelizable/View/Draw/NeedsDrawTests.cs b/Tests/UnitTestsParallelizable/View/Draw/NeedsDrawTests.cs index 1a0839eb32..2f425ccd44 100644 --- a/Tests/UnitTestsParallelizable/View/Draw/NeedsDrawTests.cs +++ b/Tests/UnitTestsParallelizable/View/Draw/NeedsDrawTests.cs @@ -10,7 +10,7 @@ public void NeedsDraw_False_If_Width_Height_Zero () View view = new () { Width = 0, Height = 0 }; view.BeginInit (); view.EndInit (); - Assert.True (view.NeedsDraw); + Assert.False (view.NeedsDraw); //Assert.False (view.SubViewNeedsDraw); } @@ -70,14 +70,16 @@ public void NeedsDraw_True_After_BeginInit () view.NeedsDraw = false; view.BeginInit (); - Assert.True (view.NeedsDraw); // Because layout is still needed + Assert.False (view.NeedsDraw); // Because layout is still needed view.Layout (); - Assert.False (view.NeedsDraw); + // NeedsDraw is true after layout and NeedsLayout is false if SubViewsLaidOut doesn't call SetNeedsLayout + Assert.True (view.NeedsDraw); + Assert.False (view.NeedsLayout); } [Fact] - public void NeedsDraw_False_After_EndInit () + public void NeedsDraw_True_After_EndInit_Where_Call_Layout () { var view = new View { Width = 2, Height = 2, BorderStyle = LineStyle.Single }; Assert.True (view.NeedsDraw); @@ -96,7 +98,7 @@ public void NeedsDraw_False_After_EndInit () } [Fact] - public void NeedsDraw_After_SetLayoutNeeded () + public void NeedsDraw_After_SetLayoutNeeded_And_Layout () { var view = new View { Width = 2, Height = 2 }; Assert.True (view.NeedsDraw); @@ -107,8 +109,12 @@ public void NeedsDraw_After_SetLayoutNeeded () Assert.False (view.NeedsLayout); view.SetNeedsLayout (); - Assert.True (view.NeedsDraw); + Assert.False (view.NeedsDraw); Assert.True (view.NeedsLayout); + + view.Layout (); + Assert.True (view.NeedsDraw); + Assert.False (view.NeedsLayout); } [Fact] @@ -121,21 +127,27 @@ public void NeedsDraw_False_After_SetRelativeLayout_Absolute_Dims () Assert.False (view.NeedsDraw); Assert.False (view.NeedsLayout); - // SRL won't change anything since the view is Absolute + // SRL won't change anything since the view frame wasn't changed view.SetRelativeLayout (Application.Screen.Size); Assert.False (view.NeedsDraw); view.SetNeedsLayout (); - // SRL won't change anything since the view is Absolute + // SRL won't change anything since the view frame wasn't changed + // SRL doesn't depend on NeedsLayout, but LayoutSubViews does view.SetRelativeLayout (Application.Screen.Size); + Assert.False (view.NeedsDraw); + Assert.True (view.NeedsLayout); + + view.Layout (); Assert.True (view.NeedsDraw); + Assert.False (view.NeedsLayout); view.NeedsDraw = false; - // SRL won't change anything since the view is Absolute. However, Layout has not been called + // SRL won't change anything since the view frame wasn't changed. However, Layout has not been called view.SetRelativeLayout (new (10, 10)); - Assert.True (view.NeedsDraw); + Assert.False (view.NeedsDraw); } [Fact] @@ -149,17 +161,20 @@ public void NeedsDraw_False_After_SetRelativeLayout_Relative_Dims () Width = Dim.Fill (), Height = Dim.Fill () }; - Assert.True (superView.NeedsDraw); + + // A layout wasn't called yet, so NeedsDraw is still empty + Assert.False (superView.NeedsDraw); superView.Add (view); - Assert.True (view.NeedsDraw); - Assert.True (superView.NeedsDraw); + // A layout wasn't called yet, so NeedsDraw is still empty + Assert.False (view.NeedsDraw); + Assert.False (superView.NeedsDraw); superView.BeginInit (); - Assert.True (view.NeedsDraw); - Assert.True (superView.NeedsDraw); + Assert.False (view.NeedsDraw); + Assert.False (superView.NeedsDraw); - superView.EndInit (); + superView.EndInit (); // Call Layout Assert.True (view.NeedsDraw); Assert.True (superView.NeedsDraw); @@ -177,9 +192,10 @@ public void NeedsDraw_False_After_SetRelativeLayout_10x10 () Width = Dim.Fill (), Height = Dim.Fill () }; - Assert.True (superView.NeedsDraw); + Assert.False (superView.NeedsDraw); superView.Layout (); + Assert.True (superView.NeedsDraw); superView.NeedsDraw = false; superView.SetRelativeLayout (new (10, 10)); diff --git a/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.DimTypes.cs b/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.DimTypes.cs index c5c2d3b9d3..002375d3c9 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.DimTypes.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.DimTypes.cs @@ -179,7 +179,7 @@ public void With_SubView_Using_DimFill_And_Another_SubView (int minWidth, int ma public void With_SubView_Using_DimFunc () { var view = new View (); - var subview = new View { Width = Dim.Func (() => 20), Height = Dim.Func (() => 25) }; + var subview = new View { Width = Dim.Func (_ => 20), Height = Dim.Func (_ => 25) }; view.Add (subview); subview.SetRelativeLayout (new (100, 100)); diff --git a/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.PosTypes.cs b/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.PosTypes.cs index fd854b1e48..d14dfc7c09 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.PosTypes.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Dim.AutoTests.PosTypes.cs @@ -577,6 +577,7 @@ public void With_DimViewSubView_And_SubView_Using_PosAnchorEnd (int minWidth, in Assert.Equal (view.Viewport.Width - subview.Frame.Width, subview.Frame.X); Assert.Equal (view.Viewport.Height - subview.Frame.Height, subview.Frame.Y); } + [Theory] [InlineData (0, 10, 0, 10, 10, 2)] [InlineData (0, 5, 0, 5, 5, 3)] // max width of 5 should cause wordwrap at 5 giving a height of 2 + 1 @@ -638,7 +639,7 @@ public void With_SubView_Using_PosFunc () Width = Dim.Auto (), Height = Dim.Auto (), }; - var subview = new View { X = Pos.Func (() => 20), Y = Pos.Func (() => 25) }; + var subview = new View { X = Pos.Func (_ => 20), Y = Pos.Func (_ => 25) }; view.Add (subview); view.SetRelativeLayout (new (100, 100)); diff --git a/Tests/UnitTestsParallelizable/View/Layout/Dim.FillTests.cs b/Tests/UnitTestsParallelizable/View/Layout/Dim.FillTests.cs index ec43c95389..ea93099f45 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Dim.FillTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Dim.FillTests.cs @@ -123,12 +123,12 @@ public void DimFill_SetsValue () [Fact] public void DimFill_Margin_Is_Dim_SetsValue () { - Dim testMargin = Dim.Func (() => 0); + Dim testMargin = Dim.Func (_ => 0); Dim dim = Dim.Fill (testMargin); Assert.Equal (0, dim!.GetAnchor (0)); - testMargin = Dim.Func (() => 5); + testMargin = Dim.Func (_ => 5); dim = Dim.Fill (testMargin); Assert.Equal (-5, dim!.GetAnchor (0)); } diff --git a/Tests/UnitTestsParallelizable/View/Layout/Dim.FuncTests.cs b/Tests/UnitTestsParallelizable/View/Layout/Dim.FuncTests.cs index 7dfc2a7bb6..a94a858cba 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Dim.FuncTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Dim.FuncTests.cs @@ -10,8 +10,8 @@ public class DimFuncTests (ITestOutputHelper output) [Fact] public void DimFunc_Equal () { - Func f1 = () => 0; - Func f2 = () => 0; + Func f1 = _ => 0; + Func f2 = _ => 0; Dim dim1 = Func (f1); Dim dim2 = Func (f1); @@ -20,7 +20,7 @@ public void DimFunc_Equal () dim2 = Func (f2); Assert.NotEqual (dim1, dim2); - f2 = () => 1; + f2 = _ => 1; dim2 = Func (f2); Assert.NotEqual (dim1, dim2); } @@ -29,7 +29,7 @@ public void DimFunc_Equal () public void DimFunc_SetsValue () { var text = "Test"; - Dim dim = Func (() => text.Length); + Dim dim = Func (_ => text.Length); Assert.Equal ("DimFunc(4)", dim.ToString ()); text = "New Test"; @@ -42,8 +42,51 @@ public void DimFunc_SetsValue () [Fact] public void DimFunc_Calculate_ReturnsCorrectValue () { - var dim = new DimFunc (() => 10); + var dim = new DimFunc (_ => 10); int result = dim.Calculate (0, 100, null, Dimension.None); Assert.Equal (10, result); } + + [Fact] + public void DimFunc_View_Equal () + { + Func f1 = v => v.Frame.Width; + Func f2 = v => v.Frame.Width; + View view1 = new (); + View view2 = new (); + + Dim dim1 = Func (f1, view1); + Dim dim2 = Func (f1, view1); + Assert.Equal (dim1, dim2); + + dim2 = Func (f2, view2); + Assert.NotEqual (dim1, dim2); + + view2.Width = 1; + Assert.NotEqual (dim1, dim2); + Assert.Equal (1, f2 (view2)); + } + + [Fact] + public void DimFunc_View_SetsValue () + { + View view = new () { Text = "Test" }; + Dim dim = Func (v => v.Text.Length, view); + Assert.Equal ("DimFunc(4)", dim.ToString ()); + + view.Text = "New Test"; + Assert.Equal ("DimFunc(8)", dim.ToString ()); + + view.Text = ""; + Assert.Equal ("DimFunc(0)", dim.ToString ()); + } + + [Fact] + public void DimFunc_View_Calculate_ReturnsCorrectValue () + { + View view = new () { Width = 10 }; + var dim = new DimFunc (v => v.Frame.Width, view); + int result = dim.Calculate (0, 100, view, Dimension.None); + Assert.Equal (10, result); + } } diff --git a/Tests/UnitTestsParallelizable/View/Layout/FrameTests.cs b/Tests/UnitTestsParallelizable/View/Layout/FrameTests.cs index a58475158f..c6d1fd9194 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/FrameTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/FrameTests.cs @@ -61,10 +61,10 @@ public void Frame_Empty_Initializer_Overrides_Base () Assert.Equal (view.Height, frame.Height); // Set back to original state - view.X = Pos.Func (() => 10); - view.Y = Pos.Func (() => 20); - view.Width = Dim.Func (() => 30); - view.Height = Dim.Func (() => 40); + view.X = Pos.Func (_ => 10); + view.Y = Pos.Func (_ => 20); + view.Width = Dim.Func (_ => 30); + view.Height = Dim.Func (_ => 40); Assert.True (view.NeedsLayout); view.Layout (); @@ -281,10 +281,10 @@ private class FrameTestView : View { public FrameTestView () { - X = Pos.Func (() => 10); - Y = Pos.Func (() => 20); - Width = Dim.Func (() => 30); - Height = Dim.Func (() => 40); + X = Pos.Func (_ => 10); + Y = Pos.Func (_ => 20); + Width = Dim.Func (_ => 30); + Height = Dim.Func (_ => 40); } } diff --git a/Tests/UnitTestsParallelizable/View/Layout/Pos.FuncTests.cs b/Tests/UnitTestsParallelizable/View/Layout/Pos.FuncTests.cs index 9874c91602..9665aceed1 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Pos.FuncTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Pos.FuncTests.cs @@ -9,14 +9,14 @@ public class PosFuncTests (ITestOutputHelper output) [Fact] public void PosFunc_Equal () { - Func f1 = () => 0; - Func f2 = () => 0; + Func f1 = _ => 0; + Func f2 = _ => 0; Pos pos1 = Pos.Func (f1); Pos pos2 = Pos.Func (f1); Assert.Equal (pos1, pos2); - f2 = () => 1; + f2 = _ => 1; pos2 = Pos.Func (f2); Assert.NotEqual (pos1, pos2); } @@ -25,7 +25,7 @@ public void PosFunc_Equal () public void PosFunc_SetsValue () { var text = "Test"; - Pos pos = Pos.Func (() => text.Length); + Pos pos = Pos.Func (_ => text.Length); Assert.Equal ("PosFunc(4)", pos.ToString ()); text = "New Test"; @@ -38,8 +38,52 @@ public void PosFunc_SetsValue () [Fact] public void PosFunc_Calculate_ReturnsCorrectValue () { - var pos = new PosFunc (() => 10); + var pos = new PosFunc (_ => 10); int result = pos.Calculate (0, 100, null, Dimension.None); Assert.Equal (10, result); } + + [Fact] + public void PosFunc_View_Equal () + { + Func f1 = v => v.Frame.X; + Func f2 = v => v.Frame.X; + View view1 = new (); + View view2 = new (); + + Pos pos1 = Pos.Func (f1, view1); + Pos pos2 = Pos.Func (f1, view1); + Assert.Equal (pos1, pos2); + + f2 = _ => 1; + pos2 = Pos.Func (f2, view2); + Assert.NotEqual (pos1, pos2); + + view2.X = 1; + Assert.NotEqual (pos1, pos2); + Assert.Equal (1, f2 (view2)); + } + + [Fact] + public void PosFunc_View_SetsValue () + { + View view = new () { Text = "Test" }; + Pos pos = Pos.Func (v => v.Text.Length, view); + Assert.Equal ("PosFunc(4)", pos.ToString ()); + + view.Text = "New Test"; + Assert.Equal ("PosFunc(8)", pos.ToString ()); + + view.Text = ""; + Assert.Equal ("PosFunc(0)", pos.ToString ()); + } + + [Fact] + public void PosFunc_View_Calculate_ReturnsCorrectValue () + { + View view = new () { X = 10 }; + var pos = new PosFunc (v => v.Frame.X, view); + int result = pos.Calculate (0, 100, view, Dimension.None); + Assert.Equal (10, result); + } } diff --git a/Tests/UnitTestsParallelizable/View/Layout/Pos.Tests.cs b/Tests/UnitTestsParallelizable/View/Layout/Pos.Tests.cs index fcfc40456e..b37cf622f9 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/Pos.Tests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/Pos.Tests.cs @@ -21,7 +21,7 @@ public void PosFactor_Calculate_ReturnsExpectedValue () [Fact] public void PosFunc_Calculate_ReturnsExpectedValue () { - var posFunc = new PosFunc (() => 5); + var posFunc = new PosFunc (_ => 5); int result = posFunc.Calculate (10, new DimAbsolute (2), null, Dimension.None); Assert.Equal (5, result); } @@ -86,7 +86,7 @@ public void PosCombine_DoesNotReturn () public void PosFunction_SetsValue () { var text = "Test"; - Pos pos = Pos.Func (() => text.Length); + Pos pos = Pos.Func (_ => text.Length); Assert.Equal ("PosFunc(4)", pos.ToString ()); text = "New Test"; diff --git a/Tests/UnitTestsParallelizable/View/Layout/SetLayoutTests.cs b/Tests/UnitTestsParallelizable/View/Layout/SetLayoutTests.cs index 2aa4e65149..44a7309d98 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/SetLayoutTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/SetLayoutTests.cs @@ -597,7 +597,7 @@ public void Set_Height_Non_DimAbsolute_Explicit_Layout_Required () Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Height); - v.Height = Dim.Func (() => 10); + v.Height = Dim.Func (_ => 10); Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Height); @@ -649,7 +649,7 @@ public void Set_Width_Non_DimAbsolute_Explicit_Layout_Required () Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Width); - v.Width = Dim.Func (() => 10); + v.Width = Dim.Func (_ => 10); Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Width); @@ -675,7 +675,7 @@ public void Set_X_Non_PosAbsolute_Explicit_Layout_Required () Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.X); - v.X = Pos.Func (() => 10); + v.X = Pos.Func (_ => 10); Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.X); @@ -731,7 +731,7 @@ public void Set_Y_Non_PosAbsolute_Explicit_Layout_Required () Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Y); - v.Y = Pos.Func (() => 10); + v.Y = Pos.Func (_ => 10); Assert.True (v.NeedsLayout); Assert.Equal (0, v.Frame.Y); diff --git a/Tests/UnitTestsParallelizable/View/Layout/SetRelativeLayoutTests.cs b/Tests/UnitTestsParallelizable/View/Layout/SetRelativeLayoutTests.cs index 133ac3ab37..bf032df2d8 100644 --- a/Tests/UnitTestsParallelizable/View/Layout/SetRelativeLayoutTests.cs +++ b/Tests/UnitTestsParallelizable/View/Layout/SetRelativeLayoutTests.cs @@ -1,4 +1,5 @@ -using UnitTests; +using JetBrains.Annotations; +using UnitTests; using Xunit.Abstractions; using static Terminal.Gui.ViewBase.Dim; @@ -403,7 +404,7 @@ public void PosDimFunc () }; view.X = Pos.AnchorEnd (0) - Pos.Func (GetViewWidth); - int GetViewWidth () { return view.Frame.Width; } + int GetViewWidth ([CanBeNull] View _) { return view.Frame.Width; } // view will be 3 chars wide. It's X will be 27 (30 - 3). // BUGBUG: IsInitialized need to be true before calculate