From cd8e4ea1b3e4ce2ae4707a462766687b1796c43c Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 01:26:41 +0000 Subject: [PATCH 001/101] WIP try to build --- README.md | 4 +-- src/Design.cs | 14 +++++----- src/MenuTracker.cs | 2 +- src/TerminalGuiDesigner.csproj | 6 ++-- src/ToCode/Property.cs | 6 ++-- src/UI/Windows/ArrayEditor.Designer.cs | 30 ++++++++++---------- src/UI/Windows/DimEditor.Designer.cs | 34 +++++++++++------------ src/UI/Windows/PosEditor.Designer.cs | 38 +++++++++++++------------- src/ViewFactory.cs | 8 +++--- tests/PropertyTests.cs | 8 +++--- tests/RadioGroupTests.cs | 14 +++++----- 11 files changed, 82 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index b3d660dc..08e2dff9 100644 --- a/README.md +++ b/README.md @@ -198,12 +198,12 @@ italics are experimental and require passing the `-e` flag when starting applica - [x] GraphView - [x] HexView - [x] Label - - [x] LineView + - [x] Line - [x] ListView - [x] MenuBar - [ ] Copy/Paste preserve menu entries - [x] ProgressBar - - [x] RadioGroup + - [x] OptionSelector - [ ] [SplitContainer](https://github.com/gui-cs/Terminal.Gui/pull/2258) (Unreleased) - [ ] Copy/Paste preserve split content panels - [x] StatusBar diff --git a/src/Design.cs b/src/Design.cs index 13acf5aa..5d89ba2f 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -44,7 +44,7 @@ public class Design typeof(Toplevel), typeof(GraphView), typeof(HexView), - typeof(LineView), + typeof(Line), typeof(ListView), typeof(MenuBar), typeof(TableView), @@ -696,10 +696,10 @@ private IEnumerable LoadDesignableProperties() yield return this.CreateProperty(nameof(Button.IsDefault)); } - if (this.View is LineView) + if (this.View is Line) { - yield return this.CreateProperty(nameof(LineView.LineRune)); - yield return this.CreateProperty(nameof(LineView.Orientation)); + yield return this.CreateProperty(nameof(Line.LineRune)); + yield return this.CreateProperty(nameof(Line.Orientation)); } if (this.View is ProgressBar) @@ -798,9 +798,9 @@ private IEnumerable LoadDesignableProperties() yield return this.CreateSubProperty(nameof(TabStyle.TabsOnBottom), nameof(TabView.Style), tabView.Style); } - if (this.View is RadioGroup) + if (this.View is OptionSelector) { - yield return this.CreateProperty(nameof(RadioGroup.RadioLabels)); + yield return this.CreateProperty(nameof(OptionSelector.RadioLabels)); } if (viewType.IsGenericType(typeof(NumericUpDown<>))) @@ -840,7 +840,7 @@ private bool ShowTextProperty() } // Do not let Text be set on Slider or Slider<> implementations as weird stuff happens - if(this.View.GetType().Name.StartsWith("Slider") || View is RadioGroup || View.GetType().IsGenericType(typeof(NumericUpDown<>))) + if(this.View.GetType().Name.StartsWith("Slider") || View is OptionSelector || View.GetType().IsGenericType(typeof(NumericUpDown<>))) { return false; } diff --git a/src/MenuTracker.cs b/src/MenuTracker.cs index 30a65d77..6ad44636 100644 --- a/src/MenuTracker.cs +++ b/src/MenuTracker.cs @@ -196,7 +196,7 @@ internal static bool ConvertMenuBarItemToRegularItemIfEmpty( MenuBarItem bar, [N { Title = bar.Title, Data = bar.Data, - ShortcutKey = bar.ShortcutKey + Key = bar.Key }; return true; diff --git a/src/TerminalGuiDesigner.csproj b/src/TerminalGuiDesigner.csproj index 22ec0fd1..a7ba1e9a 100644 --- a/src/TerminalGuiDesigner.csproj +++ b/src/TerminalGuiDesigner.csproj @@ -70,7 +70,7 @@ * Fix right click on TableView headers * Improve context menu layout for menus, status bars etc * Improved private field naming conventions - * RadioGroup can now be set to horizontal + * OptionSelector can now be set to horizontal v1.0.19 * Added `-e` experimental mode flag that lets you create new Toplevel and View classes * Added dotted border around Views that do not have any visible boundary (e.g. `View`, `TabView` with ShowBorder off) @@ -101,7 +101,7 @@ * Deleting the last item on a MenuBar now removes the MenuBar too * Added multi copy/paste (drag selection box and copy/paste). Still restricted to non container views (i.e. not TabView etc) v1.0.13 - * Changing LineView Orientation now properly flips rune and Width/Height + * Changing Line Orientation now properly flips rune and Width/Height * Fixed mouse drag moving and resizing container views (e.g. TabView) * Fixed bug where you were able to copy/paste the root view v1.0.12 @@ -165,7 +165,7 @@ - + diff --git a/src/ToCode/Property.cs b/src/ToCode/Property.cs index 78bec35f..8ec21f60 100644 --- a/src/ToCode/Property.cs +++ b/src/ToCode/Property.cs @@ -100,10 +100,10 @@ public virtual void SetValue(object? value) { value = AdjustValueBeingSet(value); - // if a LineView and changing Orientation then also flip + // if a Line and changing Orientation then also flip // the Height/Width and set appropriate new rune - if (this.PropertyInfo.Name == nameof(LineView.Orientation) - && this.Design.View is LineView v && value is Orientation newOrientation) + if (this.PropertyInfo.Name == nameof(Line.Orientation) + && this.Design.View is Line v && value is Orientation newOrientation) { switch (newOrientation) { diff --git a/src/UI/Windows/ArrayEditor.Designer.cs b/src/UI/Windows/ArrayEditor.Designer.cs index 9e6dcdec..0cbb4d2a 100644 --- a/src/UI/Windows/ArrayEditor.Designer.cs +++ b/src/UI/Windows/ArrayEditor.Designer.cs @@ -38,7 +38,7 @@ public partial class ArrayEditor : Terminal.Gui.Views.Dialog { private Terminal.Gui.Views.Button btnEdit; - private Terminal.Gui.Views.LineView lineView; + private Terminal.Gui.Views.Line Line; private Terminal.Gui.Views.Button btnOk; @@ -47,7 +47,7 @@ public partial class ArrayEditor : Terminal.Gui.Views.Dialog { private void InitializeComponent() { this.btnCancel = new Terminal.Gui.Views.Button(); this.btnOk = new Terminal.Gui.Views.Button(); - this.lineView = new Terminal.Gui.Views.LineView(); + this.Line = new Terminal.Gui.Views.Line(); this.btnEdit = new Terminal.Gui.Views.Button(); this.btnMoveDown = new Terminal.Gui.Views.Button(); this.btnMoveUp = new Terminal.Gui.Views.Button(); @@ -160,19 +160,19 @@ private void InitializeComponent() { this.btnEdit.TextAlignment = Terminal.Gui.ViewBase.Alignment.Center; this.btnEdit.IsDefault = false; this.Add(this.btnEdit); - this.lineView.Width = Dim.Fill(1); - this.lineView.Height = 1; - this.lineView.X = -1; - this.lineView.Y = Pos.AnchorEnd(3); - this.lineView.Visible = true; - this.lineView.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; - this.lineView.CanFocus = true; - this.lineView.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; - this.lineView.Data = "lineView"; - this.lineView.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.lineView.LineRune = new System.Text.Rune('─'); - this.lineView.Orientation = Terminal.Gui.ViewBase.Orientation.Horizontal; - this.Add(this.lineView); + this.Line.Width = Dim.Fill(1); + this.Line.Height = 1; + this.Line.X = -1; + this.Line.Y = Pos.AnchorEnd(3); + this.Line.Visible = true; + this.Line.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; + this.Line.CanFocus = true; + this.Line.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; + this.Line.Data = "Line"; + this.Line.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; + this.Line.LineRune = new System.Text.Rune('─'); + this.Line.Orientation = Terminal.Gui.ViewBase.Orientation.Horizontal; + this.Add(this.Line); this.btnOk.Width = Dim.Auto(); this.btnOk.Height = Dim.Auto(); this.btnOk.X = 0; diff --git a/src/UI/Windows/DimEditor.Designer.cs b/src/UI/Windows/DimEditor.Designer.cs index 89a25e50..28053d28 100644 --- a/src/UI/Windows/DimEditor.Designer.cs +++ b/src/UI/Windows/DimEditor.Designer.cs @@ -24,9 +24,9 @@ namespace TerminalGuiDesigner.UI.Windows { public partial class DimEditor : Terminal.Gui.Views.Dialog { - private Terminal.Gui.Views.RadioGroup rgDimType; + private Terminal.Gui.Views.OptionSelector rgDimType; - private Terminal.Gui.Views.LineView lineview1; + private Terminal.Gui.Views.Line Line1; private Terminal.Gui.Views.Label lblValue; @@ -47,8 +47,8 @@ private void InitializeComponent() { this.lblOffset = new Terminal.Gui.Views.Label(); this.tbValue = new Terminal.Gui.Views.TextField(); this.lblValue = new Terminal.Gui.Views.Label(); - this.lineview1 = new Terminal.Gui.Views.LineView(); - this.rgDimType = new Terminal.Gui.Views.RadioGroup(); + this.Line1 = new Terminal.Gui.Views.Line(); + this.rgDimType = new Terminal.Gui.Views.OptionSelector(); this.Width = 40; this.Height = 11; this.X = Pos.Center(); @@ -76,19 +76,19 @@ private void InitializeComponent() { "Fill", "Auto"}; this.Add(this.rgDimType); - this.lineview1.Width = 1; - this.lineview1.Height = 3; - this.lineview1.X = 12; - this.lineview1.Y = 1; - this.lineview1.Visible = true; - this.lineview1.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; - this.lineview1.CanFocus = false; - this.lineview1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; - this.lineview1.Data = "lineview1"; - this.lineview1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.lineview1.LineRune = new System.Text.Rune('│'); - this.lineview1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; - this.Add(this.lineview1); + this.Line1.Width = 1; + this.Line1.Height = 3; + this.Line1.X = 12; + this.Line1.Y = 1; + this.Line1.Visible = true; + this.Line1.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; + this.Line1.CanFocus = false; + this.Line1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; + this.Line1.Data = "Line1"; + this.Line1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; + this.Line1.LineRune = new System.Text.Rune('│'); + this.Line1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; + this.Add(this.Line1); this.lblValue.Width = 6; this.lblValue.Height = 1; this.lblValue.X = 14; diff --git a/src/UI/Windows/PosEditor.Designer.cs b/src/UI/Windows/PosEditor.Designer.cs index 1a341fac..512db1ac 100644 --- a/src/UI/Windows/PosEditor.Designer.cs +++ b/src/UI/Windows/PosEditor.Designer.cs @@ -24,9 +24,9 @@ namespace TerminalGuiDesigner.UI.Windows { public partial class PosEditor : Terminal.Gui.Views.Dialog { - private Terminal.Gui.Views.RadioGroup rgPosType; + private Terminal.Gui.Views.OptionSelector rgPosType; - private Terminal.Gui.Views.LineView lineview1; + private Terminal.Gui.Views.Line Line1; private Terminal.Gui.Views.Label lblValue; @@ -38,7 +38,7 @@ public partial class PosEditor : Terminal.Gui.Views.Dialog { private Terminal.Gui.Views.Label lblSide; - private Terminal.Gui.Views.RadioGroup rgSide; + private Terminal.Gui.Views.OptionSelector rgSide; private Terminal.Gui.Views.Label lblOffset; @@ -53,14 +53,14 @@ private void InitializeComponent() { this.btnOk = new Terminal.Gui.Views.Button(); this.tbOffset = new Terminal.Gui.Views.TextField(); this.lblOffset = new Terminal.Gui.Views.Label(); - this.rgSide = new Terminal.Gui.Views.RadioGroup(); + this.rgSide = new Terminal.Gui.Views.OptionSelector(); this.lblSide = new Terminal.Gui.Views.Label(); this.tbRelativeTo = new Terminal.Gui.Views.TextField(); this.lblRelativeTo = new Terminal.Gui.Views.Label(); this.tbValue = new Terminal.Gui.Views.TextField(); this.lblValue = new Terminal.Gui.Views.Label(); - this.lineview1 = new Terminal.Gui.Views.LineView(); - this.rgPosType = new Terminal.Gui.Views.RadioGroup(); + this.Line1 = new Terminal.Gui.Views.Line(); + this.rgPosType = new Terminal.Gui.Views.OptionSelector(); this.Width = 47; this.Height = 16; this.X = Pos.Center(); @@ -89,19 +89,19 @@ private void InitializeComponent() { "Center", "AnchorEnd"}; this.Add(this.rgPosType); - this.lineview1.Width = 1; - this.lineview1.Height = 5; - this.lineview1.X = 14; - this.lineview1.Y = 1; - this.lineview1.Visible = true; - this.lineview1.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; - this.lineview1.CanFocus = false; - this.lineview1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; - this.lineview1.Data = "lineview1"; - this.lineview1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.lineview1.LineRune = new System.Text.Rune('│'); - this.lineview1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; - this.Add(this.lineview1); + this.Line1.Width = 1; + this.Line1.Height = 5; + this.Line1.X = 14; + this.Line1.Y = 1; + this.Line1.Visible = true; + this.Line1.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Fixed; + this.Line1.CanFocus = false; + this.Line1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; + this.Line1.Data = "Line1"; + this.Line1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; + this.Line1.LineRune = new System.Text.Rune('│'); + this.Line1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; + this.Add(this.Line1); this.lblValue.Width = 6; this.lblValue.Height = 1; this.lblValue.X = 22; diff --git a/src/ViewFactory.cs b/src/ViewFactory.cs index 0afd09c6..471b187e 100644 --- a/src/ViewFactory.cs +++ b/src/ViewFactory.cs @@ -216,7 +216,7 @@ public static T Create(int? width = null, int? height = null, string? text = case StatusBar sb: sb.SetShortcuts(new[] { new Shortcut( Key.F1, "F1 - Edit Me", null ) }); break; - case RadioGroup rg: + case OptionSelector rg: rg.RadioLabels = new string[] { "Option 1", "Option 2" }; SetDefaultDimensions( newView, width ?? 10, height ?? 2 ); break; @@ -236,7 +236,7 @@ public static T Create(int? width = null, int? height = null, string? text = case Window: SetDefaultDimensions( newView, width ?? 10, height ?? 5 ); break; - case LineView: + case Line: SetDefaultDimensions( newView, width ?? 8, height ?? 1 ); break; case TreeView: @@ -343,7 +343,7 @@ public static View Create( Type requestedType ) { } t when t.IsAssignableTo( typeof( CheckBox ) ) => Create( ), { } t when t.IsAssignableTo( typeof( TableView ) ) => Create( ), { } t when t.IsAssignableTo( typeof( TabView ) ) => Create( ), - { } t when t.IsAssignableTo( typeof( RadioGroup ) ) => Create( ), + { } t when t.IsAssignableTo( typeof( OptionSelector ) ) => Create( ), { } t when t.IsAssignableTo( typeof( MenuBar ) ) => Create( ), { } t when t.IsAssignableTo( typeof( StatusBar ) ) => Create( ), { } t when t == typeof( TextValidateField ) => Create( ), @@ -355,7 +355,7 @@ public static View Create( Type requestedType ) { } t when t == typeof( TextField ) => Create( ), { } t when t.IsAssignableTo( typeof( GraphView ) ) => Create( ), { } t when t.IsAssignableTo( typeof( ListView ) ) => Create( ), - { } t when t == typeof( LineView ) => Create( ), + { } t when t == typeof( Line ) => Create( ), { } t when t == typeof( TreeView ) => Create( ), { } t when t.IsAssignableTo( typeof( SpinnerView ) ) => Create( ), { } t when t.IsAssignableTo( typeof( FrameView ) ) => Create( ), diff --git a/tests/PropertyTests.cs b/tests/PropertyTests.cs index 3eb43c64..6c79a450 100644 --- a/tests/PropertyTests.cs +++ b/tests/PropertyTests.cs @@ -13,10 +13,10 @@ namespace UnitTests; internal class PropertyTests : Tests { [Test] - public void Changing_LineViewOrientation( ) + public void Changing_LineOrientation( ) { Design v = Get10By10View( ); - using LineView lv = ViewFactory.Create( ); + using Line lv = ViewFactory.Create( ); Design d = new( v.SourceCode, "lv", lv ); v.View.Add( lv ); @@ -28,7 +28,7 @@ public void Changing_LineViewOrientation( ) Assert.That( lv.LineRune, Is.EqualTo( new Rune( '─' ) ) ); } ); - Property? prop = d.GetDesignableProperty( nameof( LineView.Orientation ) ); + Property? prop = d.GetDesignableProperty( nameof( Line.Orientation ) ); Assert.That( prop, Is.Not.Null ); prop?.SetValue( Orientation.Vertical ); @@ -103,7 +103,7 @@ public string PropertyOfType_Pos( ) public void PropertyOfType_Rune( [Values( 'a', 'A', 'f', 'F' )] char runeCharacter ) { FileInfo file = new( $"{nameof( PropertyOfType_Rune )}_{runeCharacter}.cs" ); - using LineView lv = new( ); + using Line lv = new( ); Design d = new( new( file ), "lv", lv ); Property prop = d.GetDesignableProperties( ).Single( static p => p.PropertyInfo.Name.Equals( "LineRune" ) ); diff --git a/tests/RadioGroupTests.cs b/tests/RadioGroupTests.cs index 98376208..ae2ee1e7 100644 --- a/tests/RadioGroupTests.cs +++ b/tests/RadioGroupTests.cs @@ -7,12 +7,12 @@ namespace UnitTests; [TestOf( typeof( CodeToView ) )] [TestOf( typeof( ViewToCode ) )] [Category( "Code Generation" )] -internal class RadioGroupTests : Tests +internal class OptionSelectorTests : Tests { [Test] - public void RoundTrip_PreserveRadioGroups( ) + public void RoundTrip_PreserveOptionSelectors( ) { - var rgIn = RoundTrip( static ( _, _ ) => { }, out _ ); + var rgIn = RoundTrip( static ( _, _ ) => { }, out _ ); Assert.That( rgIn.RadioLabels, Has.Length.EqualTo( 2 ) ); @@ -24,9 +24,9 @@ public void RoundTrip_PreserveRadioGroups( ) } [Test] - public void RoundTrip_PreserveRadioGroups_Custom( ) + public void RoundTrip_PreserveOptionSelectors_Custom( ) { - var rgIn = RoundTrip( static ( _, r ) => { r.RadioLabels = ["Fish", "Cat", "Balloon"]; }, out _ ); + var rgIn = RoundTrip( static ( _, r ) => { r.RadioLabels = ["Fish", "Cat", "Balloon"]; }, out _ ); Assert.That( rgIn.RadioLabels, Has.Length.EqualTo( 3 ) ); @@ -39,9 +39,9 @@ public void RoundTrip_PreserveRadioGroups_Custom( ) } [Test] - public void RoundTrip_PreserveRadioGroups_Empty( ) + public void RoundTrip_PreserveOptionSelectors_Empty( ) { - var rgIn = RoundTrip( static ( _, r ) => { r.RadioLabels = []; }, out _ ); + var rgIn = RoundTrip( static ( _, r ) => { r.RadioLabels = []; }, out _ ); Assert.That( rgIn.RadioLabels, Is.Empty ); } From 8d8ae3b8890028ae028fad17758b0c9b0ed594a7 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 01:45:30 +0000 Subject: [PATCH 002/101] WIP remove modal true and LineRune --- .gitignore | 2 ++ Showcase/Tabs.Designer.cs | 8 +++--- src/Design.cs | 8 +----- src/MenuTracker.cs | 28 +++++++----------- src/UI/Editor.cs | 39 +++++++++++++++----------- src/UI/Windows/ArrayEditor.Designer.cs | 4 +-- src/UI/Windows/BigListBox.cs | 3 +- src/UI/Windows/DimEditor.cs | 1 - src/UI/Windows/GetTextDialog.cs | 1 - src/UI/Windows/PosEditor.cs | 1 - 10 files changed, 42 insertions(+), 53 deletions(-) diff --git a/.gitignore b/.gitignore index dfcfd56f..a96e7a22 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,8 @@ # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs +.claude + # Mono auto generated files mono_crash.* diff --git a/Showcase/Tabs.Designer.cs b/Showcase/Tabs.Designer.cs index d898e59a..e5f23c54 100644 --- a/Showcase/Tabs.Designer.cs +++ b/Showcase/Tabs.Designer.cs @@ -485,9 +485,9 @@ private void InitializeComponent() { ".OfType();\r\n var others = operations\r\n ." + "Except(setProps)\r\n .GroupBy(k => k.Category, ToMenuItem);\r\n\r\n " + "var setPropsItems = setProps.Select(ToMenuItem).ToArray();\r\n bool hasProp" + - "sItems = setPropsItems.Any();\r\n\r\n var all = new List();\r\n\r\n " + + "sItems = setPropsItems.Any();\r\n\r\n var all = new List();\r\n\r\n " + " // only add the set properties category if there are some\r\n if (has" + - "PropsItems)\r\n {\r\n all.Add(new MenuItemv2()\r\n {\r\n " + + "PropsItems)\r\n {\r\n all.Add(new MenuItem()\r\n {\r\n " + " Title = name,\r\n Action = () =>\r\n {\r\n " + " if (selected.Length == 1 || rightClicked != null)\r\n " + " {\r\n this.ShowEditProperties(rightClicked ?? sel" + @@ -499,7 +499,7 @@ private void InitializeComponent() { " in alphabetical order\r\n all.AddRange(g.OrderBy(mi => mi.Title));" + "\r\n }\r\n else\r\n {\r\n // Add categor" + "ies first\r\n all.Insert(\r\n hasPropsItems ? 1 : " + - "0,\r\n new MenuItemv2()\r\n {\r\n " + + "0,\r\n new MenuItem()\r\n {\r\n " + " Title = g.Key,\r\n SubMenu = new Menuv2(g.ToArray(" + "))\r\n });\r\n }\r\n }\r\n\r\n // there\'s noth" + "ing we can do\r\n if (all.Count == 0)\r\n {\r\n return;\r\n " + @@ -514,7 +514,7 @@ private void InitializeComponent() { "t its own menu items!?\r\n menu.MakeVisible(position);\r\n menu.Accept" + "ed += (_, _) =>\r\n {\r\n this.menuOpen = false;\r\n Sele" + "ctionManager.Instance.LockSelection = false;\r\n };\r\n }\r\n\r\n private s" + - "tatic MenuItemv2 ToMenuItem(IOperation operation)\r\n {\r\n return new Men" + + "tatic MenuItem ToMenuItem(IOperation operation)\r\n {\r\n return new Men" + "uItemv2(operation.ToString(), string.Empty, () => Try(() => OperationManager.Ins" + "tance.Do(operation)));\r\n\r\n static void Try(Action action)\r\n {\r\n " + " try\r\n {\r\n // BUG: Thread-safety\r\n " + diff --git a/src/Design.cs b/src/Design.cs index 5d89ba2f..3a217e85 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -658,12 +658,7 @@ private IEnumerable LoadDesignableProperties() yield return this.CreateProperty(nameof(TextView.AllowsReturn)); yield return this.CreateProperty(nameof(TextView.WordWrap)); } - - if (this.View is Toplevel) - { - yield return this.CreateProperty(nameof(Toplevel.Modal)); - } - + // Allow changing the FieldName on anything but root where // such an action would break things badly if (!this.IsRoot) @@ -698,7 +693,6 @@ private IEnumerable LoadDesignableProperties() if (this.View is Line) { - yield return this.CreateProperty(nameof(Line.LineRune)); yield return this.CreateProperty(nameof(Line.Orientation)); } diff --git a/src/MenuTracker.cs b/src/MenuTracker.cs index 6ad44636..acbe1c2a 100644 --- a/src/MenuTracker.cs +++ b/src/MenuTracker.cs @@ -41,10 +41,6 @@ public void Register(MenuBar mb) return; } - mb.MenuAllClosed += this.MenuAllClosed; - mb.MenuOpened += this.MenuOpened; - mb.MenuClosing += this.MenuClosing; - this.bars.Add(mb); } @@ -58,10 +54,6 @@ public void UnregisterMenuBar( MenuBar? mb ) { return; } - - mb.MenuAllClosed -= MenuAllClosed; - mb.MenuOpened -= MenuOpened; - mb.MenuClosing -= MenuClosing; } /// @@ -84,7 +76,7 @@ public void UnregisterMenuBar( MenuBar? mb ) { foreach (var bar in this.bars) { - foreach (var sub in bar.Menus) + foreach (var sub in bar.SubViews.OfType()) { var candidate = this.GetParent(item, sub); @@ -144,7 +136,7 @@ public Dictionary ConvertEmptyMenus( ) Dictionary dictionary = []; foreach (var b in this.bars) { - foreach (var bi in b.Menus) + foreach (var bi in b.SubViews.OfType()) { foreach ( ( MenuBarItem? convertedMenuBarItem, MenuItem? convertedMenuItem ) in this.ConvertEmptyMenus( dictionary, b, bi ) ) { @@ -172,9 +164,9 @@ public Dictionary ConvertEmptyMenus( ) internal static bool ConvertMenuBarItemToRegularItemIfEmpty( MenuBarItem bar, [NotNullWhen( true )] out MenuItem? added ) { added = null; - + /* // bar still has more children so don't convert - if ( bar.Children.Length != 0 ) + if ( bar.SubViews.Length != 0 ) { return false; } @@ -198,28 +190,28 @@ internal static bool ConvertMenuBarItemToRegularItemIfEmpty( MenuBarItem bar, [N Data = bar.Data, Key = bar.Key }; - + */ return true; } /// private Dictionary ConvertEmptyMenus(Dictionary dictionary, MenuBar bar, MenuBarItem mbi) { - foreach (var c in mbi.Children.OfType()) + foreach (var c in mbi.SubViews.OfType()) { this.ConvertEmptyMenus(dictionary,bar, c); if ( ConvertMenuBarItemToRegularItemIfEmpty( c, out MenuItem? added)) { dictionary.TryAdd( c, added ); - + /* bar.CloseMenu(false); - bar.OpenMenu(); + bar.OpenMenu();*/ } } return dictionary; } - + /* private void MenuClosing(object? sender, MenuClosingEventArgs obj) { this.CurrentlyOpenMenuItem = null; @@ -257,5 +249,5 @@ private void MenuAllClosed(object? sender, EventArgs e) } return null; - } + }*/ } diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index dd39c04f..4896b292 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -22,11 +22,11 @@ namespace TerminalGuiDesigner.UI; /// -/// Root that is visible on loading the +/// Root that is visible on loading the /// application. Hooks key and mouse events and mounts as a sub-view whatever file /// the user opens. /// -public class Editor : Toplevel, IErrorReporter +public class Editor : View, IErrorReporter { private KeyMap keyMap; private readonly KeyboardManager keyboardManager; @@ -86,7 +86,9 @@ public Editor() { ErrorReporter = this }; - this.Closing += this.Editor_Closing; + + // TODO: save changes + //this.Closing += this.Editor_Closing; this.BuildRootMenu(); } @@ -204,7 +206,7 @@ public void Run(Options options) } catch (Exception ex) { - MessageBox.ErrorQuery("Error Loading Designer", ex.Message, "Ok"); + MessageBox.ErrorQuery(null, "Error Loading Designer", ex.Message, "Ok"); Application.Shutdown(); return; } @@ -342,9 +344,9 @@ protected override void OnDrawComplete(DrawContext? context) /// /// Draws title screen when no view is currently open /// - protected override bool OnDrawingContent() + protected override bool OnDrawingContent(DrawContext? context) { - var r = base.OnDrawingContent(); + var r = base.OnDrawingContent(context); if (viewBeingEdited != null) { @@ -902,7 +904,7 @@ private void ChangeKeybindings() } - private void Editor_Closing(object? sender, ToplevelClosingEventArgs obj) + private void Editor_Closing(object? sender, CancelEventArgs obj) { if (this.viewBeingEdited == null) { @@ -955,12 +957,12 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) var setPropsItems = setProps.Select(ToMenuItem).ToArray(); bool hasPropsItems = setPropsItems.Any(); - var all = new List(); + var all = new List(); // only add the set properties category if there are some if (hasPropsItems) { - all.Add(new MenuItemv2() + all.Add(new MenuItem() { Title = name, Action = () => @@ -970,7 +972,11 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) this.ShowEditProperties(rightClicked ?? selected[0]); } }, - SubMenu = new Menuv2(setPropsItems) + SubMenu = new Menu() + { + // TODO: get the menu items back + // Subitems = setPropsItems + } }); } @@ -988,10 +994,10 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) // Add categories first all.Insert( hasPropsItems ? 1 : 0, - new MenuItemv2() + new MenuItem() { Title = g.Key, - SubMenu = new Menuv2(g.ToArray()) + SubMenu = new Menu(g.ToArray()) }); } } @@ -1033,9 +1039,9 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) }; } - private static MenuItemv2 ToMenuItem(IOperation operation) + private static MenuItem ToMenuItem(IOperation operation) { - return new MenuItemv2(operation.ToString(), string.Empty, () => Try(() => OperationManager.Instance.Do(operation))); + return new MenuItem(operation.ToString(), string.Empty, () => Try(() => OperationManager.Instance.Do(operation))); static void Try(Action action) { @@ -1372,7 +1378,7 @@ private void New() private static Type[] GetSupportedRootViews() { - return new Type[] { typeof(Window), typeof(Dialog), typeof(View), typeof(Toplevel) }; + return new Type[] { typeof(Window), typeof(Dialog), typeof(View) }; } private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) @@ -1395,7 +1401,8 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) // Validate the namespace if (string.IsNullOrWhiteSpace(ns) || ns.Contains(' ') || char.IsDigit(ns.First())) { - MessageBox.ErrorQuery("Invalid Namespace", "Namespace must not contain spaces, be empty or begin with a number", "Ok"); + // TODO: app should be null? + MessageBox.ErrorQuery(null, "Invalid Namespace", "Namespace must not contain spaces, be empty or begin with a number", "Ok"); return; } diff --git a/src/UI/Windows/ArrayEditor.Designer.cs b/src/UI/Windows/ArrayEditor.Designer.cs index 0cbb4d2a..d5a9fb98 100644 --- a/src/UI/Windows/ArrayEditor.Designer.cs +++ b/src/UI/Windows/ArrayEditor.Designer.cs @@ -63,7 +63,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "Array Editor"; this.frameView.Width = Dim.Fill(0); @@ -169,8 +168,7 @@ private void InitializeComponent() { this.Line.CanFocus = true; this.Line.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.Line.Data = "Line"; - this.Line.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.Line.LineRune = new System.Text.Rune('─'); + this.Line.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Line.Orientation = Terminal.Gui.ViewBase.Orientation.Horizontal; this.Add(this.Line); this.btnOk.Width = Dim.Auto(); diff --git a/src/UI/Windows/BigListBox.cs b/src/UI/Windows/BigListBox.cs index 37f1dbf7..cc636d54 100644 --- a/src/UI/Windows/BigListBox.cs +++ b/src/UI/Windows/BigListBox.cs @@ -80,8 +80,7 @@ public BigListBox(string prompt, // By using Dim.Fill(), it will automatically resize without manual intervention Width = Dim.Fill(), - Height = Dim.Fill(), - Modal = true, + Height = Dim.Fill() }; this.listView = new ListView() diff --git a/src/UI/Windows/DimEditor.cs b/src/UI/Windows/DimEditor.cs index 8a625173..3052ab6b 100644 --- a/src/UI/Windows/DimEditor.cs +++ b/src/UI/Windows/DimEditor.cs @@ -56,7 +56,6 @@ public DimEditor(Design design, Dim oldValue) { btnOk.Accepting += BtnOk_Clicked; btnCancel.Accepting += BtnCancel_Clicked; Cancelled = true; - Modal = true; rgDimType.KeyDown += RgDimType_KeyPress; if(oldValue.GetDimType(out var type,out var value, out var offset)) diff --git a/src/UI/Windows/GetTextDialog.cs b/src/UI/Windows/GetTextDialog.cs index 1174f1f3..478662b0 100644 --- a/src/UI/Windows/GetTextDialog.cs +++ b/src/UI/Windows/GetTextDialog.cs @@ -29,7 +29,6 @@ public GetTextDialog(DialogArgs args, string? initialValue) Title = this.args.WindowTitle, X = 0, Y = 0, - Modal = true, }; var description = new Label diff --git a/src/UI/Windows/PosEditor.cs b/src/UI/Windows/PosEditor.cs index 9de07520..a05f1009 100644 --- a/src/UI/Windows/PosEditor.cs +++ b/src/UI/Windows/PosEditor.cs @@ -61,7 +61,6 @@ public PosEditor(Design design, Pos oldValue) { btnOk.Accepting += BtnOk_Clicked; btnCancel.Accepting += BtnCancel_Clicked; Cancelled = true; - Modal = true; _siblings = design.GetSiblings().ToDictionary( d=>d.FieldName, From 387d1e36c60a36f58b31657c12c1c120621f3c44 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 02:08:02 +0000 Subject: [PATCH 003/101] WIP deal with more breaking changes --- src/Design.cs | 12 ++++----- src/MenuBarExtensions.cs | 8 +++--- .../MenuOperations/AddMenuOperation.cs | 2 +- .../MoveMenuItemLeftOperation.cs | 4 +-- .../MenuOperations/MoveMenuOperation.cs | 2 +- .../MenuOperations/RemoveMenuItemOperation.cs | 6 ++--- .../MenuOperations/RemoveMenuOperation.cs | 2 +- .../MenuOperations/RenameMenuOperation.cs | 2 +- src/ToCode/MenuBarItemsToCode.cs | 12 ++++++--- src/ToCode/Property.cs | 2 -- src/UI/KeyboardManager.cs | 5 ++-- src/UI/Windows/BigListBox.cs | 4 +-- src/UI/Windows/ChoicesDialog.Designer.cs | 1 - src/UI/Windows/ListViewExtensions.cs | 27 ------------------- src/ViewExtensions.cs | 7 +---- src/ViewFactory.cs | 14 +--------- 16 files changed, 33 insertions(+), 77 deletions(-) delete mode 100644 src/UI/Windows/ListViewExtensions.cs diff --git a/src/Design.cs b/src/Design.cs index 3a217e85..491de39b 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -41,7 +41,6 @@ public class Design typeof(FrameView), typeof(TabView), typeof(Window), - typeof(Toplevel), typeof(GraphView), typeof(HexView), typeof(Line), @@ -211,20 +210,20 @@ public Design CreateSubControlDesign(string name, View subView) if (subView is TextView txt) { // prevent control from responding to events - txt.MouseClick += (s, e) => this.SuppressNativeClickEvents(s, e); + txt.MouseEvent += (s, e) => this.SuppressNativeClickEvents(s, e); } if (subView is TextField tf) { // prevent control from responding to events - tf.MouseClick += (s,e)=>this.SuppressNativeClickEvents(s,e); + tf.MouseEvent += (s,e)=>this.SuppressNativeClickEvents(s,e); } if (subView.GetType().IsGenericType(typeof(Slider<>))) { // TODO: Does not seem to work subView.MouseEvent += (s, e) => SuppressNativeClickEvents(s, e,true); - subView.MouseClick += (s, e) => SuppressNativeClickEvents(s,e, true); + subView.MouseEvent += (s, e) => SuppressNativeClickEvents(s,e, true); } if (subView is TreeView tree) @@ -252,7 +251,6 @@ public Design CreateSubControlDesign(string name, View subView) // in non designed subcomponents e.g. the bar of a true color picker. foreach (var v in subView.GetAllNonDesignableSubviews()) { - v.MouseClick += (s,e)=>this.SuppressNativeClickEvents(s,e,true); v.MouseEvent += (s, e) => this.SuppressNativeClickEvents(s, e, true); } @@ -588,7 +586,7 @@ private void RegisterCheckboxDesignTimeChanges(CheckBox cb) // prevent space toggling the checkbox // (gives better typing experience e.g. "my lovely checkbox") cb.KeyBindings.Remove(Key.Space); - cb.MouseClick += (s, e) => + cb.MouseEvent += (s, e) => { if (e.Flags.HasFlag(MouseFlags.Button1Clicked)) { @@ -794,7 +792,7 @@ private IEnumerable LoadDesignableProperties() if (this.View is OptionSelector) { - yield return this.CreateProperty(nameof(OptionSelector.RadioLabels)); + yield return this.CreateProperty(nameof(OptionSelector.Labels)); } if (viewType.IsGenericType(typeof(NumericUpDown<>))) diff --git a/src/MenuBarExtensions.cs b/src/MenuBarExtensions.cs index d3c8ef49..1dfa5558 100644 --- a/src/MenuBarExtensions.cs +++ b/src/MenuBarExtensions.cs @@ -20,12 +20,12 @@ public static class MenuBarExtensions { int selected = menuBar.GetNonNullNonPublicFieldValue( "selected" ); - if (selected < 0 || selected >= menuBar.Menus.Length) + if (selected < 0 || selected >= menuBar.SubViews.OfType().Count()) { return null; } - return menuBar.Menus[selected]; + return menuBar.SubViews.OfType().ElementAt(selected); } /// @@ -41,7 +41,7 @@ public static class MenuBarExtensions const int initialWhitespace = 1; const int afterEachItemWhitespace = 2; - if (menuBar.Menus.Length == 0) + if (menuBar.SubViews.OfType().Count() == 0) { return null; } @@ -58,7 +58,7 @@ public static class MenuBarExtensions int distance = initialWhitespace; Dictionary menuXLocations = new(); - foreach (var mb in menuBar.Menus) + foreach (var mb in menuBar.SubViews.OfType()) { menuXLocations.Add(distance, mb); distance += mb.Title.GetColumns() + afterEachItemWhitespace; diff --git a/src/Operations/MenuOperations/AddMenuOperation.cs b/src/Operations/MenuOperations/AddMenuOperation.cs index 63c0e78e..9a9cd600 100644 --- a/src/Operations/MenuOperations/AddMenuOperation.cs +++ b/src/Operations/MenuOperations/AddMenuOperation.cs @@ -19,7 +19,7 @@ public class AddMenuOperation : AddOperation /// Thrown if the is not wrapping a . public AddMenuOperation(Design design, string? name) : base( - (v) => v.Menus, + (v) => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, (s) => s.Title.ToString() ?? "blank menu", (v, n) => new(n, new MenuItem[] { new() { Title = ViewFactory.DefaultMenuItemText } }), diff --git a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs index eedc9240..bb276648 100644 --- a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs @@ -26,7 +26,7 @@ public MoveMenuItemLeftOperation(MenuItem toMove) : base(toMove) { // command is already invalid or user is trying to move a menu item that is not in a sub-menu - if (this.IsImpossible || this.Bar == null || this.Bar.Menus.Any(m => m.Children.Contains(toMove))) + if (this.IsImpossible || this.Bar == null || this.Bar.SubViews.OfType().Any(m => m.SubViews.Contains(toMove))) { this.IsImpossible = true; return; @@ -34,7 +34,7 @@ public MoveMenuItemLeftOperation(MenuItem toMove) if (this.Parent != null) { - this.pulledFromIndex = Array.IndexOf(this.Parent.Children, this.OperateOn); + this.pulledFromIndex = Array.IndexOf(this.Parent.SubViews.OfType().ToArray(), this.OperateOn); } } diff --git a/src/Operations/MenuOperations/MoveMenuOperation.cs b/src/Operations/MenuOperations/MoveMenuOperation.cs index 6e918151..74062177 100644 --- a/src/Operations/MenuOperations/MoveMenuOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuOperation.cs @@ -20,7 +20,7 @@ public class MoveMenuOperation : MoveOperation /// Negative to move menu left, positive to move menu right. public MoveMenuOperation(Design design, MenuBarItem toMove, int adjustment) : base( - v => v.Menus, + v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", design, diff --git a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs index 15958a8a..6a3fff24 100644 --- a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs +++ b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs @@ -96,7 +96,7 @@ .. Parent.Children[ removedAtIdx .. ] // side effect of the removal then put them back if (this.prunedEmptyTopLevelMenus != null && this.Bar != null) { - var l = this.Bar.Menus.ToList(); + var l = this.Bar.SubViews.OfType().ToList(); // for each index they used to be at foreach (var kvp in this.prunedEmptyTopLevelMenus.OrderBy(k => k)) @@ -126,7 +126,7 @@ protected override bool DoImpl() { return false; } - + /* this.removedAtIdx = Math.Max( 0, Array.IndexOf( Parent.Children, OperateOn ) ); this.Parent.Children = [ @@ -160,7 +160,7 @@ .. Parent.Children[ ( removedAtIdx + 1 ).. ] this.barRemovedFrom = this.Bar.SuperView; this.barRemovedFrom.Remove(this.Bar); } - + */ return true; } } \ No newline at end of file diff --git a/src/Operations/MenuOperations/RemoveMenuOperation.cs b/src/Operations/MenuOperations/RemoveMenuOperation.cs index 8ebe9dda..78de6e4a 100644 --- a/src/Operations/MenuOperations/RemoveMenuOperation.cs +++ b/src/Operations/MenuOperations/RemoveMenuOperation.cs @@ -19,7 +19,7 @@ public class RemoveMenuOperation : RemoveOperation /// Thrown if does not wrap a . public RemoveMenuOperation(Design design, MenuBarItem toRemove) : base( - v => v.Menus, + v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", design, diff --git a/src/Operations/MenuOperations/RenameMenuOperation.cs b/src/Operations/MenuOperations/RenameMenuOperation.cs index 62177d33..bea0e9af 100644 --- a/src/Operations/MenuOperations/RenameMenuOperation.cs +++ b/src/Operations/MenuOperations/RenameMenuOperation.cs @@ -17,7 +17,7 @@ public class RenameMenuOperation : RenameOperation /// The new name to use. public RenameMenuOperation(Design design, MenuBarItem toRename, string? newName) : base( - v => v.Menus, + v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", (v, s) => v.Title = s, diff --git a/src/ToCode/MenuBarItemsToCode.cs b/src/ToCode/MenuBarItemsToCode.cs index 5c96504d..f9ccce02 100644 --- a/src/ToCode/MenuBarItemsToCode.cs +++ b/src/ToCode/MenuBarItemsToCode.cs @@ -50,6 +50,7 @@ public void ToCode(CodeDomArgs args) mb.Menus = new []{m1}; */ + /* // TODO: Let user name these List menus = new(); foreach (var child in this.menuBar.Menus) @@ -66,8 +67,9 @@ public void ToCode(CodeDomArgs args) menus.Select(c => new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), c)) .ToArray())); + */ } - + /* private void ToCode(CodeDomArgs args, MenuBarItem child, out string fieldName) { fieldName = this.GetUniqueFieldName(args, child); @@ -104,7 +106,7 @@ private void ToCode(CodeDomArgs args, MenuBarItem child, out string fieldName) { this.AddPropertyAssignment( args, - $"this.{subFieldName}.{nameof(MenuItem.ShortcutKey)}", + $"this.{subFieldName}.{nameof(MenuItem.Key)}", new CodeCastExpression( new CodeTypeReference(typeof(KeyCode)), new CodePrimitiveExpression((uint)sub.ShortcutKey))); @@ -114,11 +116,13 @@ private void ToCode(CodeDomArgs args, MenuBarItem child, out string fieldName) } } + // TODO: This is not the way to do it in v2 + // we have created fields and constructor calls for our menu // now set the menu to an array of all those fields this.AddPropertyAssignment( args, - $"this.{fieldName}.{nameof(MenuBarItem.Children)}", + $"this.{fieldName}.{"Children"}", new CodeArrayCreateExpression( typeof(MenuItem), children.Select(c => @@ -130,7 +134,7 @@ private void ToCode(CodeDomArgs args, MenuBarItem child, out string fieldName) (CodeExpression)new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), c)) .ToArray())); } - + */ private string GetUniqueFieldName(CodeDomArgs args, MenuItem item) { // if user has an explicit name they have set diff --git a/src/ToCode/Property.cs b/src/ToCode/Property.cs index 8ec21f60..e45a040b 100644 --- a/src/ToCode/Property.cs +++ b/src/ToCode/Property.cs @@ -110,13 +110,11 @@ public virtual void SetValue(object? value) case Orientation.Horizontal: v.Width = v.Height; v.Height = 1; - v.LineRune = Glyphs.HLine; break; case Orientation.Vertical: v.Height = v.Width; v.Width = 1; - v.LineRune = Glyphs.VLine; break; default: throw new ArgumentException($"Unknown Orientation {newOrientation}"); diff --git a/src/UI/KeyboardManager.cs b/src/UI/KeyboardManager.cs index 761b2a89..48e9be49 100644 --- a/src/UI/KeyboardManager.cs +++ b/src/UI/KeyboardManager.cs @@ -114,7 +114,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.SetShortcut) { - menuItem.ShortcutKey = Modals.GetShortcut().KeyCode; + menuItem.Key = Modals.GetShortcut().KeyCode; focusedView.SetNeedsDraw(); return false; @@ -167,11 +167,12 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (remove.PrunedTopLevelMenu) { // if we deleted the last menu item + /* if (remove.Bar?.Menus.Length == 0) { remove.Bar.CloseMenu(false); return true; - } + }*/ // convert keystroke to left, // so we move to the next menu diff --git a/src/UI/Windows/BigListBox.cs b/src/UI/Windows/BigListBox.cs index cc636d54..f332f73e 100644 --- a/src/UI/Windows/BigListBox.cs +++ b/src/UI/Windows/BigListBox.cs @@ -93,7 +93,7 @@ public BigListBox(string prompt, }; listView.SetSource(new ObservableCollection(ErrorStringArray)); - this.listView.MouseClick += this.ListView_MouseClick; + this.listView.MouseEvent += this.ListView_MouseClick; this.collection = this.BuildList(this.GetInitialSource()).ToList(); @@ -206,7 +206,7 @@ public bool ShowDialog() private void Accept() { - var selected = this.listView.SelectedItem; + var selected = this.listView.SelectedItem ?? -1; if (selected < 0 || selected >= this.collection.Count) { return; diff --git a/src/UI/Windows/ChoicesDialog.Designer.cs b/src/UI/Windows/ChoicesDialog.Designer.cs index 56fb66ff..89f8d91b 100644 --- a/src/UI/Windows/ChoicesDialog.Designer.cs +++ b/src/UI/Windows/ChoicesDialog.Designer.cs @@ -52,7 +52,6 @@ private void InitializeComponent() { | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = ""; this.label1.Width = Dim.Fill(0); diff --git a/src/UI/Windows/ListViewExtensions.cs b/src/UI/Windows/ListViewExtensions.cs deleted file mode 100644 index 96ec8324..00000000 --- a/src/UI/Windows/ListViewExtensions.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Terminal.Gui; -using Terminal.Gui.Views; - -namespace TerminalGuiDesigner.UI.Windows; - -/// -/// Extension methods for the class. -/// -public static class ListViewExtensions -{ - /// - /// Adjusts so that is - /// within the view bounds (scrolls to selected item if not in current view area). - /// - /// The to scroll. - public static void EnsureSelectedItemVisible(this ListView list) - { - if (list.SelectedItem < list.TopItem) - { - list.TopItem = list.SelectedItem; - } - else if (list.Frame.Height > 0 && list.SelectedItem >= list.TopItem + list.Frame.Height) - { - list.TopItem = Math.Max(list.SelectedItem - list.Frame.Height + 2, 0); - } - } -} diff --git a/src/ViewExtensions.cs b/src/ViewExtensions.cs index 29510db0..987f7439 100644 --- a/src/ViewExtensions.cs +++ b/src/ViewExtensions.cs @@ -15,7 +15,7 @@ public static class ViewExtensions { public static View? FindDeepestView(Point screenPoint) { - return View.GetViewsAtLocation(Application.Top,screenPoint).LastOrDefault(v=> v!= null); + return View.GetViewsAtLocation(Application.Instance.TopRunnableView, screenPoint).LastOrDefault(v=> v!= null); } /// /// Returns the sub-views of skipping out any @@ -219,11 +219,6 @@ v is Window || /// True if no visible border and . public static bool IsBorderlessContainerView(this View v) { - if (v is Toplevel) - { - return false; - } - if (v is TabView tabView) { return !tabView.Style.ShowBorder || tabView.Style.TabsOnBottom; diff --git a/src/ViewFactory.cs b/src/ViewFactory.cs index 471b187e..afac4d69 100644 --- a/src/ViewFactory.cs +++ b/src/ViewFactory.cs @@ -33,7 +33,6 @@ public static class ViewFactory internal static readonly Type[] KnownUnsupportedTypes = [ - typeof( Toplevel ), typeof( Dialog ), typeof( FileDialog ), typeof( SaveDialog ), @@ -42,9 +41,6 @@ public static class ViewFactory // BUG These seem to cause stack overflows in CreateSubControlDesigns (see TestAddView_RoundTrip) typeof( Wizard ), typeof( WizardStep ), - - // Ignore menu bar v2 for now - typeof(MenuBarv2), // This is unstable when added directly as a view see https://github.com/gui-cs/Terminal.Gui/issues/3664 typeof(Shortcut), @@ -52,10 +48,8 @@ public static class ViewFactory typeof(Tab), typeof(CharMap), typeof(LegendAnnotation), - typeof(Menuv2), typeof(ScrollBar), typeof(ScrollSlider), - typeof(TileView), // Terminal.Gui combo boxes do not really work properly typeof(ComboBox), @@ -176,8 +170,6 @@ public static T Create(int? width = null, int? height = null, string? text = break; case Line: case Slider: - case TileView: - SetDefaultDimensions( newView, width ?? 4, height ?? 1 ); break; case TableView tv: var dt = new DataTable( ); @@ -217,7 +209,7 @@ public static T Create(int? width = null, int? height = null, string? text = sb.SetShortcuts(new[] { new Shortcut( Key.F1, "F1 - Edit Me", null ) }); break; case OptionSelector rg: - rg.RadioLabels = new string[] { "Option 1", "Option 2" }; + rg.lab = new string[] { "Option 1", "Option 2" }; SetDefaultDimensions( newView, width ?? 10, height ?? 2 ); break; case GraphView gv: @@ -236,9 +228,6 @@ public static T Create(int? width = null, int? height = null, string? text = case Window: SetDefaultDimensions( newView, width ?? 10, height ?? 5 ); break; - case Line: - SetDefaultDimensions( newView, width ?? 8, height ?? 1 ); - break; case TreeView: SetDefaultDimensions( newView, width ?? 16, height ?? 5 ); break; @@ -339,7 +328,6 @@ public static View Create( Type requestedType ) { } t when t == typeof(Label) => Create -public class Editor : View, IErrorReporter +public class Editor : Runnable, IErrorReporter { private KeyMap keyMap; private readonly KeyboardManager keyboardManager; diff --git a/src/UI/Windows/ArrayEditor.cs b/src/UI/Windows/ArrayEditor.cs index ab7aa885..081ba0ec 100644 --- a/src/UI/Windows/ArrayEditor.cs +++ b/src/UI/Windows/ArrayEditor.cs @@ -77,7 +77,7 @@ public ArrayEditor(Design design, Type elementType, IList oldValue) { private void BtnMoveUp_Clicked(object sender, CommandEventArgs e) { // Moving up means reducing the index by 1 - var idx = lvElements.SelectedItem; + var idx = lvElements.SelectedItem ?? -1; if (idx >= 1 && idx < ResultAsList.Count) { @@ -97,7 +97,7 @@ private void BtnMoveUp_Clicked(object sender, CommandEventArgs e) private void BtnMoveDown_Clicked(object sender, CommandEventArgs e) { // Moving up means increasing the index by 1 - var idx = lvElements.SelectedItem; + var idx = lvElements.SelectedItem ?? -1; if (idx >= 0 && idx < ResultAsList.Count-1) { @@ -125,7 +125,7 @@ private void LvElements_KeyDown(object sender, Key e) private void DeleteSelectedItem() { - var idx = lvElements.SelectedItem; + var idx = lvElements.SelectedItem??-1; if (idx >= 0 && idx < ResultAsList.Count) { @@ -151,7 +151,7 @@ private void BtnAddElement_Clicked(object sender, CommandEventArgs e) } private void BtnEdit_Clicked(object sender, CommandEventArgs e) { - var idx = lvElements.SelectedItem; + var idx = lvElements.SelectedItem ?? -1; if (idx >= 0 && idx < ResultAsList.Count) { diff --git a/src/UI/Windows/DimEditor.Designer.cs b/src/UI/Windows/DimEditor.Designer.cs index 28053d28..3fb51dfc 100644 --- a/src/UI/Windows/DimEditor.Designer.cs +++ b/src/UI/Windows/DimEditor.Designer.cs @@ -57,7 +57,6 @@ private void InitializeComponent() { this.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Movable; this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = ""; this.rgDimType.Width = 11; @@ -70,7 +69,7 @@ private void InitializeComponent() { this.rgDimType.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.rgDimType.Data = "rgDimType"; this.rgDimType.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.rgDimType.RadioLabels = new string[] { + this.rgDimType.Labels = new string[] { "Absolute", "Percent", "Fill", @@ -86,7 +85,6 @@ private void InitializeComponent() { this.Line1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.Line1.Data = "Line1"; this.Line1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.Line1.LineRune = new System.Text.Rune('│'); this.Line1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; this.Add(this.Line1); this.lblValue.Width = 6; diff --git a/src/UI/Windows/DimEditor.cs b/src/UI/Windows/DimEditor.cs index 3052ab6b..1309d0db 100644 --- a/src/UI/Windows/DimEditor.cs +++ b/src/UI/Windows/DimEditor.cs @@ -63,16 +63,16 @@ public DimEditor(Design design, Dim oldValue) { switch(type) { case DimType.Absolute: - rgDimType.SelectedItem = 0; + rgDimType.Value = 0; break; case DimType.Percent: - rgDimType.SelectedItem = 1; + rgDimType.Value = 1; break; case DimType.Fill: - rgDimType.SelectedItem = 2; + rgDimType.Value = 2; break; case DimType.Auto: - rgDimType.SelectedItem = 3; + rgDimType.Value = 3; break; } @@ -82,7 +82,7 @@ public DimEditor(Design design, Dim oldValue) { SetupForCurrentDimType(); - rgDimType.SelectedItemChanged += DdType_SelectedItemChanged; + rgDimType.ValueChanged += DdType_SelectedItemChanged; } private void RgDimType_KeyPress(object sender, Key obj) @@ -96,13 +96,13 @@ private void RgDimType_KeyPress(object sender, Key obj) } } - private void DdType_SelectedItemChanged(object sender, SelectedItemChangedArgs obj) + private void DdType_SelectedItemChanged(object sender, EventArgs e) { SetupForCurrentDimType(); } private DimType GetDimType() { - return Enum.Parse(rgDimType.RadioLabels[rgDimType.SelectedItem].ToString()); + return Enum.Parse(rgDimType.Labels[rgDimType.Value??0].ToString()); } private void SetupForCurrentDimType() { diff --git a/src/UI/Windows/EditDialog.cs b/src/UI/Windows/EditDialog.cs index a03ed09d..b509599b 100644 --- a/src/UI/Windows/EditDialog.cs +++ b/src/UI/Windows/EditDialog.cs @@ -109,11 +109,11 @@ internal static bool SetPropertyToNewValue(Design design, Property p, object? ol private void SetProperty(bool setNull) { - if (this.list.SelectedItem != -1) + if (this.list.SelectedItem.HasValue) { try { - var p = this.collection[this.list.SelectedItem]; + var p = this.collection[this.list.SelectedItem.Value]; var oldValue = p.GetValue(); if (setNull) diff --git a/src/UI/Windows/KeyBindingsUI.Designer.cs b/src/UI/Windows/KeyBindingsUI.Designer.cs index 17bcf452..6e56ca5a 100644 --- a/src/UI/Windows/KeyBindingsUI.Designer.cs +++ b/src/UI/Windows/KeyBindingsUI.Designer.cs @@ -48,7 +48,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "Keybindings"; this.tableView.Width = Dim.Fill(0); diff --git a/src/UI/Windows/LoadingDialog.Designer.cs b/src/UI/Windows/LoadingDialog.Designer.cs index 2a1f7850..6375e126 100644 --- a/src/UI/Windows/LoadingDialog.Designer.cs +++ b/src/UI/Windows/LoadingDialog.Designer.cs @@ -36,7 +36,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "Loading..."; this.lblLoading.Width = 36; diff --git a/src/UI/Windows/PointEditor.Designer.cs b/src/UI/Windows/PointEditor.Designer.cs index 869af219..4f06e80f 100644 --- a/src/UI/Windows/PointEditor.Designer.cs +++ b/src/UI/Windows/PointEditor.Designer.cs @@ -51,7 +51,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "Point Designer"; this.lblX.Width = 2; diff --git a/src/UI/Windows/PointEditor.cs b/src/UI/Windows/PointEditor.cs index 4cf86fe5..33fc0d36 100644 --- a/src/UI/Windows/PointEditor.cs +++ b/src/UI/Windows/PointEditor.cs @@ -77,12 +77,12 @@ private void Ok(object sender, CommandEventArgs e) } else { - MessageBox.ErrorQuery(20,5,"Could no parse",$"Could not parse '{tbY.Text}'","Ok"); + MessageBox.ErrorQuery(null, 20,5,"Could no parse",$"Could not parse '{tbY.Text}'","Ok"); } } else { - MessageBox.ErrorQuery(20,5,"Could no parse",$"Could not parse '{tbX.Text}'","Ok"); + MessageBox.ErrorQuery(null,20,5,"Could no parse",$"Could not parse '{tbX.Text}'","Ok"); } } } diff --git a/src/UI/Windows/PosEditor.Designer.cs b/src/UI/Windows/PosEditor.Designer.cs index 512db1ac..1af59271 100644 --- a/src/UI/Windows/PosEditor.Designer.cs +++ b/src/UI/Windows/PosEditor.Designer.cs @@ -69,7 +69,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = ""; this.rgPosType.Width = 12; @@ -82,7 +81,7 @@ private void InitializeComponent() { this.rgPosType.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.rgPosType.Data = "rgPosType"; this.rgPosType.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.rgPosType.RadioLabels = new string[] { + this.rgPosType.Labels = new string[] { "Absolute", "Percent", "Relative", @@ -99,7 +98,6 @@ private void InitializeComponent() { this.Line1.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.Line1.Data = "Line1"; this.Line1.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.Line1.LineRune = new System.Text.Rune('│'); this.Line1.Orientation = Terminal.Gui.ViewBase.Orientation.Vertical; this.Add(this.Line1); this.lblValue.Width = 6; @@ -174,7 +172,7 @@ private void InitializeComponent() { this.rgSide.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.None; this.rgSide.Data = "rgSide"; this.rgSide.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; - this.rgSide.RadioLabels = new string[] { + this.rgSide.Labels = new string[] { "Left", "Top", "Right", diff --git a/src/UI/Windows/PosEditor.cs b/src/UI/Windows/PosEditor.cs index a05f1009..374e0d0e 100644 --- a/src/UI/Windows/PosEditor.cs +++ b/src/UI/Windows/PosEditor.cs @@ -78,22 +78,22 @@ public PosEditor(Design design, Pos oldValue) { switch(type) { case PosType.Absolute: - rgPosType.SelectedItem = 0; + rgPosType.Value = 0; break; case PosType.Percent: - rgPosType.SelectedItem = 1; + rgPosType.Value = 1; break; case PosType.Relative: - rgPosType.SelectedItem = 2; + rgPosType.Value = 2; if(relativeTo != null) tbRelativeTo.Text = relativeTo.FieldName; - rgSide.SelectedItem = (int)side; + rgSide.Value = (int)side; break; case PosType.Center: - rgPosType.SelectedItem = 3; + rgPosType.Value = 3; break; case PosType.AnchorEnd: - rgPosType.SelectedItem = 4; + rgPosType.Value = 4; break; } @@ -103,7 +103,7 @@ public PosEditor(Design design, Pos oldValue) { SetupForCurrentPosType(); - rgPosType.SelectedItemChanged += DdType_SelectedItemChanged; + rgPosType.ValueChanged += DdType_SelectedItemChanged; } @@ -118,7 +118,7 @@ private void RgPosType_KeyPress(object sender, Key key) } } - private void DdType_SelectedItemChanged(object sender, SelectedItemChangedArgs obj) + private void DdType_SelectedItemChanged(object sender, EventArgs e) { SetupForCurrentPosType(); } @@ -253,13 +253,13 @@ private bool BuildPos(out Pos result) private PosType GetPosType() { - return Enum.Parse(rgPosType.RadioLabels[rgPosType.SelectedItem].ToString()); + return Enum.Parse(rgPosType.Labels[rgPosType.Value ?? 0].ToString()); } private Side? GetSide() { - return rgSide.SelectedItem == -1 ? null : (Side)rgSide.SelectedItem; + return rgSide.Value == null ? null : (Side)rgSide.Value; } private bool GetOffset(out int offset) diff --git a/src/UI/Windows/SizeEditor.Designer.cs b/src/UI/Windows/SizeEditor.Designer.cs index 6b504626..55abbaaa 100644 --- a/src/UI/Windows/SizeEditor.Designer.cs +++ b/src/UI/Windows/SizeEditor.Designer.cs @@ -51,7 +51,6 @@ private void InitializeComponent() { this.Arrangement = (Terminal.Gui.ViewBase.ViewArrangement.Movable | Terminal.Gui.ViewBase.ViewArrangement.Overlapped); this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "Size"; this.label1.Width = Dim.Auto(); diff --git a/src/UI/Windows/SizeEditor.cs b/src/UI/Windows/SizeEditor.cs index ac574cec..d7e53e30 100644 --- a/src/UI/Windows/SizeEditor.cs +++ b/src/UI/Windows/SizeEditor.cs @@ -52,7 +52,7 @@ public SizeEditor(Size s) } catch (Exception ex) { - MessageBox.ErrorQuery("Bad Value", ex.Message); + MessageBox.ErrorQuery(null, "Bad Value", ex.Message); return; } diff --git a/src/UI/Windows/SliderOptionEditor.Designer.cs b/src/UI/Windows/SliderOptionEditor.Designer.cs index be09432f..ce54da24 100644 --- a/src/UI/Windows/SliderOptionEditor.Designer.cs +++ b/src/UI/Windows/SliderOptionEditor.Designer.cs @@ -63,7 +63,6 @@ private void InitializeComponent() { this.Arrangement = Terminal.Gui.ViewBase.ViewArrangement.Movable; this.CanFocus = true; this.ShadowStyle = Terminal.Gui.ViewBase.ShadowStyle.Transparent; - this.Modal = true; this.TextAlignment = Terminal.Gui.ViewBase.Alignment.Start; this.Title = "OptionEditor"; this.label.Width = Dim.Auto(); diff --git a/src/ViewFactory.cs b/src/ViewFactory.cs index afac4d69..40c8b040 100644 --- a/src/ViewFactory.cs +++ b/src/ViewFactory.cs @@ -209,7 +209,7 @@ public static T Create(int? width = null, int? height = null, string? text = sb.SetShortcuts(new[] { new Shortcut( Key.F1, "F1 - Edit Me", null ) }); break; case OptionSelector rg: - rg.lab = new string[] { "Option 1", "Option 2" }; + rg.Labels = new string[] { "Option 1", "Option 2" }; SetDefaultDimensions( newView, width ?? 10, height ?? 2 ); break; case GraphView gv: From c6fb1c5b393307226a635ece8c49a245ec480d57 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 02:40:24 +0000 Subject: [PATCH 005/101] Can boot main app --- src/MenuTracker.cs | 3 ++- .../MenuOperations/AddMenuItemOperation.cs | 2 +- .../ConvertMenuItemToSeperatorOperation.cs | 8 ++++---- .../MoveMenuItemLeftOperation.cs | 4 ++-- .../MenuOperations/MoveMenuItemOperation.cs | 7 ++++--- .../MoveMenuItemRightOperation.cs | 7 +++++-- .../MenuOperations/RemoveMenuItemOperation.cs | 3 ++- src/Program.cs | 2 +- src/UI/Editor.cs | 19 +++++++++---------- 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/MenuTracker.cs b/src/MenuTracker.cs index acbe1c2a..86b36cf1 100644 --- a/src/MenuTracker.cs +++ b/src/MenuTracker.cs @@ -74,6 +74,7 @@ public void UnregisterMenuBar( MenuBar? mb ) /// or a sub-menu parent (e.g. View=>Windows). private MenuBarItem? GetParent( MenuItem item, out MenuBar? hostBar ) { + /* foreach (var bar in this.bars) { foreach (var sub in bar.SubViews.OfType()) @@ -87,7 +88,7 @@ public void UnregisterMenuBar( MenuBar? mb ) } } } - + */ hostBar = null; return null; } diff --git a/src/Operations/MenuOperations/AddMenuItemOperation.cs b/src/Operations/MenuOperations/AddMenuItemOperation.cs index c0d7c0f5..9f1b444a 100644 --- a/src/Operations/MenuOperations/AddMenuItemOperation.cs +++ b/src/Operations/MenuOperations/AddMenuItemOperation.cs @@ -78,7 +78,7 @@ private bool Add(MenuItem menuItem) int insertAt = Math.Max(0, currentItemIdx + 1); children.Insert(insertAt, menuItem); - this.Parent.Children = children.ToArray(); + // this.Parent.Children = children.ToArray(); this.Bar?.SetNeedsDraw(); diff --git a/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs b/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs index 1aaf598a..66c2215d 100644 --- a/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs +++ b/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs @@ -35,12 +35,12 @@ protected override void UndoImpl() { return; } - + /* var children = this.Parent.Children.ToList(); children[this.removedAtIdx] = this.OperateOn; this.Parent.Children = children.ToArray(); - this.Bar?.SetNeedsDraw(); + this.Bar?.SetNeedsDraw();*/ } /// @@ -50,7 +50,7 @@ protected override bool DoImpl() { return false; } - + /* var children = this.Parent.Children.ToList(); this.removedAtIdx = Math.Max(0, children.IndexOf(this.OperateOn)); @@ -58,7 +58,7 @@ protected override bool DoImpl() this.Parent.Children = children.ToArray(); this.Bar?.SetNeedsDraw(); - + */ return true; } } \ No newline at end of file diff --git a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs index bb276648..a9e995fd 100644 --- a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs @@ -71,7 +71,7 @@ protected override bool DoImpl() { return false; } - + /* // Figure out where the parent MenuBarItem was in the list because // after we remove ourselves from its sublist it might // turn into a MenuItem (i.e. we loose the reference). @@ -99,7 +99,7 @@ protected override bool DoImpl() return true; } - + */ return false; } } diff --git a/src/Operations/MenuOperations/MoveMenuItemOperation.cs b/src/Operations/MenuOperations/MoveMenuItemOperation.cs index 1c171149..249892de 100644 --- a/src/Operations/MenuOperations/MoveMenuItemOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemOperation.cs @@ -31,7 +31,7 @@ public MoveMenuItemOperation(MenuItem toMove, bool up) this.IsImpossible = true; return; } - + /* this.siblings = this.Parent.Children.ToList(); this.currentItemIdx = this.siblings.IndexOf(this.OperateOn); @@ -43,6 +43,7 @@ public MoveMenuItemOperation(MenuItem toMove, bool up) { this.IsImpossible = up ? this.currentItemIdx == 0 : this.currentItemIdx == this.siblings.Count - 1; } + */ } /// @@ -69,7 +70,7 @@ private bool Move(int amount) { return false; } - + /* int moveTo = Math.Max(0, amount + this.currentItemIdx); // pull it out from wherever it is @@ -82,7 +83,7 @@ private bool Move(int amount) this.Parent.Children = this.siblings.ToArray(); this.Bar?.SetNeedsDraw(); - + */ return true; } } \ No newline at end of file diff --git a/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs b/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs index 17d6e478..63cdc5ae 100644 --- a/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs @@ -18,10 +18,13 @@ public class MoveMenuItemRightOperation : MenuItemOperation public MoveMenuItemRightOperation(MenuItem toMove) : base(toMove) { + /* if (this.Parent?.GetChildrenIndex(toMove) == 0) { this.IsImpossible = true; } + */ + } /// @@ -60,7 +63,7 @@ protected override bool DoImpl() { return false; } - + /* // When user hits shift right var children = this.Parent.Children.ToList(); var currentItemIdx = children.IndexOf(this.OperateOn); @@ -98,7 +101,7 @@ protected override bool DoImpl() addTo.Children = submenuChildren.ToArray(); this.Bar?.SetNeedsDraw(); - + */ return true; } diff --git a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs index 6a3fff24..a886ef31 100644 --- a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs +++ b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs @@ -65,7 +65,7 @@ protected override void UndoImpl() { return; } - + /* this.Parent.Children = [ .. Parent.Children[ .. removedAtIdx ], @@ -117,6 +117,7 @@ .. Parent.Children[ removedAtIdx .. ] // times this.barRemovedFrom = null; } + */ } /// diff --git a/src/Program.cs b/src/Program.cs index 8b45b4dc..eb377d5a 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -23,7 +23,7 @@ public static void Main(string[] args) Editor.Quiet = o.Quiet; using var app = Application.Create().Init(o.Driver); - var editor = new Editor(); + var editor = new Editor(app); editor.Run(o); }); } diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index f2afa4bd..95a16154 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -2,10 +2,8 @@ using System.Reflection; using System.Text; using System.Text.Json; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Serilog; -using Terminal.Gui; using Terminal.Gui.App; using Terminal.Gui.Drawing; using Terminal.Gui.Drivers; @@ -28,6 +26,7 @@ namespace TerminalGuiDesigner.UI; /// public class Editor : Runnable, IErrorReporter { + private readonly IApplication app; private KeyMap keyMap; private readonly KeyboardManager keyboardManager; private readonly MouseManager mouseManager; @@ -69,8 +68,10 @@ public class Editor : Runnable, IErrorReporter /// /// Initializes a new instance of the class. /// - public Editor() + /// + public Editor(IApplication app) { + this.app = app; // Bug: This will have strange inheritance behavior if Editor is inherited from. this.CanFocus = true; @@ -207,12 +208,11 @@ public void Run(Options options) catch (Exception ex) { MessageBox.ErrorQuery(null, "Error Loading Designer", ex.Message, "Ok"); - Application.Shutdown(); return; } } - Application.KeyDown += (_, k) => + app.Keyboard.KeyDown += (_, k) => { if (this.editing || this.viewBeingEdited == null) { @@ -232,7 +232,7 @@ public void Run(Options options) } }; - Application.MouseEvent += (s, m) => + app.Mouse.MouseEvent += (s, m) => { // if another window is showing don't respond to mouse if (!this.IsCurrentTop) @@ -276,8 +276,7 @@ public void Run(Options options) } }; - Application.Run(this, this.ErrorHandler); - Application.Shutdown(); + app.Run(this, this.ErrorHandler); } /// @@ -355,8 +354,8 @@ protected override bool OnDrawingContent(DrawContext? context) var bounds = Viewport; - Application.Driver.SetAttribute(new Attribute(Color.Black)); - Application.Driver.FillRect(bounds,' '); + app.Driver.SetAttribute(new Attribute(Color.Black)); + app.Driver.FillRect(bounds,' '); var top = new Rectangle(0, 0, bounds.Width, rootCommandsListView.Frame.Top - 1); RenderTitle(top); From 6d7bbd2663a4ed7d50b793811a3bc7341203bab1 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 02:50:53 +0000 Subject: [PATCH 006/101] app for everyone --- src/UI/Editor.cs | 46 ++++++++++++++-------------- src/UI/KeyboardManager.cs | 7 +++-- src/UI/ValueFactory.cs | 10 +++--- src/UI/Windows/ArrayEditor.cs | 9 ++++-- src/UI/Windows/EditDialog.cs | 12 +++++--- src/UI/Windows/ExceptionViewer.cs | 5 +-- src/UI/Windows/SliderOptionEditor.cs | 16 +++++----- tests/KeyboardManagerTests.cs | 8 ++--- 8 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 95a16154..37323bfd 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -82,7 +82,7 @@ public Editor(IApplication app) LoadKeyMap(); - this.keyboardManager = new KeyboardManager(this.keyMap); + this.keyboardManager = new KeyboardManager(app, this.keyMap); this.mouseManager = new MouseManager() { ErrorReporter = this @@ -117,7 +117,7 @@ private void LoadKeyMap() catch (Exception ex) { // if there is bad yaml use the defaults - ExceptionViewer.ShowException("Failed to read keybindings from configuration file", ex); + ExceptionViewer.ShowException(app,"Failed to read keybindings from configuration file", ex); this.keyMap = new KeyMap(); } } @@ -133,7 +133,7 @@ private void SaveKeyMap() } catch (Exception ex) { - ExceptionViewer.ShowException("Failed to save keybindings from configuration file", ex); + ExceptionViewer.ShowException(app, "Failed to save keybindings from configuration file", ex); } } @@ -228,7 +228,7 @@ public void Run(Options options) } catch (Exception ex) { - ExceptionViewer.ShowException("Error processing keystroke", ex); + ExceptionViewer.ShowException(app, "Error processing keystroke", ex); } }; @@ -272,7 +272,7 @@ public void Run(Options options) } catch (Exception ex) { - ExceptionViewer.ShowException("Error processing mouse", ex); + ExceptionViewer.ShowException(app,"Error processing mouse", ex); } }; @@ -353,9 +353,9 @@ protected override bool OnDrawingContent(DrawContext? context) } var bounds = Viewport; - - app.Driver.SetAttribute(new Attribute(Color.Black)); - app.Driver.FillRect(bounds,' '); + + SetAttribute(new Attribute(Color.Black)); + FillRect(bounds,new Rune(' ')); var top = new Rectangle(0, 0, bounds.Width, rootCommandsListView.Frame.Top - 1); RenderTitle(top); @@ -738,7 +738,7 @@ public bool HandleKey(Key key) } catch (Exception ex) { - ExceptionViewer.ShowException("Error", ex); + ExceptionViewer.ShowException(app, "Error", ex); } finally { @@ -941,7 +941,7 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) // BUG: This is an improper exception here and could have unexpected behavior if this method is ever called asynchronously. var factory = new OperationFactory( - (p, v) => ValueFactory.GetNewValue(p.Design, p, v, out var newValue) ? newValue : throw new OperationCanceledException() ); + (p, v) => ValueFactory.GetNewValue(app, p.Design, p, v, out var newValue) ? newValue : throw new OperationCanceledException() ); var operations = factory .CreateOperations(selected, m, rightClicked, out string name) @@ -951,9 +951,9 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) var setProps = operations.OfType(); var others = operations .Except(setProps) - .GroupBy(k => k.Category, ToMenuItem); + .GroupBy(k => k.Category, p=>ToMenuItem(app,p)); - var setPropsItems = setProps.Select(ToMenuItem).ToArray(); + var setPropsItems = setProps.Select(p=>ToMenuItem(app,p)).ToArray(); bool hasPropsItems = setPropsItems.Any(); var all = new List(); @@ -1038,11 +1038,11 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) }; } - private static MenuItem ToMenuItem(IOperation operation) + private static MenuItem ToMenuItem(IApplication application, IOperation operation) { - return new MenuItem(operation.ToString(), string.Empty, () => Try(() => OperationManager.Instance.Do(operation))); + return new MenuItem(operation.ToString(), string.Empty, () => Try(application,() => OperationManager.Instance.Do(operation))); - static void Try(Action action) + static void Try(IApplication application, Action action) { try { @@ -1053,7 +1053,7 @@ static void Try(Action action) } catch (Exception ex) { - ExceptionViewer.ShowException("Operation failed", ex); + ExceptionViewer.ShowException(application, "Operation failed", ex); } finally { @@ -1255,14 +1255,14 @@ private void Open() } catch (Exception ex) { - ExceptionViewer.ShowException($"Failed to open '{ofd.Path}'", ex); + ExceptionViewer.ShowException(app,$"Failed to open '{ofd.Path}'", ex); } } } private bool ErrorHandler(Exception arg) { - ExceptionViewer.ShowException("Global Exception", arg); + ExceptionViewer.ShowException(app,"Global Exception", arg); return true; } @@ -1289,7 +1289,7 @@ private void Open(FileInfo toOpen) if (t.Exception != null) { Application.Invoke(() => - ExceptionViewer.ShowException($"Failed to open '{toOpen.Name}'", t.Exception)); + ExceptionViewer.ShowException(app, $"Failed to open '{toOpen.Name}'", t.Exception)); return; } @@ -1369,7 +1369,7 @@ private void New() } catch (Exception ex) { - ExceptionViewer.ShowException($"Failed to create '{ofd.Path}'", ex); + ExceptionViewer.ShowException(app, $"Failed to create '{ofd.Path}'", ex); throw; } } @@ -1427,7 +1427,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) if (t.Exception != null) { Application.Invoke(() => - ExceptionViewer.ShowException($"Failed to create '{toOpen.Name}'", t.Exception)); + ExceptionViewer.ShowException(app, $"Failed to create '{toOpen.Name}'", t.Exception)); return; } @@ -1510,7 +1510,7 @@ private void ShowEditProperties() private void ShowEditProperties(Design d) { - var edit = new EditDialog(d); - Application.Run(edit, this.ErrorHandler); + var edit = new EditDialog(app, d); + app.Run(edit, this.ErrorHandler); } } \ No newline at end of file diff --git a/src/UI/KeyboardManager.cs b/src/UI/KeyboardManager.cs index 48e9be49..ebff9f00 100644 --- a/src/UI/KeyboardManager.cs +++ b/src/UI/KeyboardManager.cs @@ -17,15 +17,18 @@ namespace TerminalGuiDesigner.UI; /// public class KeyboardManager { + private readonly IApplication app; private readonly KeyMap keyMap; private SetPropertyOperation? currentOperation; /// /// Initializes a new instance of the class. /// + /// /// User configurable keybindings for class functionality. - public KeyboardManager(KeyMap keyMap) + public KeyboardManager(IApplication app, KeyMap keyMap) { + this.app = app; this.keyMap = keyMap; } @@ -73,7 +76,7 @@ public bool HandleKey(View focusedView, Key keystroke) var nameProp = d.GetDesignableProperties().OfType().FirstOrDefault(); if (nameProp != null) { - EditDialog.SetPropertyToNewValue(d, nameProp, nameProp.GetValue()); + EditDialog.SetPropertyToNewValue(app, d, nameProp, nameProp.GetValue()); return true; } } diff --git a/src/UI/ValueFactory.cs b/src/UI/ValueFactory.cs index b328a36c..32625bfc 100644 --- a/src/UI/ValueFactory.cs +++ b/src/UI/ValueFactory.cs @@ -47,13 +47,13 @@ static class ValueFactory typeof(DateTime?) }; - internal static bool GetNewValue(string propertyName, Design design, Type type, object? oldValue, out object? newValue, bool allowMultiLine) + internal static bool GetNewValue(IApplication app, string propertyName, Design design, Type type, object? oldValue, out object? newValue, bool allowMultiLine) { newValue = null; if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SliderOption<>)) { - return RunEditor(new SliderOptionEditor(type.GetGenericArguments()[0], oldValue), out newValue); + return RunEditor(new SliderOptionEditor(app, type.GetGenericArguments()[0], oldValue), out newValue); } if (type == typeof(Pos)) { @@ -114,7 +114,7 @@ internal static bool GetNewValue(string propertyName, Design design, Type type, } else { - var designer = new ArrayEditor(design, type.GetElementTypeEx(), (IList)oldValue); + var designer = new ArrayEditor(app, design, type.GetElementTypeEx(), (IList)oldValue); Application.Run(designer); if (!designer.Cancelled) @@ -234,7 +234,7 @@ private static bool RunEditor(T editor, out object? result) where T : Dialog, return true; } - internal static bool GetNewValue(Design design, Property property, object? oldValue, out object? newValue) + internal static bool GetNewValue(IApplication app, Design design, Property property, object? oldValue, out object? newValue) { if (property is InstanceOfProperty inst) { @@ -262,7 +262,7 @@ internal static bool GetNewValue(Design design, Property property, object? oldVa } else { - return GetNewValue(property.PropertyInfo.Name, design, property.PropertyInfo.PropertyType, oldValue, out newValue, ValueFactory.AllowMultiLine(property)); + return GetNewValue(app, property.PropertyInfo.Name, design, property.PropertyInfo.PropertyType, oldValue, out newValue, ValueFactory.AllowMultiLine(property)); } } diff --git a/src/UI/Windows/ArrayEditor.cs b/src/UI/Windows/ArrayEditor.cs index 081ba0ec..b79f3630 100644 --- a/src/UI/Windows/ArrayEditor.cs +++ b/src/UI/Windows/ArrayEditor.cs @@ -28,6 +28,7 @@ public partial class ArrayEditor : IValueGetterDialog { /// public bool Cancelled { get; private set; } = true; + private readonly IApplication app; private readonly Design design; private Type elementType; @@ -46,11 +47,13 @@ public partial class ArrayEditor : IValueGetterDialog { /// Creates a new instance of the editor configured to build lists of /// and showing initial values held in (if any). /// + /// /// /// /// - public ArrayEditor(Design design, Type elementType, IList oldValue) { + public ArrayEditor(IApplication app, Design design, Type elementType, IList oldValue) { InitializeComponent(); + this.app = app; this.design = design; this.elementType = elementType; @@ -139,7 +142,7 @@ private void DeleteSelectedItem() private void BtnAddElement_Clicked(object sender, CommandEventArgs e) { - if(ValueFactory.GetNewValue("Element Value", design, this.elementType,null, out var newValue,true)) + if(ValueFactory.GetNewValue(app, "Element Value", design, this.elementType,null, out var newValue,true)) { ResultAsList.Add(newValue); } @@ -157,7 +160,7 @@ private void BtnEdit_Clicked(object sender, CommandEventArgs e) { var toEdit = ResultAsList[idx]; - if (ValueFactory.GetNewValue("Element Value", design, this.elementType, toEdit, out var newValue, true)) + if (ValueFactory.GetNewValue(app, "Element Value", design, this.elementType, toEdit, out var newValue, true)) { // Replace old with new ResultAsList.RemoveAt(idx); diff --git a/src/UI/Windows/EditDialog.cs b/src/UI/Windows/EditDialog.cs index b509599b..52d5f214 100644 --- a/src/UI/Windows/EditDialog.cs +++ b/src/UI/Windows/EditDialog.cs @@ -19,6 +19,7 @@ namespace TerminalGuiDesigner.UI.Windows; public class EditDialog : Window { private readonly ListView list; + private readonly IApplication app; private readonly Design design; private readonly List collection = new(); @@ -26,8 +27,9 @@ public class EditDialog : Window /// Initializes a new instance of the class. /// /// The on which you want to set properties. - public EditDialog(Design design) + public EditDialog(IApplication app, Design design) { + this.app = app; this.design = design; this.collection.Clear( ); this.collection.AddRange( this.design.GetDesignableProperties( ) @@ -93,10 +95,10 @@ public EditDialog(Design design) } - internal static bool SetPropertyToNewValue(Design design, Property p, object? oldValue) + internal static bool SetPropertyToNewValue(IApplication app, Design design, Property p, object? oldValue) { // user wants to give us a new value for this property - if (ValueFactory.GetNewValue(design, p, p.GetValue(), out object? newValue)) + if (ValueFactory.GetNewValue(app, design, p, p.GetValue(), out object? newValue)) { OperationManager.Instance.Do( new SetPropertyOperation(design, p, oldValue, newValue)); @@ -124,7 +126,7 @@ private void SetProperty(bool setNull) } else { - if (!SetPropertyToNewValue(this.design, p, oldValue)) + if (!SetPropertyToNewValue(app, this.design, p, oldValue)) { // user cancelled editing the value return; @@ -138,7 +140,7 @@ private void SetProperty(bool setNull) } catch (Exception e) { - ExceptionViewer.ShowException("Failed to set Property", e); + ExceptionViewer.ShowException(app, "Failed to set Property", e); } } } diff --git a/src/UI/Windows/ExceptionViewer.cs b/src/UI/Windows/ExceptionViewer.cs index b2a8aa95..f1c7ebc1 100644 --- a/src/UI/Windows/ExceptionViewer.cs +++ b/src/UI/Windows/ExceptionViewer.cs @@ -14,10 +14,11 @@ public class ExceptionViewer /// /// Launches a new modal instance of showing . /// + /// /// Message that describes what was going on when - /// occurred (e.g. "Could not open file x"). + /// occurred (e.g. "Could not open file x"). /// to show. - public static void ShowException(string errorText, Exception exception) + public static void ShowException(IApplication app, string errorText, Exception exception) { Logging.Critical(errorText + exception); var msg = GetExceptionText(errorText, exception, false); diff --git a/src/UI/Windows/SliderOptionEditor.cs b/src/UI/Windows/SliderOptionEditor.cs index 7528d618..ea45aaf6 100644 --- a/src/UI/Windows/SliderOptionEditor.cs +++ b/src/UI/Windows/SliderOptionEditor.cs @@ -14,13 +14,12 @@ using Terminal.Gui.Views; namespace TerminalGuiDesigner.UI.Windows { - using System.Reflection; using System.Text; - using Terminal.Gui; - - + + public partial class SliderOptionEditor : IValueGetterDialog { + private readonly IApplication app; private readonly Type genericTypeArgument; private readonly Type sliderOptionType; @@ -40,9 +39,10 @@ public partial class SliderOptionEditor : IValueGetterDialog /// /// The T Type of the you want to design /// Previous value (if editing an existing instance). - public SliderOptionEditor(Type genericTypeArgument, object? oldValue) { + public SliderOptionEditor(IApplication app, Type genericTypeArgument, object? oldValue) { InitializeComponent(); + this.app = app; this.genericTypeArgument = genericTypeArgument; this.sliderOptionType = typeof(SliderOption<>).MakeGenericType(this.genericTypeArgument); @@ -76,7 +76,7 @@ private void BtnCancel_Clicked(object sender, CommandEventArgs e) { e.Handled = true; this.Cancelled = true; - Application.RequestStop(); + app.RequestStop(); } private void BtnOk_Clicked(object sender, CommandEventArgs e) @@ -88,12 +88,12 @@ private void BtnOk_Clicked(object sender, CommandEventArgs e) } catch(Exception ex) { - ExceptionViewer.ShowException("Could not build result", ex); + ExceptionViewer.ShowException(app, "Could not build result", ex); return; } this.Cancelled = false; - Application.RequestStop(); + app.RequestStop(); } private void BuildResult() diff --git a/tests/KeyboardManagerTests.cs b/tests/KeyboardManagerTests.cs index 8ad6b8dd..690d6a57 100644 --- a/tests/KeyboardManagerTests.cs +++ b/tests/KeyboardManagerTests.cs @@ -31,7 +31,7 @@ public void Constructor( ) Assume.That( keyMap, Is.Not.Null.And.TypeOf( ) ); KeyboardManager? mgr = null; - Assert.That( ( ) => mgr = new( keyMap! ), Throws.Nothing ); + Assert.That( ( ) => mgr = new(TODO, keyMap! ), Throws.Nothing ); Assert.That( mgr, Is.Not.Null.And.TypeOf( ) ); } @@ -60,7 +60,7 @@ public void Backspace_WithDateFieldSelected( ) Assume.That( keyMap, Is.Not.Null.And.TypeOf( ) ); KeyboardManager? mgr = null; - Assert.That( ( ) => mgr = new( keyMap! ), Throws.Nothing ); + Assert.That( ( ) => mgr = new(TODO, keyMap! ), Throws.Nothing ); Assert.That( mgr, Is.Not.Null.And.TypeOf( ) ); bool keyEventSuppressed = false; @@ -99,7 +99,7 @@ public void ButtonRename( ) Assume.That( keyMap, Is.Not.Null.And.TypeOf( ) ); KeyboardManager? mgr = null; - Assert.That( ( ) => mgr = new( keyMap! ), Throws.Nothing ); + Assert.That( ( ) => mgr = new(TODO, keyMap! ), Throws.Nothing ); Assert.That( mgr, Is.Not.Null.And.TypeOf( ) ); Assert.That( ( ) => mgr!.HandleKey( v, backspace ), Throws.Nothing ); @@ -136,7 +136,7 @@ public void HandleKey_AddsExpectedCharactersToView_AsciiAlphanumeric( [ValueS Assume.That( keyMap, Is.Not.Null.And.TypeOf() ); KeyboardManager? mgr = null; - Assert.That( () => mgr = new( keyMap! ), Throws.Nothing ); + Assert.That( () => mgr = new(TODO, keyMap! ), Throws.Nothing ); Assert.That( mgr, Is.Not.Null.And.TypeOf() ); Assume.That( testView, Is.Not.Null.And.InstanceOf() ); From 9fd82d1cc39927c22ccdeab80c04e2aa1c7b8b21 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 03:24:11 +0000 Subject: [PATCH 007/101] App for everyone --- src/Operations/AddViewOperation.cs | 22 ++++++++++-- src/Operations/Generics/AddOperation.cs | 2 +- src/Operations/Generics/RenameOperation.cs | 2 +- .../MenuOperations/RenameMenuItemOperation.cs | 2 +- src/Operations/Operation.cs | 5 +++ .../SetShortcutOperation.cs | 2 +- src/UI/Editor.cs | 36 +++++++++---------- src/UI/KeyboardManager.cs | 2 +- src/UI/ValueFactory.cs | 35 +++++++++--------- src/UI/Windows/ArrayEditor.cs | 4 +-- src/UI/Windows/BigListBox.cs | 12 ++++--- src/UI/Windows/ChoicesDialog.cs | 24 +++++++------ src/UI/Windows/DimEditor.cs | 11 +++--- src/UI/Windows/EditDialog.cs | 4 +-- src/UI/Windows/ExceptionViewer.cs | 4 +-- src/UI/Windows/GetTextDialog.cs | 10 +++--- src/UI/Windows/KeyBindingsUI.cs | 12 ++++--- src/UI/Windows/Modals.cs | 36 ++++++++++--------- src/UI/Windows/PointEditor.cs | 10 ++++-- src/UI/Windows/PosEditor.cs | 15 ++++---- 20 files changed, 151 insertions(+), 99 deletions(-) diff --git a/src/Operations/AddViewOperation.cs b/src/Operations/AddViewOperation.cs index 4fdc2cc1..4cdc16f2 100644 --- a/src/Operations/AddViewOperation.cs +++ b/src/Operations/AddViewOperation.cs @@ -37,6 +37,19 @@ public AddViewOperation(View add, Design to, string? fieldName) this.to = to; } + /// + /// Initializes a new instance of the class. + /// This overload asks users what view type they want at runtime (See ). + /// + /// The application instance. + /// A (which should be ) + /// to add any newly created to. + public AddViewOperation(IApplication app, Design design) + { + this.App = app; + this.to = design; + } + /// /// Initializes a new instance of the class. /// This overload asks users what view type they want at runtime (See ). @@ -79,15 +92,20 @@ protected override bool DoImpl() { if (this.add == null) { + if (this.App == null) + { + throw new InvalidOperationException("App is required for interactive add operations"); + } + var selectable = ViewFactory.SupportedViewTypes.ToArray(); - if (Modals.Get("Type of Control", "Add", true, selectable, this.TypeNameDelegate, false, null, out var selected) && selected != null) + if (Modals.Get(this.App, "Type of Control", "Add", true, selectable, this.TypeNameDelegate, false, null, out var selected) && selected != null) { if (selected.IsGenericType) { var allowedTTypes = TTypes.GetSupportedTTypesForGenericViewOfType(selected).ToArray(); - if(Modals.Get("Enter a Type for ", "Choose", true, allowedTTypes, this.TypeNameDelegate, false, null, out var selectedTType) && selectedTType != null) + if(Modals.Get(this.App, "Enter a Type for ", "Choose", true, allowedTTypes, this.TypeNameDelegate, false, null, out var selectedTType) && selectedTType != null) { selected = selected.MakeGenericType(new[] { selectedTType }); } diff --git a/src/Operations/Generics/AddOperation.cs b/src/Operations/Generics/AddOperation.cs index 36f3e692..94180a6b 100644 --- a/src/Operations/Generics/AddOperation.cs +++ b/src/Operations/Generics/AddOperation.cs @@ -71,7 +71,7 @@ protected override bool DoImpl() if (uniqueName == null) { - if (!Modals.GetString("Name", "Name", $"My{typeof(T2).Name}", out uniqueName)) + if (!Modals.GetString(App!, "Name", "Name", $"My{typeof(T2).Name}", out uniqueName)) { // user canceled adding return false; diff --git a/src/Operations/Generics/RenameOperation.cs b/src/Operations/Generics/RenameOperation.cs index 9b28cddd..36382fba 100644 --- a/src/Operations/Generics/RenameOperation.cs +++ b/src/Operations/Generics/RenameOperation.cs @@ -74,7 +74,7 @@ protected override bool DoImpl() { if (string.IsNullOrWhiteSpace(this.newName)) { - if (Modals.GetString($"Rename {typeof(T2).Name}", "Name", this.originalName?.ToString(), out string? n) && n != null) + if (Modals.GetString(App!, $"Rename {typeof(T2).Name}", "Name", this.originalName?.ToString(), out string? n) && n != null) { this.newName = n; } diff --git a/src/Operations/MenuOperations/RenameMenuItemOperation.cs b/src/Operations/MenuOperations/RenameMenuItemOperation.cs index b7ff46e7..a4ce4708 100644 --- a/src/Operations/MenuOperations/RenameMenuItemOperation.cs +++ b/src/Operations/MenuOperations/RenameMenuItemOperation.cs @@ -55,7 +55,7 @@ protected override bool DoImpl() } // TODO: make this an optional constructor field so it can be unit tested - if (Modals.GetString("Menu Item Name", "Name", this.originalName, out string? newName)) + if (Modals.GetString(App!, "Menu Item Name", "Name", this.originalName, out string? newName)) { if (string.IsNullOrWhiteSpace(newName)) { diff --git a/src/Operations/Operation.cs b/src/Operations/Operation.cs index 0b0fe5ae..6559d671 100644 --- a/src/Operations/Operation.cs +++ b/src/Operations/Operation.cs @@ -9,6 +9,11 @@ namespace TerminalGuiDesigner.Operations; /// public abstract class Operation : IOperation { + /// + /// The application instance. May be null for operations that don't need to show dialogs. + /// + protected IApplication? App { get; set; } + /// /// The number of times the operation has been performed. /// diff --git a/src/Operations/StatusBarOperations/SetShortcutOperation.cs b/src/Operations/StatusBarOperations/SetShortcutOperation.cs index 3b59154a..bb24d10b 100644 --- a/src/Operations/StatusBarOperations/SetShortcutOperation.cs +++ b/src/Operations/StatusBarOperations/SetShortcutOperation.cs @@ -55,7 +55,7 @@ protected override bool DoImpl() { if (this.shortcut == Key.Empty) { - this.shortcut = Modals.GetShortcut(); + this.shortcut = Modals.GetShortcut(App!); } this.OperateOn.Key = this.shortcut; diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 37323bfd..5764290a 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -893,9 +893,9 @@ private void BuildRootMenu() private void ChangeKeybindings() { - var kb = new KeyBindingsUI(keyMap); - Application.Run(kb); - + var kb = new KeyBindingsUI(app, keyMap); + app.Run(kb); + if (kb.Save) { SaveKeyMap(); @@ -912,7 +912,7 @@ private void Editor_Closing(object? sender, CancelEventArgs obj) if (this.HasUnsavedChanges) { - int answer = ChoicesDialog.Query("Unsaved Changes", $"You have unsaved changes to {this.viewBeingEdited.SourceCode.DesignerFile.Name}", "Save", "Don't Save", "Cancel"); + int answer = ChoicesDialog.Query(app, "Unsaved Changes", $"You have unsaved changes to {this.viewBeingEdited.SourceCode.DesignerFile.Name}", "Save", "Don't Save", "Cancel"); if (answer == 0) { @@ -1134,7 +1134,7 @@ private void ShowViewSpecificOperations() { var options = d.GetExtraOperations().Where(o => !o.IsImpossible).ToArray(); - if (options.Any() && Modals.Get("Operations", "Ok", options, null, out var selected) && selected != null) + if (options.Any() && Modals.Get(app, "Operations", "Ok", options, null, out var selected) && selected != null) { OperationManager.Instance.Do(selected); } @@ -1154,8 +1154,8 @@ private void ShowHelp() { return; } - - ChoicesDialog.Query("Help", this.GetHelp(), "Ok"); + + ChoicesDialog.Query(app, "Help", this.GetHelp(), "Ok"); } private void MoveControl(int deltaX, int deltaY) @@ -1238,7 +1238,7 @@ private void Open() }; ofd.Layout(); - Application.Run(ofd, this.ErrorHandler); + app.Run(ofd, this.ErrorHandler); if (!ofd.Canceled) { @@ -1284,7 +1284,7 @@ private void Open(FileInfo toOpen) (t, _) => { // no longer loading - Application.Invoke(() => Application.RequestStop()); + Application.Invoke(() => app.RequestStop()); if (t.Exception != null) { @@ -1301,12 +1301,12 @@ private void Open(FileInfo toOpen) }, TaskScheduler.FromCurrentSynchronizationContext()); - Application.Run(open, this.ErrorHandler); + app.Run(open, this.ErrorHandler); } private void New() { - if (!Modals.Get("Create New View", "Ok", GetSupportedRootViews(), null, out var selected)) + if (!Modals.Get(app, "Create New View", "Ok", GetSupportedRootViews(), null, out var selected)) { return; } @@ -1320,7 +1320,7 @@ private void New() ofd.Style.PreserveFilenameOnDirectoryChanges = true; ofd.Layout(); - Application.Run(ofd); + app.Run(ofd); if (!ofd.Canceled) { @@ -1341,7 +1341,7 @@ private void New() if(!CodeDomArgs.IsValidIdentifier(files.ClassName)) { - ChoicesDialog.Query("Invalid Name",$"Invalid class name '{files.ClassName}'","Ok"); + ChoicesDialog.Query(app, "Invalid Name",$"Invalid class name '{files.ClassName}'","Ok"); return; } @@ -1359,7 +1359,7 @@ private void New() if (sb.Length > 0) { - if (!ChoicesDialog.Confirm("Overwrite Files?", $"The following files will be overwritten:{Environment.NewLine}{sb.ToString().TrimEnd()}", "Ok", "Cancel")) + if (!ChoicesDialog.Confirm(app, "Overwrite Files?", $"The following files will be overwritten:{Environment.NewLine}{sb.ToString().TrimEnd()}", "Ok", "Cancel")) { return; // user canceled overwrite } @@ -1390,7 +1390,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) if (string.IsNullOrWhiteSpace(ns)) { // prompt user for namespace - if (!Modals.GetString("Namespace", "Enter the namespace for your class", "YourNamespace", out ns)) + if (!Modals.GetString(app, "Namespace", "Enter the namespace for your class", "YourNamespace", out ns)) { // user cancelled typing a namespace return; @@ -1422,7 +1422,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) (t, _) => { // no longer loading - Application.Invoke(() => Application.RequestStop()); + Application.Invoke(() => app.RequestStop()); if (t.Exception != null) { @@ -1439,7 +1439,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) }, TaskScheduler.FromCurrentSynchronizationContext()); - Application.Run(open, this.ErrorHandler); + app.Run(open, this.ErrorHandler); } private void ReplaceViewBeingEdited(Design design) @@ -1496,7 +1496,7 @@ private void ShowAddViewWindow() var toAddTo = SelectionManager.Instance.GetMostSelectedContainerOrNull() ?? this.viewBeingEdited; OperationManager.Instance.Do( - new AddViewOperation(toAddTo)); + new AddViewOperation(app, toAddTo)); } private void ShowEditProperties() diff --git a/src/UI/KeyboardManager.cs b/src/UI/KeyboardManager.cs index ebff9f00..357cfe44 100644 --- a/src/UI/KeyboardManager.cs +++ b/src/UI/KeyboardManager.cs @@ -117,7 +117,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.SetShortcut) { - menuItem.Key = Modals.GetShortcut().KeyCode; + menuItem.Key = Modals.GetShortcut(app).KeyCode; focusedView.SetNeedsDraw(); return false; diff --git a/src/UI/ValueFactory.cs b/src/UI/ValueFactory.cs index 32625bfc..76b51c83 100644 --- a/src/UI/ValueFactory.cs +++ b/src/UI/ValueFactory.cs @@ -53,20 +53,20 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(SliderOption<>)) { - return RunEditor(new SliderOptionEditor(app, type.GetGenericArguments()[0], oldValue), out newValue); + return RunEditor(app, new SliderOptionEditor(app, type.GetGenericArguments()[0], oldValue), out newValue); } if (type == typeof(Pos)) { - return RunEditor(new PosEditor(design, (Pos)oldValue ?? throw new Exception("Pos property was unexpectedly null")), out newValue); + return RunEditor(app, new PosEditor(app, design, (Pos)oldValue ?? throw new Exception("Pos property was unexpectedly null")), out newValue); } if (type == typeof(Size)) { - return RunEditor(new SizeEditor((Size)(oldValue ?? throw new Exception($"Property {propertyName} is of Type Size but its current value is null"))), out newValue); + return RunEditor(app, new SizeEditor((Size)(oldValue ?? throw new Exception($"Property {propertyName} is of Type Size but its current value is null"))), out newValue); } if (type == typeof(Point)) { var oldPoint = (Point)(oldValue ?? throw new Exception($"Property {propertyName} is of Type Point but its current value is null")); - var result = RunEditor(new PointEditor(oldPoint.X, oldPoint.Y), out newValue); + var result = RunEditor(app, new PointEditor(app, oldPoint.X, oldPoint.Y), out newValue); if (newValue != null) { @@ -78,15 +78,15 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d if (type == typeof(PointF)) { var oldPointF = (PointF)(oldValue ?? throw new Exception($"Property {propertyName} is of Type PointF but its current value is null")); - return RunEditor(new PointEditor(oldPointF.X, oldPointF.Y), out newValue); + return RunEditor(app, new PointEditor(app, oldPointF.X, oldPointF.Y), out newValue); } if (type == typeof(Dim)) { - return RunEditor(new DimEditor(design, (Dim)oldValue), out newValue); + return RunEditor(app, new DimEditor(app, design, (Dim)oldValue), out newValue); } if (type == typeof(bool)) { - int answer = ChoicesDialog.Query(propertyName, $"New value for {type}", "Yes", "No"); + int answer = ChoicesDialog.Query(app, propertyName, $"New value for {type}", "Yes", "No"); newValue = answer == 0 ? true : false; return answer != -1; } @@ -102,6 +102,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d if (elementType.IsValueType || elementType == typeof(string)) { if (Modals.GetArray( + app, propertyName, "New Array Value", type.GetElementType() ?? throw new Exception("Property was an Array but GetElementType returned null"), @@ -115,7 +116,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d else { var designer = new ArrayEditor(app, design, type.GetElementTypeEx(), (IList)oldValue); - Application.Run(designer); + app.Run(designer); if (!designer.Cancelled) { @@ -143,6 +144,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d .ToArray(); if (Modals.TryGetArray( + app, propertyName, "New List Value", oldValueAsArrayOfStrings, @@ -155,7 +157,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d else if (type.IsEnum) { - if (Modals.GetEnum(propertyName, "New Enum Value", type, (Enum?)oldValue, out var resultEnum)) + if (Modals.GetEnum(app, propertyName, "New Enum Value", type, (Enum?)oldValue, out var resultEnum)) { newValue = resultEnum; return true; @@ -165,7 +167,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d if (ConvertChangeTypeSupports.Contains(type)) { var oldValueConverted = oldValue == null ? null : Convert.ChangeType(oldValue, type); - if (Modals.GetString(propertyName, $"New {type.Name} Value", oldValueConverted?.ToString(), out var result, allowMultiLine)) + if (Modals.GetString(app, propertyName, $"New {type.Name} Value", oldValueConverted?.ToString(), out var result, allowMultiLine)) { newValue = string.IsNullOrWhiteSpace(result) ? null : Convert.ChangeType(result, type); return true; @@ -175,7 +177,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d if (type== typeof(Rune) || type== typeof(Rune?)) { - if (Modals.GetChar(propertyName, "New Single Character", oldValue is null ? null : (char?)oldValue.ToPrimitive() ?? null, out var resultChar)) + if (Modals.GetChar(app, propertyName, "New Single Character", oldValue is null ? null : (char?)oldValue.ToPrimitive() ?? null, out var resultChar)) { newValue = resultChar == null ? null : new Rune(resultChar.Value); return true; @@ -188,7 +190,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d fd.AllowsMultipleSelection = false; fd.Layout(); - int answer = ChoicesDialog.Query(propertyName, $"Directory or File?", "Directory", "File", "Cancel"); + int answer = ChoicesDialog.Query(app, propertyName, $"Directory or File?", "Directory", "File", "Cancel"); if (answer < 0 || answer >= 2) { @@ -198,7 +200,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d fd.OpenMode = pickDir ? OpenMode.Directory : OpenMode.File; - Application.Run(fd); + app.Run(fd); if (fd.Canceled || string.IsNullOrWhiteSpace(fd.Path)) { return false; @@ -211,7 +213,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d } } else - if (Modals.GetString(propertyName, "New String Value", oldValue?.ToString(), out var result, allowMultiLine)) + if (Modals.GetString(app, propertyName, "New String Value", oldValue?.ToString(), out var result, allowMultiLine)) { newValue = result; return true; @@ -221,9 +223,9 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d return false; } - private static bool RunEditor(T editor, out object? result) where T : Dialog, IValueGetterDialog + private static bool RunEditor(IApplication app, T editor, out object? result) where T : Dialog, IValueGetterDialog { - Application.Run(editor); + app.Run(editor); if (editor.Cancelled) { result = null; @@ -239,6 +241,7 @@ internal static bool GetNewValue(IApplication app, Design design, Property prope if (property is InstanceOfProperty inst) { if (Modals.Get( + app, property.PropertyInfo.Name, "New Value", typeof(Label).Assembly.GetTypes() diff --git a/src/UI/Windows/ArrayEditor.cs b/src/UI/Windows/ArrayEditor.cs index b79f3630..c7242a12 100644 --- a/src/UI/Windows/ArrayEditor.cs +++ b/src/UI/Windows/ArrayEditor.cs @@ -179,14 +179,14 @@ private void BtnCancel_Clicked(object sender, CommandEventArgs e) { e.Handled = true; Cancelled = true; - Application.RequestStop(); + app.RequestStop(); } private void BtnOk_Clicked(object sender, CommandEventArgs e) { e.Handled = true; Cancelled = false; - Application.RequestStop(); + app.RequestStop(); } } } diff --git a/src/UI/Windows/BigListBox.cs b/src/UI/Windows/BigListBox.cs index f332f73e..a76ae5fc 100644 --- a/src/UI/Windows/BigListBox.cs +++ b/src/UI/Windows/BigListBox.cs @@ -19,6 +19,7 @@ public class BigListBox private static readonly string[ ] ErrorStringArray = new[] { "Error" }; private readonly object taskCancellationLock = new(); private readonly ConcurrentBag cancelFiltering = new(); + private readonly IApplication app; private readonly Window win; private readonly ListView listView; private readonly bool addNull; @@ -45,6 +46,7 @@ public class BigListBox /// /// Initializes a new instance of the class. /// + /// The application instance. /// User message indicating what they are being asked to select. /// The confirmation text on the 'ok' button. /// True to add search text box. @@ -53,7 +55,8 @@ public class BigListBox /// Creates a selection option "Null" that returns a null selection. /// The optional existing value, if present it should be selected in the list. /// - public BigListBox(string prompt, + public BigListBox(IApplication app, + string prompt, string okText, in bool addSearch, IList collection, @@ -61,6 +64,7 @@ public BigListBox(string prompt, bool addNull, T? currentSelection, bool sort = true) { + this.app = app; this.AspectGetter = displayMember ?? (arg => arg?.ToString() ?? string.Empty); // Sort alphabetically according to display member @@ -122,7 +126,7 @@ public BigListBox(string prompt, btnCancel.Accepting += (s, e) => { e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; if (addSearch) @@ -197,7 +201,7 @@ public BigListBox(string prompt, /// True if selection was made (see ) or false if user cancelled the dialog. public bool ShowDialog() { - Application.Run(this.win); + app.Run(this.win); Application.RemoveTimeout(this.callback); @@ -213,7 +217,7 @@ private void Accept() } this.okClicked = true; - Application.RequestStop(); + app.RequestStop(); this.Selected = this.collection[selected].Object; } diff --git a/src/UI/Windows/ChoicesDialog.cs b/src/UI/Windows/ChoicesDialog.cs index 7643d51a..a85a2a0b 100644 --- a/src/UI/Windows/ChoicesDialog.cs +++ b/src/UI/Windows/ChoicesDialog.cs @@ -24,6 +24,8 @@ namespace TerminalGuiDesigner.UI.Windows; /// public partial class ChoicesDialog { + private readonly IApplication app; + /// /// The index of the button user clicked (starting at 0). /// @@ -32,16 +34,18 @@ public partial class ChoicesDialog private string _title; /// - /// + /// /// + /// The application instance. /// /// /// /// - public ChoicesDialog(string title, string message, params string[] options) { - + public ChoicesDialog(IApplication app, string title, string message, params string[] options) { + const int defaultWidth = 50; + this.app = app; InitializeComponent(); if (options.Length == 0 || options.Length > 4) @@ -64,7 +68,7 @@ public ChoicesDialog(string title, string message, params string[] options) { buttons[i].Accepting += (s,e) => { Result = i2; e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; } @@ -104,16 +108,16 @@ public ChoicesDialog(string title, string message, params string[] options) { btn1.FocusDeepest(NavigationDirection.Forward, TabBehavior.TabGroup); } - internal static int Query(string title, string message, params string[] options) + internal static int Query(IApplication app, string title, string message, params string[] options) { - var dlg = new ChoicesDialog(title, message, options); - Application.Run(dlg); + var dlg = new ChoicesDialog(app, title, message, options); + app.Run(dlg); return dlg.Result; } - internal static bool Confirm(string title, string message, string okText = "Yes", string cancelText = "No") + internal static bool Confirm(IApplication app, string title, string message, string okText = "Yes", string cancelText = "No") { - var dlg = new ChoicesDialog(title, message, okText, cancelText); - Application.Run(dlg); + var dlg = new ChoicesDialog(app, title, message, okText, cancelText); + app.Run(dlg); return dlg.Result == 0; } } diff --git a/src/UI/Windows/DimEditor.cs b/src/UI/Windows/DimEditor.cs index 1309d0db..0f4918e9 100644 --- a/src/UI/Windows/DimEditor.cs +++ b/src/UI/Windows/DimEditor.cs @@ -25,6 +25,7 @@ namespace TerminalGuiDesigner.UI.Windows; /// public partial class DimEditor : Dialog, IValueGetterDialog { + private readonly IApplication app; private Design design; /// @@ -42,11 +43,13 @@ public partial class DimEditor : Dialog, IValueGetterDialog /// /// Creates a new instance of the class. /// + /// The application instance. /// /// Old value (if editing an existing instance) - public DimEditor(Design design, Dim oldValue) { + public DimEditor(IApplication app, Design design, Dim oldValue) { InitializeComponent(); - + + this.app = app; this.design = design; @@ -151,7 +154,7 @@ private void BtnCancel_Clicked(object sender, CommandEventArgs e) { e.Handled = true; Cancelled = true; - Application.RequestStop(); + app.RequestStop(); } private void BtnOk_Clicked(object sender, CommandEventArgs e) @@ -159,7 +162,7 @@ private void BtnOk_Clicked(object sender, CommandEventArgs e) e.Handled = true; Cancelled = false; Result = BuildResult(); - Application.RequestStop(); + app.RequestStop(); } private Dim BuildResult() diff --git a/src/UI/Windows/EditDialog.cs b/src/UI/Windows/EditDialog.cs index 52d5f214..6ba4ee47 100644 --- a/src/UI/Windows/EditDialog.cs +++ b/src/UI/Windows/EditDialog.cs @@ -76,7 +76,7 @@ public EditDialog(IApplication app, Design design) btnClose.Accepting += (s, e) => { e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; this.list.KeyDown += (s, e) => @@ -150,7 +150,7 @@ private void List_KeyPress(object? sender, Key obj) // TODO: Should really be using the _keyMap here if (obj == Key.DeleteChar) { - int rly = ChoicesDialog.Query("Clear", "Clear Property Value?", "Yes", "Cancel"); + int rly = ChoicesDialog.Query(app, "Clear", "Clear Property Value?", "Yes", "Cancel"); obj.Handled = true; if (rly == 0) diff --git a/src/UI/Windows/ExceptionViewer.cs b/src/UI/Windows/ExceptionViewer.cs index f1c7ebc1..01b536a4 100644 --- a/src/UI/Windows/ExceptionViewer.cs +++ b/src/UI/Windows/ExceptionViewer.cs @@ -45,7 +45,7 @@ public static void ShowException(IApplication app, string errorText, Exception e btnOk.Accepting += (s, e) => { e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; var btnStack = new Button() { @@ -71,7 +71,7 @@ public static void ShowException(IApplication app, string errorText, Exception e }; dlg.Add(textView); - Application.Run(dlg); + app.Run(dlg); } private static string GetExceptionText(string errorText, Exception exception, bool includeStackTrace) diff --git a/src/UI/Windows/GetTextDialog.cs b/src/UI/Windows/GetTextDialog.cs index 478662b0..6fcc17fb 100644 --- a/src/UI/Windows/GetTextDialog.cs +++ b/src/UI/Windows/GetTextDialog.cs @@ -11,6 +11,7 @@ namespace TerminalGuiDesigner.UI.Windows; /// internal class GetTextDialog { + private readonly IApplication app; private readonly DialogArgs args; private readonly string? initialValue; private readonly Window win; @@ -19,8 +20,9 @@ internal class GetTextDialog private static CheckState lastKnownEnableNewlines = CheckState.UnChecked; private bool? multiLineChecked; - public GetTextDialog(DialogArgs args, string? initialValue) + public GetTextDialog(IApplication app, DialogArgs args, string? initialValue) { + this.app = app; this.args = args; this.initialValue = initialValue; @@ -101,7 +103,7 @@ public GetTextDialog(DialogArgs args, string? initialValue) { e.Handled = true; this.okClicked = false; - Application.RequestStop(); + app.RequestStop(); }; var btnClear = new Button() @@ -166,7 +168,7 @@ private void SetEnableNewlines(CheckState newValue) public bool ShowDialog() { - Application.Run(this.win); + app.Run(this.win); return this.okClicked; } @@ -175,7 +177,7 @@ private void Accept() { this.okClicked = true; this.ResultText = this.textView.Text.ToString(); - Application.RequestStop(); + app.RequestStop(); } private void TextViewKeyPress(object? sender, Key key) diff --git a/src/UI/Windows/KeyBindingsUI.cs b/src/UI/Windows/KeyBindingsUI.cs index 2d45afa8..693a5954 100644 --- a/src/UI/Windows/KeyBindingsUI.cs +++ b/src/UI/Windows/KeyBindingsUI.cs @@ -18,14 +18,16 @@ namespace TerminalGuiDesigner.UI.Windows { using Terminal.Gui; - + public partial class KeyBindingsUI { + private readonly IApplication app; private readonly KeyMap keyMap; private readonly PropertyInfo[] _props; public bool Save { get; set; } = false; - public KeyBindingsUI(KeyMap keyMap) { + public KeyBindingsUI(IApplication app, KeyMap keyMap) { + this.app = app; this.keyMap = keyMap; InitializeComponent(); @@ -61,7 +63,7 @@ public KeyBindingsUI(KeyMap keyMap) { tableView.CellActivated += (s, e) => { var prop = _props[e.Row]; - var k = Modals.GetShortcut(); + var k = Modals.GetShortcut(app); prop.SetValue(this.keyMap,k.ToString()); this.SetNeedsDraw(); }; @@ -80,12 +82,12 @@ public KeyBindingsUI(KeyMap keyMap) { { Save = true; e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; btnCancel.Accepting += (s, e) => { e.Handled = true; - Application.RequestStop(); + app.RequestStop(); }; } diff --git a/src/UI/Windows/Modals.cs b/src/UI/Windows/Modals.cs index a36ca214..d7116e21 100644 --- a/src/UI/Windows/Modals.cs +++ b/src/UI/Windows/Modals.cs @@ -17,14 +17,15 @@ public class Modals /// /// Prompts user to enter a number. /// + /// The application instance. /// Title for the pop-up. /// Text to show next to the entry field. /// Initial value to put into the entry field. /// Output value user typed. /// True if user confirmed a choice. - public static bool GetInt(string windowTitle, string entryLabel, int? initialValue, out int? result) + public static bool GetInt(IApplication app, string windowTitle, string entryLabel, int? initialValue, out int? result) { - if (GetString(windowTitle, entryLabel, initialValue.ToString(), out var newValue)) + if (GetString(app, windowTitle, entryLabel, initialValue.ToString(), out var newValue)) { if (string.IsNullOrWhiteSpace(newValue)) { @@ -43,9 +44,10 @@ public static bool GetInt(string windowTitle, string entryLabel, int? initialVal return false; } - internal static bool GetArray(string windowTitle, string entryLabel, Type arrayElement, Array? initialValue, out Array? result) + internal static bool GetArray(IApplication app, string windowTitle, string entryLabel, Type arrayElement, Array? initialValue, out Array? result) { var dlg = new GetTextDialog( + app, new DialogArgs() { WindowTitle = windowTitle, @@ -81,9 +83,10 @@ internal static bool GetArray(string windowTitle, string entryLabel, Type arrayE return false; } - internal static bool TryGetArray(string windowTitle, string entryLabel, Array? initialValue, out Array? result) + internal static bool TryGetArray(IApplication app, string windowTitle, string entryLabel, Array? initialValue, out Array? result) { var dlg = new GetTextDialog( + app, new () { WindowTitle = windowTitle, @@ -119,9 +122,10 @@ internal static bool TryGetArray(string windowTitle, string entryLabel, Array return false; } - internal static bool GetString(string windowTitle, string entryLabel, string? initialValue, out string? result, bool multiLine = false) + internal static bool GetString(IApplication app, string windowTitle, string entryLabel, string? initialValue, out string? result, bool multiLine = false) { var dlg = new GetTextDialog( + app, new DialogArgs() { WindowTitle = windowTitle, @@ -140,27 +144,27 @@ internal static bool GetString(string windowTitle, string entryLabel, string? in return false; } - internal static bool Get(string prompt, string okText, T[] collection, T? currentSelection, out T? selected, bool sort = true) + internal static bool Get(IApplication app, string prompt, string okText, T[] collection, T? currentSelection, out T? selected, bool sort = true) { - return Get(prompt, okText, true, collection, o => o is Type t ? t.Name : o?.ToString() ?? "Null", false, currentSelection, out selected,sort); + return Get(app, prompt, okText, true, collection, o => o is Type t ? t.Name : o?.ToString() ?? "Null", false, currentSelection, out selected,sort); } - internal static bool Get( string prompt, string okText, in bool addSearch, T[] collection, Func displayMember, bool addNull, [NotNullWhen( true )]T? currentSelection, [NotNullWhen( true )] out T? selected, bool sort=true ) + internal static bool Get(IApplication app, string prompt, string okText, in bool addSearch, T[] collection, Func displayMember, bool addNull, [NotNullWhen( true )]T? currentSelection, [NotNullWhen( true )] out T? selected, bool sort=true ) { - var pick = new BigListBox( prompt, okText, in addSearch, collection, displayMember, addNull, currentSelection,sort ); + var pick = new BigListBox(app, prompt, okText, in addSearch, collection, displayMember, addNull, currentSelection,sort ); bool toReturn = pick.ShowDialog( ); selected = pick.Selected; return toReturn; } - internal static bool GetEnum(string prompt, string okText, Type enumType, Enum? currentValue, out Enum? result) + internal static bool GetEnum(IApplication app, string prompt, string okText, Type enumType, Enum? currentValue, out Enum? result) { - return Get(prompt, okText, true, Enum.GetValues(enumType).Cast().ToArray(), o => o?.ToString() ?? "Null", false, currentValue, out result); + return Get(app, prompt, okText, true, Enum.GetValues(enumType).Cast().ToArray(), o => o?.ToString() ?? "Null", false, currentValue, out result); } - internal static bool GetChar(string windowTitle, string entryLabel, char? oldValue, out char? resultChar) + internal static bool GetChar(IApplication app, string windowTitle, string entryLabel, char? oldValue, out char? resultChar) { - if (GetString(windowTitle, entryLabel, oldValue?.ToString() ?? string.Empty, out var result)) + if (GetString(app, windowTitle, entryLabel, oldValue?.ToString() ?? string.Empty, out var result)) { if (result == null || result.Length == 0) { @@ -179,7 +183,7 @@ internal static bool GetChar(string windowTitle, string entryLabel, char? oldVal return false; } - internal static Key GetShortcut() + internal static Key GetShortcut(IApplication app) { Key key = KeyCode.Null; var dlg = new LoadingDialog("Press Shortcut or Del"); @@ -189,10 +193,10 @@ internal static Key GetShortcut() { key = e; key.Handled = true; - Application.RequestStop(); + app.RequestStop(); } }; - Application.Run(dlg); + app.Run(dlg); return key == Key.DeleteChar ? KeyCode.Null : key; } diff --git a/src/UI/Windows/PointEditor.cs b/src/UI/Windows/PointEditor.cs index 33fc0d36..d85edf84 100644 --- a/src/UI/Windows/PointEditor.cs +++ b/src/UI/Windows/PointEditor.cs @@ -22,6 +22,8 @@ namespace TerminalGuiDesigner; /// public partial class PointEditor : IValueGetterDialog { + private readonly IApplication app; + /// /// Gets a value indicating whether user cancelled the dialog before /// making a choice. @@ -43,11 +45,13 @@ public partial class PointEditor : IValueGetterDialog { /// /// Creates a new instance of the class. /// + /// The application instance. /// Initial value to show in dialog for X. /// Initial value to show in dialog for Y. - public PointEditor(float x, float y) { + public PointEditor(IApplication app, float x, float y) { InitializeComponent(); + this.app = app; tbX.Text = x.ToString(); tbY.Text = y.ToString(); @@ -59,7 +63,7 @@ private void Cancel(object sender, CommandEventArgs e) { e.Handled = true; Cancelled = true; - Application.RequestStop(); + app.RequestStop(); } private void Ok(object sender, CommandEventArgs e) @@ -73,7 +77,7 @@ private void Ok(object sender, CommandEventArgs e) ResultY = y; Cancelled = false; - Application.RequestStop(); + app.RequestStop(); } else { diff --git a/src/UI/Windows/PosEditor.cs b/src/UI/Windows/PosEditor.cs index 374e0d0e..ee22e7e9 100644 --- a/src/UI/Windows/PosEditor.cs +++ b/src/UI/Windows/PosEditor.cs @@ -27,6 +27,7 @@ namespace TerminalGuiDesigner.UI.Windows; /// public partial class PosEditor : Dialog, IValueGetterDialog { + private readonly IApplication app; private Design design; private readonly Dictionary _siblings; @@ -46,11 +47,13 @@ public partial class PosEditor : Dialog, IValueGetterDialog { /// Prompt user to create a new value to populate /// on with. /// + /// The application instance. /// What to set the value on. /// The current value for the property. - public PosEditor(Design design, Pos oldValue) { + public PosEditor(IApplication app, Design design, Pos oldValue) { InitializeComponent(); - + + this.app = app; this.design = design; Title = "Pos Designer"; @@ -209,7 +212,7 @@ private void BtnCancel_Clicked(object sender, CommandEventArgs e) { e.Handled = true; Cancelled = true; - Application.RequestStop(); + app.RequestStop(); } private void BtnOk_Clicked(object sender, CommandEventArgs e) @@ -217,15 +220,15 @@ private void BtnOk_Clicked(object sender, CommandEventArgs e) e.Handled = true; if(GetPosType() == PosType.AnchorEnd && GetValue(out var value) && value <=0) { - if (!ChoicesDialog.Confirm("Anchor Without Margin", "Using AnchorEnd without a margin will result in a point outside of parent bounds.\nAre you sure?")) + if (!ChoicesDialog.Confirm(app, "Anchor Without Margin", "Using AnchorEnd without a margin will result in a point outside of parent bounds.\nAre you sure?")) { return; - } + } } Cancelled = !BuildPos(out var result); Result = result; - Application.RequestStop(); + app.RequestStop(); } private bool BuildPos(out Pos result) From b283a639be4d6abafba2e4d5cb810d08dccac907 Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 03:41:21 +0000 Subject: [PATCH 008/101] Switch to app instance --- src/DesignState.cs | 2 +- src/Operations/AddViewOperation.cs | 2 +- src/UI/Editor.cs | 10 +++++----- src/UI/Windows/BigListBox.cs | 4 ++-- src/UI/Windows/ChoicesDialog.cs | 14 +++++++------- src/ViewExtensions.cs | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/DesignState.cs b/src/DesignState.cs index 6eb8dbfc..53350b69 100644 --- a/src/DesignState.cs +++ b/src/DesignState.cs @@ -72,7 +72,7 @@ private void DrawBorderlessViewFrame(Rectangle r) SelectionManager.Instance.SelectedScheme.Normal : this.Design.View.GetScheme().Normal; - Application.Driver.SetAttribute(color); + Application.Instance!.Driver.SetAttribute(color); var v = this.Design.View; diff --git a/src/Operations/AddViewOperation.cs b/src/Operations/AddViewOperation.cs index 4cdc16f2..5edc4eb0 100644 --- a/src/Operations/AddViewOperation.cs +++ b/src/Operations/AddViewOperation.cs @@ -132,7 +132,7 @@ protected override bool DoImpl() var v = this.GetViewToAddTo(); v.Add(this.add); - if (Application.Driver != null) + if (App?.Driver != null) { this.add.SetFocus(); } diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 5764290a..fefccffd 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -1284,11 +1284,11 @@ private void Open(FileInfo toOpen) (t, _) => { // no longer loading - Application.Invoke(() => app.RequestStop()); + app.Invoke(() => app.RequestStop()); if (t.Exception != null) { - Application.Invoke(() => + app.Invoke(() => ExceptionViewer.ShowException(app, $"Failed to open '{toOpen.Name}'", t.Exception)); return; } @@ -1422,11 +1422,11 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) (t, _) => { // no longer loading - Application.Invoke(() => app.RequestStop()); + app.Invoke(() => app.RequestStop()); if (t.Exception != null) { - Application.Invoke(() => + app.Invoke(() => ExceptionViewer.ShowException(app, $"Failed to create '{toOpen.Name}'", t.Exception)); return; } @@ -1444,7 +1444,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) private void ReplaceViewBeingEdited(Design design) { - Application.Invoke(() => + app.Invoke(() => { // remove the old view if (this.viewBeingEdited != null) diff --git a/src/UI/Windows/BigListBox.cs b/src/UI/Windows/BigListBox.cs index a76ae5fc..3c78580c 100644 --- a/src/UI/Windows/BigListBox.cs +++ b/src/UI/Windows/BigListBox.cs @@ -179,7 +179,7 @@ public BigListBox(IApplication app, this.listView.SelectedItem = 0; } - this.callback = Application.AddTimeout(TimeSpan.FromMilliseconds(100), this.Timer); + this.callback = app.AddTimeout(TimeSpan.FromMilliseconds(100), this.Timer); this.listView.FocusDeepest(NavigationDirection.Forward,TabBehavior.TabStop); } @@ -203,7 +203,7 @@ public bool ShowDialog() { app.Run(this.win); - Application.RemoveTimeout(this.callback); + app.RemoveTimeout(this.callback); return this.okClicked; } diff --git a/src/UI/Windows/ChoicesDialog.cs b/src/UI/Windows/ChoicesDialog.cs index a85a2a0b..bf3917f9 100644 --- a/src/UI/Windows/ChoicesDialog.cs +++ b/src/UI/Windows/ChoicesDialog.cs @@ -90,19 +90,19 @@ public ChoicesDialog(IApplication app, string title, string message, params stri buttonPanel.Width = buttonWidth = buttons.Sum(b=>buttonPanel.SubViews.Contains(b) ? b.Frame.Width : 0) + 1; int maxWidthLine = TextFormatter.GetSumMaxCharWidth(message); - if (maxWidthLine > Application.Driver.Cols) + if (maxWidthLine > app.Driver.Cols) { - maxWidthLine = Application.Driver.Cols; + maxWidthLine = app.Driver.Cols; } - + maxWidthLine = Math.Max(maxWidthLine, defaultWidth); - - int textWidth = Math.Min(TextFormatter.GetSumMaxCharWidth(message, maxWidthLine), Application.Driver.Cols); + + int textWidth = Math.Min(TextFormatter.GetSumMaxCharWidth(message, maxWidthLine), app.Driver.Cols); int textHeight = message.Count (c=>c=='\n') + 4; - int msgboxHeight = Math.Min(Math.Max(1, textHeight) + 4, Application.Driver.Rows); // textHeight + (top + top padding + buttons + bottom) + int msgboxHeight = Math.Min(Math.Max(1, textHeight) + 4, app.Driver.Rows); // textHeight + (top + top padding + buttons + bottom) - Width = Math.Min(Math.Max(maxWidthLine, Math.Max(Title.GetColumns(), Math.Max(textWidth + 2, buttonWidth))), Application.Driver.Cols); + Width = Math.Min(Math.Max(maxWidthLine, Math.Max(Title.GetColumns(), Math.Max(textWidth + 2, buttonWidth))), app.Driver.Cols); Height = msgboxHeight; btn1.FocusDeepest(NavigationDirection.Forward, TabBehavior.TabGroup); diff --git a/src/ViewExtensions.cs b/src/ViewExtensions.cs index 987f7439..2c8027d5 100644 --- a/src/ViewExtensions.cs +++ b/src/ViewExtensions.cs @@ -15,7 +15,7 @@ public static class ViewExtensions { public static View? FindDeepestView(Point screenPoint) { - return View.GetViewsAtLocation(Application.Instance.TopRunnableView, screenPoint).LastOrDefault(v=> v!= null); + return View.GetViewsAtLocation(Application.Instance!.TopRunnableView, screenPoint).LastOrDefault(v=> v!= null); } /// /// Returns the sub-views of skipping out any From b0bbccffd83dee353e988378cb645b8093c69b4e Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 08:08:08 +0000 Subject: [PATCH 009/101] remove app instance references --- src/Design.cs | 6 ++++-- src/DesignState.cs | 11 +++++++++-- src/UI/Editor.cs | 4 ++-- src/UI/MouseManager.cs | 10 ++++++++-- src/ViewExtensions.cs | 11 ++++++----- 5 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/Design.cs b/src/Design.cs index 491de39b..83efec06 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -5,6 +5,7 @@ using System.Xml.Linq; using NLog; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Configuration; using Terminal.Gui.Drawing; using Terminal.Gui.Input; @@ -60,14 +61,15 @@ public class Design /// The private instance name to use for when writing it out /// to or if . /// The view to wrap. - public Design(SourceCodeFile sourceCode, string fieldName, View view) + /// Optional application instance. If provided, enables UI features like drawing borders. + public Design(SourceCodeFile sourceCode, string fieldName, View view, IApplication? app = null) { this.View = view; this.SourceCode = sourceCode; this.FieldName = fieldName; this.designableProperties = new List(this.LoadDesignableProperties()); - this.State = new DesignState(this); + this.State = new DesignState(app, this); } /// diff --git a/src/DesignState.cs b/src/DesignState.cs index 53350b69..8dccf3e7 100644 --- a/src/DesignState.cs +++ b/src/DesignState.cs @@ -13,16 +13,20 @@ namespace TerminalGuiDesigner; /// public class DesignState { + private readonly IApplication? app; + /// /// Initializes a new instance of the class. Registers /// events on the that track entering, redrawing etc /// as well as capturing initial state e.g. . /// + /// The application instance (can be null for non-UI scenarios). /// The parent that this class will hold state for. You /// should set it's property to the new instance. /// - public DesignState(Design design) + public DesignState(IApplication? app, Design design) { + this.app = app; this.Design = design; this.Design.View.DrawComplete += this.DrawContentComplete; this.Design.View.HasFocusChanged += this.Enter; @@ -72,7 +76,10 @@ private void DrawBorderlessViewFrame(Rectangle r) SelectionManager.Instance.SelectedScheme.Normal : this.Design.View.GetScheme().Normal; - Application.Instance!.Driver.SetAttribute(color); + if (app != null) + { + app.Driver.SetAttribute(color); + } var v = this.Design.View; diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index fefccffd..4158090d 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -83,7 +83,7 @@ public Editor(IApplication app) LoadKeyMap(); this.keyboardManager = new KeyboardManager(app, this.keyMap); - this.mouseManager = new MouseManager() + this.mouseManager = new MouseManager(app) { ErrorReporter = this }; @@ -258,7 +258,7 @@ public void Run(Options options) // right click if (m.Flags.HasFlag(this.keyMap.RightClick)) { - var hit = this.viewBeingEdited.View.HitTest(m, out _, out _); + var hit = this.viewBeingEdited.View.HitTest(app, m, out _, out _); if (hit != null) { diff --git a/src/UI/MouseManager.cs b/src/UI/MouseManager.cs index 8c7fefb7..b2ff8b85 100644 --- a/src/UI/MouseManager.cs +++ b/src/UI/MouseManager.cs @@ -12,6 +12,7 @@ namespace TerminalGuiDesigner.UI; /// public class MouseManager { + private readonly IApplication app; private DragOperation? dragOperation = null; private ResizeOperation? resizeOperation = null; @@ -22,6 +23,11 @@ public class MouseManager private Point? selectionStart = null; private Point? selectionEnd = null; + public MouseManager(IApplication app) + { + this.app = app; + } + /// /// Gets the container that 'drag a box' selection is occurring in (if any). /// See also . @@ -51,7 +57,7 @@ public void HandleMouse(MouseEventArgs m, Design viewBeingEdited) if (m.Flags.HasFlag(MouseFlags.Button1Pressed) && this.resizeOperation == null && this.dragOperation == null && this.selectionStart == null) { - View? drag = viewBeingEdited.View.HitTest(m, out bool isBorder, out bool isLowerRight); + View? drag = viewBeingEdited.View.HitTest(app, m, out bool isBorder, out bool isLowerRight); // if user is ctrl+click if (m.Flags.HasFlag(MouseFlags.ButtonCtrl) && drag != null) @@ -189,7 +195,7 @@ public void HandleMouse(MouseEventArgs m, Design viewBeingEdited) if (this.dragOperation != null) { // see if we are dragging into a new container - var dropInto = viewBeingEdited.View.HitTest(m, out _, out _, this.dragOperation.BeingDragged.View); + var dropInto = viewBeingEdited.View.HitTest(app, m, out _, out _, this.dragOperation.BeingDragged.View); // TODO: this is quite hacky workaround for dropping on things like TabView top row. Need // a better solution to this. diff --git a/src/ViewExtensions.cs b/src/ViewExtensions.cs index 2c8027d5..161118a7 100644 --- a/src/ViewExtensions.cs +++ b/src/ViewExtensions.cs @@ -13,9 +13,9 @@ namespace TerminalGuiDesigner; /// public static class ViewExtensions { - public static View? FindDeepestView(Point screenPoint) + public static View? FindDeepestView(IApplication app, Point screenPoint) { - return View.GetViewsAtLocation(Application.Instance!.TopRunnableView, screenPoint).LastOrDefault(v=> v!= null); + return View.GetViewsAtLocation(app.TopRunnableView, screenPoint).LastOrDefault(v=> v!= null); } /// /// Returns the sub-views of skipping out any @@ -245,17 +245,18 @@ public static bool IsBorderlessContainerView(this View v) /// Screen coordinates. /// True if the click lands on the border of the returned . /// True if the click lands in the lower right of the returned . + /// The application instance. /// One or more to ignore (click through) when performing the hit test. /// The at the given screen location or null if none found. - public static View? HitTest(this View w, MouseEventArgs m, out bool isBorder, out bool isLowerRight, params View[] ignoring) + public static View? HitTest(this View w, IApplication app, MouseEventArgs m, out bool isBorder, out bool isLowerRight, params View[] ignoring) { // hide the views while we perform the hit test foreach (View v in ignoring) { v.Visible = false; } - - var hit = ViewExtensions.FindDeepestView(m.Position); + + var hit = ViewExtensions.FindDeepestView(app, m.Position); hit = UnpackHitView(hit); From 47f8d32eeae2a3b56cbef4200152bb104afff68e Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 11:04:02 +0000 Subject: [PATCH 010/101] Add app as parameter, see https://github.com/gui-cs/Terminal.Gui/issues/4489 --- src/UI/Editor.cs | 5 ++--- src/UI/ValueFactory.cs | 2 +- src/UI/Windows/PointEditor.cs | 4 ++-- src/UI/Windows/SizeEditor.cs | 11 +++++++---- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 4158090d..a9c98148 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -207,7 +207,7 @@ public void Run(Options options) } catch (Exception ex) { - MessageBox.ErrorQuery(null, "Error Loading Designer", ex.Message, "Ok"); + MessageBox.ErrorQuery(app, "Error Loading Designer", ex.Message, "Ok"); return; } } @@ -1400,8 +1400,7 @@ private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) // Validate the namespace if (string.IsNullOrWhiteSpace(ns) || ns.Contains(' ') || char.IsDigit(ns.First())) { - // TODO: app should be null? - MessageBox.ErrorQuery(null, "Invalid Namespace", "Namespace must not contain spaces, be empty or begin with a number", "Ok"); + MessageBox.ErrorQuery(app, "Invalid Namespace", "Namespace must not contain spaces, be empty or begin with a number", "Ok"); return; } diff --git a/src/UI/ValueFactory.cs b/src/UI/ValueFactory.cs index 76b51c83..5bf9b146 100644 --- a/src/UI/ValueFactory.cs +++ b/src/UI/ValueFactory.cs @@ -61,7 +61,7 @@ internal static bool GetNewValue(IApplication app, string propertyName, Design d } if (type == typeof(Size)) { - return RunEditor(app, new SizeEditor((Size)(oldValue ?? throw new Exception($"Property {propertyName} is of Type Size but its current value is null"))), out newValue); + return RunEditor(app, new SizeEditor(app, (Size)(oldValue ?? throw new Exception($"Property {propertyName} is of Type Size but its current value is null"))), out newValue); } if (type == typeof(Point)) { diff --git a/src/UI/Windows/PointEditor.cs b/src/UI/Windows/PointEditor.cs index d85edf84..796229f4 100644 --- a/src/UI/Windows/PointEditor.cs +++ b/src/UI/Windows/PointEditor.cs @@ -81,12 +81,12 @@ private void Ok(object sender, CommandEventArgs e) } else { - MessageBox.ErrorQuery(null, 20,5,"Could no parse",$"Could not parse '{tbY.Text}'","Ok"); + MessageBox.ErrorQuery(app, 20,5,"Could no parse",$"Could not parse '{tbY.Text}'","Ok"); } } else { - MessageBox.ErrorQuery(null,20,5,"Could no parse",$"Could not parse '{tbX.Text}'","Ok"); + MessageBox.ErrorQuery(app,20,5,"Could no parse",$"Could not parse '{tbX.Text}'","Ok"); } } } diff --git a/src/UI/Windows/SizeEditor.cs b/src/UI/Windows/SizeEditor.cs index d7e53e30..d45cef56 100644 --- a/src/UI/Windows/SizeEditor.cs +++ b/src/UI/Windows/SizeEditor.cs @@ -13,16 +13,17 @@ namespace TerminalGuiDesigner.UI.Windows; using Terminal.Gui; +using Terminal.Gui.App; /// /// Popup editor for the class. /// public partial class SizeEditor : IValueGetterDialog { - + private readonly IApplication app; /// - /// The users edited + /// The users edited /// public object? Result { get; private set; } @@ -34,9 +35,11 @@ public partial class SizeEditor : IValueGetterDialog /// /// Creates a new instance of the class. /// + /// The application instance. /// - public SizeEditor(Size s) + public SizeEditor(IApplication app, Size s) { + this.app = app; InitializeComponent(); Result = s; @@ -52,7 +55,7 @@ public SizeEditor(Size s) } catch (Exception ex) { - MessageBox.ErrorQuery(null, "Bad Value", ex.Message); + MessageBox.ErrorQuery(app, "Bad Value", ex.Message); return; } From d75fc5302512b458145974cfb5681369e3067f0d Mon Sep 17 00:00:00 2001 From: tznind Date: Sun, 14 Dec 2025 11:22:59 +0000 Subject: [PATCH 011/101] Handle the renaming of Toplevel to Runnable better --- src/Design.cs | 5 +++-- src/UI/Editor.cs | 2 +- src/ViewExtensions.cs | 5 +++++ src/ViewFactory.cs | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Design.cs b/src/Design.cs index 83efec06..b3f51bd0 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -51,7 +51,8 @@ public class Design typeof(TabView), typeof(TreeView), typeof(Dialog), - typeof(NumericUpDown) + typeof(NumericUpDown), + typeof(Runnable) }; /// @@ -658,7 +659,7 @@ private IEnumerable LoadDesignableProperties() yield return this.CreateProperty(nameof(TextView.AllowsReturn)); yield return this.CreateProperty(nameof(TextView.WordWrap)); } - + // Allow changing the FieldName on anything but root where // such an action would break things badly if (!this.IsRoot) diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index a9c98148..51c92031 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -1377,7 +1377,7 @@ private void New() private static Type[] GetSupportedRootViews() { - return new Type[] { typeof(Window), typeof(Dialog), typeof(View) }; + return new Type[] { typeof(Window), typeof(Dialog), typeof(View), typeof(Runnable) }; } private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) diff --git a/src/ViewExtensions.cs b/src/ViewExtensions.cs index 161118a7..2b816e32 100644 --- a/src/ViewExtensions.cs +++ b/src/ViewExtensions.cs @@ -219,6 +219,11 @@ v is Window || /// True if no visible border and . public static bool IsBorderlessContainerView(this View v) { + if (v is Runnable) + { + return false; + } + if (v is TabView tabView) { return !tabView.Style.ShowBorder || tabView.Style.TabsOnBottom; diff --git a/src/ViewFactory.cs b/src/ViewFactory.cs index 40c8b040..ac00ba48 100644 --- a/src/ViewFactory.cs +++ b/src/ViewFactory.cs @@ -33,6 +33,7 @@ public static class ViewFactory internal static readonly Type[] KnownUnsupportedTypes = [ + typeof( Runnable ), typeof( Dialog ), typeof( FileDialog ), typeof( SaveDialog ), From 0bbae9021acd70e1afce564f12631a8dea73ddab Mon Sep 17 00:00:00 2001 From: tznind Date: Mon, 15 Dec 2025 00:46:41 +0000 Subject: [PATCH 012/101] Workaround for https://github.com/gui-cs/Terminal.Gui/issues/4488 --- src/UI/Editor.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 51c92031..e593f186 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -1028,8 +1028,10 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) m.Handled = true; } - - // TODO: rly? you have to pass it its own menu items!? + // This internal method call shouldn't be required + menu.App = app; + app.Popover!.Register(menu); + menu.MakeVisible(position); menu.Accepted += (_, _) => { From 19d4112b42b6e67448836945e607355d1b0a885d Mon Sep 17 00:00:00 2001 From: tznind Date: Mon, 15 Dec 2025 01:07:53 +0000 Subject: [PATCH 013/101] WIP add app for more people --- src/Design.cs | 15 +++++++++------ src/DesignState.cs | 11 ++--------- src/FromCode/CodeToView.cs | 9 +++++++-- src/Operations/AddViewOperation.cs | 16 ++-------------- src/Operations/CompositeOperation.cs | 3 ++- src/Operations/Operation.cs | 8 +++++++- src/Operations/PasteOperation.cs | 2 +- src/UI/Editor.cs | 9 +++------ 8 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/Design.cs b/src/Design.cs index b3f51bd0..3a362b8e 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -33,6 +33,8 @@ public class Design private readonly List designableProperties; private readonly Logger logger = LogManager.GetCurrentClassLogger(); + public IApplication App { get; } + /// /// View Types for which does not make sense as a user /// configurable field (e.g. there is a Title field instead). @@ -62,15 +64,16 @@ public class Design /// The private instance name to use for when writing it out /// to or if . /// The view to wrap. - /// Optional application instance. If provided, enables UI features like drawing borders. - public Design(SourceCodeFile sourceCode, string fieldName, View view, IApplication? app = null) + /// Application instance + public Design(IApplication app, SourceCodeFile sourceCode, string fieldName, View view) { + App = app; this.View = view; this.SourceCode = sourceCode; this.FieldName = fieldName; this.designableProperties = new List(this.LoadDesignableProperties()); - this.State = new DesignState(app, this); + this.State = new DesignState(this); } /// @@ -257,7 +260,7 @@ public Design CreateSubControlDesign(string name, View subView) v.MouseEvent += (s, e) => this.SuppressNativeClickEvents(s, e, true); } - var d = new Design(this.SourceCode, name, subView); + var d = new Design(App, this.SourceCode, name, subView); return d; } @@ -330,7 +333,7 @@ public IEnumerable GetExtraOperations(Point pos) if (this.IsContainerView || this.IsRoot) { - yield return new AddViewOperation(this); + yield return new AddViewOperation(App,this); yield return new PasteOperation(this); } else @@ -338,7 +341,7 @@ public IEnumerable GetExtraOperations(Point pos) var nearestContainer = this.View.GetNearestContainerDesign(); if (nearestContainer != null) { - yield return new AddViewOperation(nearestContainer); + yield return new AddViewOperation(App, nearestContainer); } } diff --git a/src/DesignState.cs b/src/DesignState.cs index 8dccf3e7..97ac7631 100644 --- a/src/DesignState.cs +++ b/src/DesignState.cs @@ -13,20 +13,16 @@ namespace TerminalGuiDesigner; /// public class DesignState { - private readonly IApplication? app; - /// /// Initializes a new instance of the class. Registers /// events on the that track entering, redrawing etc /// as well as capturing initial state e.g. . /// - /// The application instance (can be null for non-UI scenarios). /// The parent that this class will hold state for. You /// should set it's property to the new instance. /// - public DesignState(IApplication? app, Design design) + public DesignState(Design design) { - this.app = app; this.Design = design; this.Design.View.DrawComplete += this.DrawContentComplete; this.Design.View.HasFocusChanged += this.Enter; @@ -76,10 +72,7 @@ private void DrawBorderlessViewFrame(Rectangle r) SelectionManager.Instance.SelectedScheme.Normal : this.Design.View.GetScheme().Normal; - if (app != null) - { - app.Driver.SetAttribute(color); - } + Design.App.Driver!.SetAttribute(color); var v = this.Design.View; diff --git a/src/FromCode/CodeToView.cs b/src/FromCode/CodeToView.cs index 08e2cfc4..06ea2db0 100644 --- a/src/FromCode/CodeToView.cs +++ b/src/FromCode/CodeToView.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.Emit; using NLog; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using TerminalGuiDesigner.ToCode; @@ -28,14 +29,18 @@ namespace TerminalGuiDesigner.FromCode; /// public class CodeToView { + private readonly IApplication app; + /// /// Initializes a new instance of the class. Opens the provided /// and extracts , etc. /// + /// /// Files on disk that will be read by this class (e.g. MyView.cs and MyView.Designer.cs). /// Thrown if file cannot be parsed, does not exist or has multiple class files in it. - public CodeToView(SourceCodeFile sourceFile) + public CodeToView(IApplication app, SourceCodeFile sourceFile) { + this.app = app; this.SourceFile = sourceFile; // Parse .cs file using Roslyn SyntaxTree @@ -122,7 +127,7 @@ public Design CreateInstance() throw new Exception($"Could not create instance of {instances[0].FullName}", ex); } - var toReturn = new Design(this.SourceFile, Design.RootDesignName, view); + var toReturn = new Design(app, this.SourceFile, Design.RootDesignName, view); toReturn.CreateSubControlDesigns(); // Record the design in Data field so it can be found later by controls diff --git a/src/Operations/AddViewOperation.cs b/src/Operations/AddViewOperation.cs index 5edc4eb0..a29d4356 100644 --- a/src/Operations/AddViewOperation.cs +++ b/src/Operations/AddViewOperation.cs @@ -28,7 +28,7 @@ public class AddViewOperation : Operation /// Field name to assign to when wrapping it as a /// . This determines the private field name that it will have in the .Designer.cs /// file. - public AddViewOperation(View add, Design to, string? fieldName) + public AddViewOperation(IApplication app, View add, Design to, string? fieldName) : base(app) { this.add = add; this.fieldName = fieldName == null @@ -44,19 +44,7 @@ public AddViewOperation(View add, Design to, string? fieldName) /// The application instance. /// A (which should be ) /// to add any newly created to. - public AddViewOperation(IApplication app, Design design) - { - this.App = app; - this.to = design; - } - - /// - /// Initializes a new instance of the class. - /// This overload asks users what view type they want at runtime (See ). - /// - /// A (which should be ) - /// to add any newly created to. - public AddViewOperation(Design design) + public AddViewOperation(IApplication app, Design design):base(app) { this.to = design; } diff --git a/src/Operations/CompositeOperation.cs b/src/Operations/CompositeOperation.cs index 0c1dcb08..d35b4c05 100644 --- a/src/Operations/CompositeOperation.cs +++ b/src/Operations/CompositeOperation.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using Terminal.Gui.App; namespace TerminalGuiDesigner.Operations; @@ -24,7 +25,7 @@ public class CompositeOperation : Operation /// /// /// All operations to perform in . - public CompositeOperation(params Operation[] operations) + public CompositeOperation(IApplication app, params Operation[] operations):base(app) { this.operations = operations; diff --git a/src/Operations/Operation.cs b/src/Operations/Operation.cs index 6559d671..a8f06729 100644 --- a/src/Operations/Operation.cs +++ b/src/Operations/Operation.cs @@ -12,7 +12,7 @@ public abstract class Operation : IOperation /// /// The application instance. May be null for operations that don't need to show dialogs. /// - protected IApplication? App { get; set; } + public IApplication App { get; } /// /// The number of times the operation has been performed. @@ -48,6 +48,12 @@ public override string ToString() return this.GetOperationName(); } + protected Operation(IApplication app) + { + App = app; + + } + /// /// Returns false if or if failed. public bool Do() diff --git a/src/Operations/PasteOperation.cs b/src/Operations/PasteOperation.cs index 930c6956..8309a6aa 100644 --- a/src/Operations/PasteOperation.cs +++ b/src/Operations/PasteOperation.cs @@ -144,7 +144,7 @@ private void Paste(View copy, Design into) private bool Paste(Design copy, Design into) { var clone = ViewFactory.Create(copy.View.GetType()); - var addOperation = new AddViewOperation(clone, into, null); + var addOperation = new AddViewOperation(App, clone, into, null); // couldn't add for some reason if (!addOperation.Do()) diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index e593f186..2148a5f0 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -971,11 +971,7 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) this.ShowEditProperties(rightClicked ?? selected[0]); } }, - SubMenu = new Menu() - { - // TODO: get the menu items back - // Subitems = setPropsItems - } + SubMenu = new Menu(setPropsItems) }); } @@ -1037,9 +1033,10 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) { this.menuOpen = false; SelectionManager.Instance.LockSelection = false; + app.Popover.DeRegister(menu); }; } - + private static MenuItem ToMenuItem(IApplication application, IOperation operation) { return new MenuItem(operation.ToString(), string.Empty, () => Try(application,() => OperationManager.Instance.Do(operation))); From e7942ad81472969f07cb75f6ab038c71134d7f62 Mon Sep 17 00:00:00 2001 From: tznind Date: Mon, 15 Dec 2025 01:36:05 +0000 Subject: [PATCH 014/101] App for everyone --- src/Design.cs | 46 +++++++++---------- src/Operations/CopyOperation.cs | 5 +- src/Operations/DeleteViewOperation.cs | 4 +- src/Operations/DragOperation.cs | 4 +- src/Operations/Generics/AddOperation.cs | 5 +- .../Generics/GenericArrayElementOperation.cs | 5 +- .../Generics/GenericArrayOperation.cs | 5 +- src/Operations/Generics/GenericOperation.cs | 4 +- src/Operations/Generics/MoveOperation.cs | 5 +- src/Operations/Generics/RemoveOperation.cs | 5 +- src/Operations/Generics/RenameOperation.cs | 5 +- .../MenuOperations/AddMenuItemOperation.cs | 8 ++-- .../MenuOperations/AddMenuOperation.cs | 5 +- .../ConvertMenuItemToSeperatorOperation.cs | 6 ++- .../MenuOperations/MenuItemOperation.cs | 4 +- .../MoveMenuItemLeftOperation.cs | 10 ++-- .../MenuOperations/MoveMenuItemOperation.cs | 6 ++- .../MoveMenuItemRightOperation.cs | 10 ++-- .../MenuOperations/MoveMenuOperation.cs | 5 +- .../MenuOperations/RemoveMenuItemOperation.cs | 6 ++- .../MenuOperations/RemoveMenuOperation.cs | 5 +- .../MenuOperations/RenameMenuItemOperation.cs | 6 ++- .../MenuOperations/RenameMenuOperation.cs | 5 +- src/Operations/MoveViewOperation.cs | 4 +- src/Operations/OperationFactory.cs | 14 ++++-- src/Operations/PasteOperation.cs | 4 +- src/Operations/ResizeOperation.cs | 4 +- src/Operations/SetPropertyOperation.cs | 12 +++-- .../AddStatusItemOperation.cs | 5 +- .../MoveStatusItemOperation.cs | 5 +- .../RemoveStatusItemOperation.cs | 5 +- .../RenameStatusItemOperation.cs | 5 +- .../SetShortcutOperation.cs | 5 +- .../TabOperations/AddTabOperation.cs | 5 +- .../TabOperations/MoveTabOperation.cs | 5 +- .../TabOperations/RemoveTabOperation.cs | 5 +- .../TabOperations/RenameTabOperation.cs | 5 +- .../TableViewOperations/AddColumnOperation.cs | 5 +- .../MoveColumnOperation.cs | 5 +- .../RemoveColumnOperation.cs | 5 +- .../RenameColumnOperation.cs | 5 +- src/ToCode/TabToCode.cs | 2 +- src/ToCode/ViewToCode.cs | 17 +++++-- src/UI/Editor.cs | 16 ++++--- src/UI/KeyboardManager.cs | 18 ++++---- src/UI/MouseManager.cs | 5 +- src/UI/Windows/EditDialog.cs | 4 +- 47 files changed, 228 insertions(+), 106 deletions(-) diff --git a/src/Design.cs b/src/Design.cs index 3a362b8e..38e3d180 100644 --- a/src/Design.cs +++ b/src/Design.cs @@ -319,22 +319,22 @@ public IEnumerable GetExtraOperations(Point pos) col = dt.Columns[tv.SelectedColumn]; } - yield return new AddColumnOperation(this, null); + yield return new AddColumnOperation(App, this, null); // no columns are selected so don't offer removal. if (col != null) { - yield return new RemoveColumnOperation(this, col); - yield return new RenameColumnOperation(this, col, null); - yield return new MoveColumnOperation(this, col, -1); - yield return new MoveColumnOperation(this, col, 1); + yield return new RemoveColumnOperation(App, this, col); + yield return new RenameColumnOperation(App, this, col, null); + yield return new MoveColumnOperation(App, this, col, -1); + yield return new MoveColumnOperation(App, this, col, 1); } } if (this.IsContainerView || this.IsRoot) { yield return new AddViewOperation(App,this); - yield return new PasteOperation(this); + yield return new PasteOperation(App, this); } else { @@ -345,53 +345,53 @@ public IEnumerable GetExtraOperations(Point pos) } } - yield return new DeleteViewOperation(this); + yield return new DeleteViewOperation(App, this); switch ( this.View ) { case TabView tabView: { - yield return new AddTabOperation(this, null); + yield return new AddTabOperation(App, this, null); if (tabView.SelectedTab != null) { - yield return new RemoveTabOperation(this, tabView.SelectedTab); - yield return new RenameTabOperation(this, tabView.SelectedTab, null); - yield return new MoveTabOperation(this, tabView.SelectedTab, -1); - yield return new MoveTabOperation(this, tabView.SelectedTab, 1); + yield return new RemoveTabOperation(App, this, tabView.SelectedTab); + yield return new RenameTabOperation(App, this, tabView.SelectedTab, null); + yield return new MoveTabOperation(App, this, tabView.SelectedTab, -1); + yield return new MoveTabOperation(App, this, tabView.SelectedTab, 1); } break; } case MenuBar mb: { - yield return new AddMenuOperation(this, null); + yield return new AddMenuOperation(App, this, null); var menu = pos.IsEmpty ? mb.GetSelectedMenuItem() : mb.ScreenToMenuBarItem(pos.X); if (menu != null) { - yield return new RemoveMenuOperation(this, menu); - yield return new RenameMenuOperation(this, menu, null); - yield return new MoveMenuOperation(this, menu, -1); - yield return new MoveMenuOperation(this, menu, 1); + yield return new RemoveMenuOperation(App, this, menu); + yield return new RenameMenuOperation(App, this, menu, null); + yield return new MoveMenuOperation(App, this, menu, -1); + yield return new MoveMenuOperation(App, this, menu, 1); } break; } case StatusBar sb: { - yield return new AddStatusItemOperation(this, null); + yield return new AddStatusItemOperation(App, this, null); var item = sb.ScreenToMenuBarItem(pos.X); if (item != null) { - yield return new RemoveStatusItemOperation(this, item); - yield return new RenameStatusItemOperation(this, item, null); - yield return new SetShortcutOperation(this, item, null); - yield return new MoveStatusItemOperation(this, item, -1); - yield return new MoveStatusItemOperation(this, item, 1); + yield return new RemoveStatusItemOperation(App, this, item); + yield return new RenameStatusItemOperation(App, this, item, null); + yield return new SetShortcutOperation(App, this, item, null); + yield return new MoveStatusItemOperation(App, this, item, -1); + yield return new MoveStatusItemOperation(App, this, item, 1); } break; diff --git a/src/Operations/CopyOperation.cs b/src/Operations/CopyOperation.cs index e7febe4a..2bfd2c41 100644 --- a/src/Operations/CopyOperation.cs +++ b/src/Operations/CopyOperation.cs @@ -1,3 +1,5 @@ +using Terminal.Gui.App; + namespace TerminalGuiDesigner.Operations; /// @@ -14,8 +16,9 @@ public class CopyOperation : Operation /// Initializes a new instance of the class. When /// run copies to . /// + /// The application instance. /// One or more designs to copy. - public CopyOperation(params Design[] toCopy) + public CopyOperation(IApplication app, params Design[] toCopy) : base(app) { if (toCopy.Any()) { diff --git a/src/Operations/DeleteViewOperation.cs b/src/Operations/DeleteViewOperation.cs index c0121607..30936b1f 100644 --- a/src/Operations/DeleteViewOperation.cs +++ b/src/Operations/DeleteViewOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; namespace TerminalGuiDesigner.Operations; @@ -22,8 +23,9 @@ public class DeleteViewOperation : Operation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrappers for the you want to delete. - public DeleteViewOperation(params Design[] delete) + public DeleteViewOperation(IApplication app, params Design[] delete) : base(app) { this.delete = delete; this.from = delete.Select(d => d.View.SuperView).ToArray(); diff --git a/src/Operations/DragOperation.cs b/src/Operations/DragOperation.cs index f0082b4f..53c39b51 100644 --- a/src/Operations/DragOperation.cs +++ b/src/Operations/DragOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -25,13 +26,14 @@ public partial class DragOperation : Operation /// Initializes a new instance of the class. /// Begins a drag operation in which is moved. /// + /// The application instance. /// The primary design being moved. Cannot be the root design (see ). /// The client X coordinate position of the mouse when dragging began. Final location is calculated as an offset from this point. /// This is not necessarily the X/Y of (e.g. if mouse click drag starts in from middle of View area) /// The client Y coordinate position of the mouse when dragging began. Final location is calculated as an offset from this point. /// This is not necessarily the X/Y of (e.g. if mouse click drag starts in from middle of View area) /// Other Designs that are also multi selected and should be dragged at the same time. - public DragOperation(Design beingDragged, int originalX, int originalY, Design[]? alsoDrag) + public DragOperation(IApplication app, Design beingDragged, int originalX, int originalY, Design[]? alsoDrag) : base(app) { // TODO: how does this respond when alsoDrag has some that are not in // same view as beingDragged - write unit test diff --git a/src/Operations/Generics/AddOperation.cs b/src/Operations/Generics/AddOperation.cs index 94180a6b..78221c57 100644 --- a/src/Operations/Generics/AddOperation.cs +++ b/src/Operations/Generics/AddOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; using TerminalGuiDesigner.UI.Windows; @@ -23,6 +24,7 @@ public abstract class AddOperation : GenericArrayOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Method to get the current collection. /// Method to save the new collection to the . /// Method to turn an element into a string (e.g. for ToString()). @@ -30,13 +32,14 @@ public abstract class AddOperation : GenericArrayOperation /// Wrapper for a of type . /// The name to use for the new object or null to prompt user at runtime. public AddOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, ArrayElementFactory elementFactory, Design design, string? name) - : base(arrayGetter, arraySetter, stringGetter, design) + : base(app, arrayGetter, arraySetter, stringGetter, design) { this.name = name; this.elementFactory = elementFactory; diff --git a/src/Operations/Generics/GenericArrayElementOperation.cs b/src/Operations/Generics/GenericArrayElementOperation.cs index 2cd12df9..cbe0c4ad 100644 --- a/src/Operations/Generics/GenericArrayElementOperation.cs +++ b/src/Operations/Generics/GenericArrayElementOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; namespace TerminalGuiDesigner.Operations.Generics; @@ -16,6 +17,7 @@ public abstract class GenericArrayElementOperation : GenericArrayOperati /// /// Initializes a new instance of the class. /// + /// The application instance. /// Method for getting current collection. /// Method for storing new collection. /// Method for turning array element to string. @@ -24,12 +26,13 @@ public abstract class GenericArrayElementOperation : GenericArrayOperati /// Thrown if is not in collection /// or is not wrapping . public GenericArrayElementOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, Design design, T2 element) - : base(arrayGetter, arraySetter, stringGetter, design) + : base(app, arrayGetter, arraySetter, stringGetter, design) { this.OperateOn = element; diff --git a/src/Operations/Generics/GenericArrayOperation.cs b/src/Operations/Generics/GenericArrayOperation.cs index 0126d810..f71ecdaa 100644 --- a/src/Operations/Generics/GenericArrayOperation.cs +++ b/src/Operations/Generics/GenericArrayOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; namespace TerminalGuiDesigner.Operations.Generics; @@ -16,16 +17,18 @@ public abstract class GenericArrayOperation : GenericOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Method for getting the current collection. /// Method for setting the new collection. /// Method for turning an element into a user readable string (Name, Title etc). /// Wrapper for a of Type . public GenericArrayOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, Design design) - : base(design) + : base(app, design) { this.StringGetter = stringGetter; this.ArrayGetter = arrayGetter; diff --git a/src/Operations/Generics/GenericOperation.cs b/src/Operations/Generics/GenericOperation.cs index 26adb654..4a69e378 100644 --- a/src/Operations/Generics/GenericOperation.cs +++ b/src/Operations/Generics/GenericOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -15,9 +16,10 @@ public abstract class GenericOperation : Operation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Design Wrapper for a of Type . /// Thrown if does not wrap a . - public GenericOperation(Design design) + public GenericOperation(IApplication app, Design design) : base(app) { if (design.View is not T t) { diff --git a/src/Operations/Generics/MoveOperation.cs b/src/Operations/Generics/MoveOperation.cs index 6848c98c..debf8a34 100644 --- a/src/Operations/Generics/MoveOperation.cs +++ b/src/Operations/Generics/MoveOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -24,6 +25,7 @@ public abstract class MoveOperation : GenericArrayElementOperation /// Initializes a new instance of the class. /// + /// The application instance. /// Method for retrieving the Array that should be modified. /// Method to invoke with the new Array order. /// Method for turning an Array element into a string (e.g. for ). @@ -31,13 +33,14 @@ public abstract class MoveOperation : GenericArrayElementOperationThe Array element to move. /// Negative to move left, positive to move right. protected MoveOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, Design design, T2 toMove, int adjustment) - : base(arrayGetter, arraySetter, stringGetter, design, toMove) + : base(app, arrayGetter, arraySetter, stringGetter, design, toMove) { var array = arrayGetter(this.View); diff --git a/src/Operations/Generics/RemoveOperation.cs b/src/Operations/Generics/RemoveOperation.cs index 9d2e453d..b9e023f9 100644 --- a/src/Operations/Generics/RemoveOperation.cs +++ b/src/Operations/Generics/RemoveOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -18,18 +19,20 @@ public abstract class RemoveOperation : GenericArrayElementOperation /// Initializes a new instance of the class. /// + /// The application instance. /// Method for getting the current collection. /// Method for setting a new collection on a of Type . /// Method for getting the 'name' from an element (Name, Title etc). /// Wrapper for a of Type which owns the collection (e.g. ). /// Element to remove. public RemoveOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, Design design, T2 toRemove) - : base(arrayGetter, arraySetter, stringGetter, design, toRemove) + : base(app, arrayGetter, arraySetter, stringGetter, design, toRemove) { this.idx = Array.IndexOf(arrayGetter(this.View), toRemove); } diff --git a/src/Operations/Generics/RenameOperation.cs b/src/Operations/Generics/RenameOperation.cs index 36382fba..32943ebe 100644 --- a/src/Operations/Generics/RenameOperation.cs +++ b/src/Operations/Generics/RenameOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; using TerminalGuiDesigner.UI.Windows; @@ -22,6 +23,7 @@ public abstract class RenameOperation : GenericArrayElementOperation /// Initializes a new instance of the class. /// + /// The application instance. /// Method for retrieving the Array that should be modified. /// Method to invoke with the new Array order. /// Method for turning an Array element into a string (e.g. for ). @@ -30,6 +32,7 @@ public abstract class RenameOperation : GenericArrayElementOperationElement to rename. /// New name to use or null to prompt user for name. protected RenameOperation( + IApplication app, ArrayGetterDelegate arrayGetter, ArraySetterDelegate arraySetter, StringGetterDelegate stringGetter, @@ -37,7 +40,7 @@ protected RenameOperation( Design design, T2 toRename, string? newName) - : base(arrayGetter, arraySetter, stringGetter, design, toRename) + : base(app, arrayGetter, arraySetter, stringGetter, design, toRename) { this.stringSetter = stringSetter; this.originalName = this.StringGetter(toRename); diff --git a/src/Operations/MenuOperations/AddMenuItemOperation.cs b/src/Operations/MenuOperations/AddMenuItemOperation.cs index 9f1b444a..562eac04 100644 --- a/src/Operations/MenuOperations/AddMenuItemOperation.cs +++ b/src/Operations/MenuOperations/AddMenuItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -21,10 +22,11 @@ public class AddMenuItemOperation : MenuItemOperation /// Initializes a new instance of the class. When /// performed the operation will add a new below . /// + /// The application instance. /// An existing to add the new one below. Must be a /// sub-menu (e.g. Open, Copy) not a top level menu (e.g. File, Edit). - public AddMenuItemOperation(MenuItem adjacentTo) - : base(adjacentTo) + public AddMenuItemOperation(IApplication app, MenuItem adjacentTo) + : base(app, adjacentTo) { } @@ -45,7 +47,7 @@ protected override void UndoImpl() return; } - var remove = new RemoveMenuItemOperation(this.added); + var remove = new RemoveMenuItemOperation(App, this.added); remove.Do(); } diff --git a/src/Operations/MenuOperations/AddMenuOperation.cs b/src/Operations/MenuOperations/AddMenuOperation.cs index 9a9cd600..e683391c 100644 --- a/src/Operations/MenuOperations/AddMenuOperation.cs +++ b/src/Operations/MenuOperations/AddMenuOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -14,11 +15,13 @@ public class AddMenuOperation : AddOperation /// Calling will add a new top level menu to the /// wrapped by . /// + /// The application instance. /// wrapper for a view of Type . /// Optional explicit name to add with or null to prompt user interactively. /// Thrown if the is not wrapping a . - public AddMenuOperation(Design design, string? name) + public AddMenuOperation(IApplication app, Design design, string? name) : base( + app, (v) => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, (s) => s.Title.ToString() ?? "blank menu", diff --git a/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs b/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs index 66c2215d..f518245d 100644 --- a/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs +++ b/src/Operations/MenuOperations/ConvertMenuItemToSeperatorOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -16,9 +17,10 @@ public class ConvertMenuItemToSeperatorOperation : MenuItemOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// A to replace with a separator (null) in it's parent . - public ConvertMenuItemToSeperatorOperation(MenuItem toConvert) - : base(toConvert) + public ConvertMenuItemToSeperatorOperation(IApplication app, MenuItem toConvert) + : base(app, toConvert) { } diff --git a/src/Operations/MenuOperations/MenuItemOperation.cs b/src/Operations/MenuOperations/MenuItemOperation.cs index b1942db2..cc794efd 100644 --- a/src/Operations/MenuOperations/MenuItemOperation.cs +++ b/src/Operations/MenuOperations/MenuItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -12,8 +13,9 @@ public abstract class MenuItemOperation : Operation /// /// Initializes a new instance of the class. /// + /// The application instance. /// that you will operate on. - protected MenuItemOperation(MenuItem operateOn) + protected MenuItemOperation(IApplication app, MenuItem operateOn) : base(app) { // if taking a new line add an extra menu item // menuItem.Parent doesn't work for root menu items diff --git a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs index a9e995fd..4df3a529 100644 --- a/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemLeftOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -21,9 +22,10 @@ public class MoveMenuItemLeftOperation : MenuItemOperation /// Initializes a new instance of the class. /// This operation pulls a out of a sub-menu onto the level above. /// + /// The application instance. /// The to move to parent containing menu. - public MoveMenuItemLeftOperation(MenuItem toMove) - : base(toMove) + public MoveMenuItemLeftOperation(IApplication app, MenuItem toMove) + : base(app, toMove) { // command is already invalid or user is trying to move a menu item that is not in a sub-menu if (this.IsImpossible || this.Bar == null || this.Bar.SubViews.OfType().Any(m => m.SubViews.Contains(toMove))) @@ -52,7 +54,7 @@ protected override void UndoImpl() return; } - new MoveMenuItemRightOperation(this.OperateOn) + new MoveMenuItemRightOperation(App, this.OperateOn) { InsertionIndex = this.pulledFromIndex, } @@ -79,7 +81,7 @@ protected override bool DoImpl() var parentsIdx = children.IndexOf(this.Parent); // remove us - if (new RemoveMenuItemOperation(this.OperateOn).Do()) + if (new RemoveMenuItemOperation(App, this.OperateOn).Do()) { // We are the parent but parents children don't contain // us. That's bad. TODO: log this diff --git a/src/Operations/MenuOperations/MoveMenuItemOperation.cs b/src/Operations/MenuOperations/MoveMenuItemOperation.cs index 249892de..c72fc790 100644 --- a/src/Operations/MenuOperations/MoveMenuItemOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -17,11 +18,12 @@ public class MoveMenuItemOperation : MenuItemOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// The that should change places relative to other /// on its . /// True to move up on the screen (array index decreases). False to move down on the screen (array index increases). - public MoveMenuItemOperation(MenuItem toMove, bool up) - : base(toMove) + public MoveMenuItemOperation(IApplication app, MenuItem toMove, bool up) + : base(app, toMove) { this.up = up; diff --git a/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs b/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs index 63cdc5ae..1ad924ec 100644 --- a/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuItemRightOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; namespace TerminalGuiDesigner.Operations.MenuOperations; @@ -14,9 +15,10 @@ public class MoveMenuItemRightOperation : MenuItemOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Moves the to the sub-menu of the above it. - public MoveMenuItemRightOperation(MenuItem toMove) - : base(toMove) + public MoveMenuItemRightOperation(IApplication app, MenuItem toMove) + : base(app, toMove) { /* if (this.Parent?.GetChildrenIndex(toMove) == 0) @@ -42,7 +44,7 @@ protected override void RedoImpl() return; } - new MoveMenuItemRightOperation(this.OperateOn).Do(); + new MoveMenuItemRightOperation(App, this.OperateOn).Do(); } /// @@ -53,7 +55,7 @@ protected override void UndoImpl() return; } - new MoveMenuItemLeftOperation(this.OperateOn).Do(); + new MoveMenuItemLeftOperation(App, this.OperateOn).Do(); } /// diff --git a/src/Operations/MenuOperations/MoveMenuOperation.cs b/src/Operations/MenuOperations/MoveMenuOperation.cs index 74062177..6cd9f32c 100644 --- a/src/Operations/MenuOperations/MoveMenuOperation.cs +++ b/src/Operations/MenuOperations/MoveMenuOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -15,11 +16,13 @@ public class MoveMenuOperation : MoveOperation /// Creates an operation that will change the ordering of top level menus within /// a . /// + /// The application instance. /// Wrapper for a . /// The top level menu to move. /// Negative to move menu left, positive to move menu right. - public MoveMenuOperation(Design design, MenuBarItem toMove, int adjustment) + public MoveMenuOperation(IApplication app, Design design, MenuBarItem toMove, int adjustment) : base( + app, v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", diff --git a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs index a886ef31..2c40338d 100644 --- a/src/Operations/MenuOperations/RemoveMenuItemOperation.cs +++ b/src/Operations/MenuOperations/RemoveMenuItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -38,9 +39,10 @@ public class RemoveMenuItemOperation : MenuItemOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// The that should be removed (deleted). - public RemoveMenuItemOperation(MenuItem toRemove) - : base(toRemove) + public RemoveMenuItemOperation(IApplication app, MenuItem toRemove) + : base(app, toRemove) { } diff --git a/src/Operations/MenuOperations/RemoveMenuOperation.cs b/src/Operations/MenuOperations/RemoveMenuOperation.cs index 78de6e4a..309fccf8 100644 --- a/src/Operations/MenuOperations/RemoveMenuOperation.cs +++ b/src/Operations/MenuOperations/RemoveMenuOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -14,11 +15,13 @@ public class RemoveMenuOperation : RemoveOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a upon which you wish to operate. /// The to remove. /// Thrown if does not wrap a . - public RemoveMenuOperation(Design design, MenuBarItem toRemove) + public RemoveMenuOperation(IApplication app, Design design, MenuBarItem toRemove) : base( + app, v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", diff --git a/src/Operations/MenuOperations/RenameMenuItemOperation.cs b/src/Operations/MenuOperations/RenameMenuItemOperation.cs index a4ce4708..0d07d10b 100644 --- a/src/Operations/MenuOperations/RenameMenuItemOperation.cs +++ b/src/Operations/MenuOperations/RenameMenuItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.ToCode; using TerminalGuiDesigner.UI.Windows; @@ -21,9 +22,10 @@ public class RenameMenuItemOperation : MenuItemOperation /// Initializes a new instance of the class. /// Note that this operation renames the field name in .Designer.cs not the . /// + /// The application instance. /// The column to choose a new private field name for. - public RenameMenuItemOperation(MenuItem toRename) - : base(toRename) + public RenameMenuItemOperation(IApplication app, MenuItem toRename) + : base(app, toRename) { this.originalName = toRename.Data as string; } diff --git a/src/Operations/MenuOperations/RenameMenuOperation.cs b/src/Operations/MenuOperations/RenameMenuOperation.cs index bea0e9af..dda95227 100644 --- a/src/Operations/MenuOperations/RenameMenuOperation.cs +++ b/src/Operations/MenuOperations/RenameMenuOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -12,11 +13,13 @@ public class RenameMenuOperation : RenameOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a upon which you wish to operate. /// The to rename. /// The new name to use. - public RenameMenuOperation(Design design, MenuBarItem toRename, string? newName) + public RenameMenuOperation(IApplication app, Design design, MenuBarItem toRename, string? newName) : base( + app, v => v.SubViews.OfType().ToArray(), (v, a) => v.Menus = a, s => s.Title.ToString() ?? "blank menu", diff --git a/src/Operations/MoveViewOperation.cs b/src/Operations/MoveViewOperation.cs index 585f33ed..a361b13f 100644 --- a/src/Operations/MoveViewOperation.cs +++ b/src/Operations/MoveViewOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; namespace TerminalGuiDesigner.Operations; @@ -15,12 +16,13 @@ public class MoveViewOperation : Operation /// Moves a within it's current container by a fixed amount /// (e.g. nudging with Shift+Cursor). /// + /// The application instance. /// Wrapper of the to move. /// The amount to move in the X plane. Positive for Right and Negative for Left. /// Ignored if is relative (e.g. ). /// The amount to move in the Y plane. Positive for Down and Negative for Up. /// Ignored if is relative (e.g. ). - public MoveViewOperation(Design toMove, int deltaX, int deltaY) + public MoveViewOperation(IApplication app, Design toMove, int deltaX, int deltaY) : base(app) { this.BeingMoved = toMove; this.OriginX = toMove.View.X; diff --git a/src/Operations/OperationFactory.cs b/src/Operations/OperationFactory.cs index 57587b88..fd69ee4a 100644 --- a/src/Operations/OperationFactory.cs +++ b/src/Operations/OperationFactory.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Input; using Terminal.Gui.ViewBase; using TerminalGuiDesigner.ToCode; @@ -11,15 +12,18 @@ namespace TerminalGuiDesigner.Operations; /// public class OperationFactory { + private readonly IApplication app; private PropertyValueGetterDelegate valueGetter; /// /// Initializes a new instance of the class. /// + /// The application instance. /// Delegate for getting new values. This /// will be passed to created operations e.g. . - public OperationFactory(PropertyValueGetterDelegate valueGetter) + public OperationFactory(IApplication app, PropertyValueGetterDelegate valueGetter) { + this.app = app; this.valueGetter = valueGetter; } @@ -78,7 +82,7 @@ public IEnumerable CreateOperations(Design[] selected, MouseEventArg if (all.Count == selected.Length) { // create an operation to change them all at once - props.Add(new SetPropertyOperation(all.Select(v => v.Design).ToArray(), propertyName, this.valueGetter)); + props.Add(new SetPropertyOperation(this.app, all.Select(v => v.Design).ToArray(), propertyName, this.valueGetter)); } } @@ -91,11 +95,11 @@ public IEnumerable CreateOperations(Design[] selected, MouseEventArg if (SelectionManager.Instance.Selected.Any()) { - toReturn.Add(new CopyOperation(SelectionManager.Instance.Selected.ToArray())); + toReturn.Add(new CopyOperation(this.app, SelectionManager.Instance.Selected.ToArray())); } else if (rightClicked != null) { - toReturn.Add(new CopyOperation(rightClicked)); + toReturn.Add(new CopyOperation(this.app, rightClicked)); } return toReturn; @@ -114,7 +118,7 @@ private IEnumerable CreateOperations(MouseEventArgs? m, Design d) foreach (var prop in d.GetDesignableProperties().OrderBy(p => p.GetHumanReadableName())) { - yield return new SetPropertyOperation(d, prop, this.valueGetter); + yield return new SetPropertyOperation(this.app, d, prop, this.valueGetter); } } } \ No newline at end of file diff --git a/src/Operations/PasteOperation.cs b/src/Operations/PasteOperation.cs index 8309a6aa..447d30ef 100644 --- a/src/Operations/PasteOperation.cs +++ b/src/Operations/PasteOperation.cs @@ -1,5 +1,6 @@ using System.Data; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -23,10 +24,11 @@ public class PasteOperation : Operation /// /// Initializes a new instance of the class. /// + /// The application instance. /// The container into which to /// add the . This allows for copying from one container /// (e.g. ) but pasting into another. - public PasteOperation(Design addTo) + public PasteOperation(IApplication app, Design addTo) : base(app) { this.toCopy = CopyOperation.LastCopiedDesign; this.toCopy = this.PruneChildViews(this.toCopy); diff --git a/src/Operations/ResizeOperation.cs b/src/Operations/ResizeOperation.cs index 6d59d99f..f4cd68ee 100644 --- a/src/Operations/ResizeOperation.cs +++ b/src/Operations/ResizeOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; namespace TerminalGuiDesigner.Operations; @@ -12,12 +13,13 @@ public class ResizeOperation : Operation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for the that is to be resized. /// Client coordinate X point within /// where the mouse cursor is positioned for resizing. /// Client coordinate Y point within /// where the mouse cursor is positioned for resizing. - public ResizeOperation(Design beingResized, int destX, int destY) + public ResizeOperation(IApplication app, Design beingResized, int destX, int destY) : base(app) { this.BeingResized = beingResized; this.OriginalWidth = beingResized.View.Width; diff --git a/src/Operations/SetPropertyOperation.cs b/src/Operations/SetPropertyOperation.cs index 9f03a57d..b404c40c 100644 --- a/src/Operations/SetPropertyOperation.cs +++ b/src/Operations/SetPropertyOperation.cs @@ -1,5 +1,6 @@ using System.Reflection; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using TerminalGuiDesigner.ToCode; using TerminalGuiDesigner.UI.Windows; @@ -32,12 +33,13 @@ public class SetPropertyOperation : Operation /// time. Throw in delegate if you want to perform last /// minute cancellation instead of returning a new value to set. /// + /// The application instance. /// A single on which to change a single . /// Property to change (see ). /// Delegate for fetching the new value for the when /// command is run e.g. via a dialog. - public SetPropertyOperation(Design design, Property property, PropertyValueGetterDelegate valueGetter) - : this(design, property, property.GetValue(), null) + public SetPropertyOperation(IApplication app, Design design, Property property, PropertyValueGetterDelegate valueGetter) + : this(app, design, property, property.GetValue(), null) { this.valueGetter = valueGetter; } @@ -46,11 +48,12 @@ public SetPropertyOperation(Design design, Property property, PropertyValueGette /// Initializes a new instance of the class. /// Operation that changes the to have a specific . /// + /// The application instance. /// A single on which to change a single . /// Property to change (see ). /// The old value that had. /// The new value you want to assign to . - public SetPropertyOperation(Design design, Property property, object? oldValue, object? newValue) + public SetPropertyOperation(IApplication app, Design design, Property property, object? oldValue, object? newValue) : base(app) { this.mementos = new[] { @@ -71,6 +74,7 @@ public SetPropertyOperation(Design design, Property property, object? oldValue, /// Constructor for setting the same property on multiple views at once (e.g. change color scheme on /// all multi selected views). /// + /// The application instance. /// All for which you want to change /// . /// The name of a designable on @@ -78,7 +82,7 @@ public SetPropertyOperation(Design design, Property property, object? oldValue, /// Delegate for fetching the new value for /// the when command is run e.g. via a . /// Thrown if is not found amongst properties. - public SetPropertyOperation(Design[] designs, string propertyName, PropertyValueGetterDelegate valueGetter) + public SetPropertyOperation(IApplication app, Design[] designs, string propertyName, PropertyValueGetterDelegate valueGetter) : base(app) { this.valueGetter = valueGetter; var mementos = new List(); diff --git a/src/Operations/StatusBarOperations/AddStatusItemOperation.cs b/src/Operations/StatusBarOperations/AddStatusItemOperation.cs index 194a4e03..7f8fcbf5 100644 --- a/src/Operations/StatusBarOperations/AddStatusItemOperation.cs +++ b/src/Operations/StatusBarOperations/AddStatusItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Drivers; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -13,10 +14,12 @@ public class AddStatusItemOperation : AddOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// Name for the new item created or null to prompt user. - public AddStatusItemOperation(Design design, string? name) + public AddStatusItemOperation(IApplication app, Design design, string? name) : base( + app, (d) => d.GetShortcuts(), (d, v) => d.SetShortcuts(v), (v) => v.Title.ToString() ?? Operation.Unnamed, diff --git a/src/Operations/StatusBarOperations/MoveStatusItemOperation.cs b/src/Operations/StatusBarOperations/MoveStatusItemOperation.cs index d518406d..035bb0e9 100644 --- a/src/Operations/StatusBarOperations/MoveStatusItemOperation.cs +++ b/src/Operations/StatusBarOperations/MoveStatusItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -12,11 +13,13 @@ public class MoveStatusItemOperation : MoveOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// The to move. /// Negative for left, positive for right. - public MoveStatusItemOperation(Design design, Shortcut toMove, int adjustment) + public MoveStatusItemOperation(IApplication app, Design design, Shortcut toMove, int adjustment) : base( + app, (v) => v.GetShortcuts(), (v, a) => v.SetShortcuts(a), (e) => e.Title?.ToString() ?? Operation.Unnamed, diff --git a/src/Operations/StatusBarOperations/RemoveStatusItemOperation.cs b/src/Operations/StatusBarOperations/RemoveStatusItemOperation.cs index 35fd5799..5a27eb6f 100644 --- a/src/Operations/StatusBarOperations/RemoveStatusItemOperation.cs +++ b/src/Operations/StatusBarOperations/RemoveStatusItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; using TerminalGuiDesigner.UI.Windows; @@ -13,10 +14,12 @@ public class RemoveStatusItemOperation : RemoveOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// A to remove from bar. - public RemoveStatusItemOperation(Design design, Shortcut toRemove) + public RemoveStatusItemOperation(IApplication app, Design design, Shortcut toRemove) : base( + app, (v) => v.GetShortcuts(), (v, a) => v.SetShortcuts(a), (e) => e.Title?.ToString() ?? Operation.Unnamed, diff --git a/src/Operations/StatusBarOperations/RenameStatusItemOperation.cs b/src/Operations/StatusBarOperations/RenameStatusItemOperation.cs index a78618f3..badad70f 100644 --- a/src/Operations/StatusBarOperations/RenameStatusItemOperation.cs +++ b/src/Operations/StatusBarOperations/RenameStatusItemOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; using TerminalGuiDesigner.UI.Windows; @@ -13,11 +14,13 @@ public class RenameStatusItemOperation : RenameOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Design wrapper for a . /// The to rename. /// The new name to use or null to prompt user. - public RenameStatusItemOperation(Design design, Shortcut toRename, string? newName) + public RenameStatusItemOperation(IApplication app, Design design, Shortcut toRename, string? newName) : base( + app, (d) => d.GetShortcuts(), (d, v) => d.SetShortcuts(v), (v) => v.Title.ToString() ?? Operation.Unnamed, diff --git a/src/Operations/StatusBarOperations/SetShortcutOperation.cs b/src/Operations/StatusBarOperations/SetShortcutOperation.cs index bb24d10b..8f599494 100644 --- a/src/Operations/StatusBarOperations/SetShortcutOperation.cs +++ b/src/Operations/StatusBarOperations/SetShortcutOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Input; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -18,11 +19,13 @@ public class SetShortcutOperation : GenericArrayElementOperation /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// The whose shortcut you want to change. /// The new shortcut or null to prompt user at runtime. - public SetShortcutOperation(Design design, Shortcut statusItem, Key? shortcut) + public SetShortcutOperation(IApplication app, Design design, Shortcut statusItem, Key? shortcut) : base( + app, (v) => v.GetShortcuts(), (v, a) => v.SetShortcuts(a), (e) => e.Title?.ToString() ?? Operation.Unnamed, diff --git a/src/Operations/TabOperations/AddTabOperation.cs b/src/Operations/TabOperations/AddTabOperation.cs index 5040fe39..d897813e 100644 --- a/src/Operations/TabOperations/AddTabOperation.cs +++ b/src/Operations/TabOperations/AddTabOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -13,10 +14,12 @@ public class AddTabOperation : AddOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for that will be operated on. /// Name for the new tab or null to prompt user. - public AddTabOperation(Design design, string? name) + public AddTabOperation(IApplication app, Design design, string? name) : base( + app, (t) => t.Tabs.ToArray(), (v, a) => v.ReOrderTabs(a), tab => tab.DisplayText.ToString() ?? "unnamed tab", diff --git a/src/Operations/TabOperations/MoveTabOperation.cs b/src/Operations/TabOperations/MoveTabOperation.cs index 6533928f..e54228f3 100644 --- a/src/Operations/TabOperations/MoveTabOperation.cs +++ b/src/Operations/TabOperations/MoveTabOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -15,11 +16,13 @@ public class MoveTabOperation : MoveOperation /// Creates an operation that will change the ordering of tabs within /// a . /// + /// The application instance. /// Wrapper for a . /// The Tab to move. /// Negative to move tab left, positive to move tab right. - public MoveTabOperation(Design design, Tab toMove, int adjustment) + public MoveTabOperation(IApplication app, Design design, Tab toMove, int adjustment) : base( + app, (t) => t.Tabs.ToArray(), (v, a) => v.ReOrderTabs(a), tab => tab.Text.ToString() ?? "unnamed tab", diff --git a/src/Operations/TabOperations/RemoveTabOperation.cs b/src/Operations/TabOperations/RemoveTabOperation.cs index 5e69c954..fb6c55cc 100644 --- a/src/Operations/TabOperations/RemoveTabOperation.cs +++ b/src/Operations/TabOperations/RemoveTabOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -13,11 +14,13 @@ public class RemoveTabOperation : RemoveOperation /// Initializes a new instance of the class. /// Removes from a . /// + /// The application instance. /// Wrapper for a from which you want to remove the tab. /// The tab to remove. /// Thrown if does not wrap a . - public RemoveTabOperation(Design design, Tab toRemove) + public RemoveTabOperation(IApplication app, Design design, Tab toRemove) : base( + app, (t) => t.Tabs.ToArray(), (v, a) => v.ReOrderTabs(a), tab => tab.Text.ToString() ?? "unnamed tab", diff --git a/src/Operations/TabOperations/RenameTabOperation.cs b/src/Operations/TabOperations/RenameTabOperation.cs index b21d52bc..37d74d55 100644 --- a/src/Operations/TabOperations/RenameTabOperation.cs +++ b/src/Operations/TabOperations/RenameTabOperation.cs @@ -1,4 +1,5 @@ using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -14,11 +15,13 @@ public class RenameTabOperation : RenameOperation /// Initializes a new instance of the class. /// This command changes the on a . /// + /// The application instance. /// Wrapper for a . /// Tab to rename. /// New name to use or null to prompt. - public RenameTabOperation(Design design, Tab toRename, string? newName) + public RenameTabOperation(IApplication app, Design design, Tab toRename, string? newName) : base( + app, (t) => t.Tabs.ToArray(), (v, a) => v.ReOrderTabs(a), tab => tab.DisplayText.ToString() ?? "unnamed tab", diff --git a/src/Operations/TableViewOperations/AddColumnOperation.cs b/src/Operations/TableViewOperations/AddColumnOperation.cs index d39bc423..be47fef9 100644 --- a/src/Operations/TableViewOperations/AddColumnOperation.cs +++ b/src/Operations/TableViewOperations/AddColumnOperation.cs @@ -1,5 +1,6 @@ using System.Data; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; using TerminalGuiDesigner.UI.Windows; @@ -14,11 +15,13 @@ public class AddColumnOperation : AddOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// The name for the new column or null to prompt at runtime with a dialog. /// Thrown if is not wrapping a . - public AddColumnOperation(Design design, string? newColumnName) + public AddColumnOperation(IApplication app, Design design, string? newColumnName) : base( + app, (v) => v.GetDataTable().Columns.Cast().ToArray(), (v, a) => v.ReOrderColumns(a), (c) => c.ColumnName, diff --git a/src/Operations/TableViewOperations/MoveColumnOperation.cs b/src/Operations/TableViewOperations/MoveColumnOperation.cs index 9fd08d1f..3f07e1e3 100644 --- a/src/Operations/TableViewOperations/MoveColumnOperation.cs +++ b/src/Operations/TableViewOperations/MoveColumnOperation.cs @@ -1,5 +1,6 @@ using System.Data; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -16,11 +17,13 @@ public class MoveColumnOperation : MoveOperation /// Creates an operation that will change the ordering of columns within /// a . /// + /// The application instance. /// Wrapper for a . /// The to move. /// Negative to move left, positive to move right. - public MoveColumnOperation(Design design, DataColumn column, int adjustment) + public MoveColumnOperation(IApplication app, Design design, DataColumn column, int adjustment) : base( + app, (v) => v.GetDataTable().Columns.Cast().ToArray(), (v, a) => v.ReOrderColumns(a), (c) => c.ColumnName, diff --git a/src/Operations/TableViewOperations/RemoveColumnOperation.cs b/src/Operations/TableViewOperations/RemoveColumnOperation.cs index e5f302f7..a14b39b7 100644 --- a/src/Operations/TableViewOperations/RemoveColumnOperation.cs +++ b/src/Operations/TableViewOperations/RemoveColumnOperation.cs @@ -1,5 +1,6 @@ using System.Data; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -14,10 +15,12 @@ public class RemoveColumnOperation : RemoveOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// Wrapper for a . /// Column to remove. - public RemoveColumnOperation(Design design, DataColumn column) + public RemoveColumnOperation(IApplication app, Design design, DataColumn column) : base( + app, (v) => v.GetDataTable().Columns.Cast().ToArray(), (v, a) => v.ReOrderColumns(a), (c) => c.ColumnName, diff --git a/src/Operations/TableViewOperations/RenameColumnOperation.cs b/src/Operations/TableViewOperations/RenameColumnOperation.cs index a6631ee8..43f4349f 100644 --- a/src/Operations/TableViewOperations/RenameColumnOperation.cs +++ b/src/Operations/TableViewOperations/RenameColumnOperation.cs @@ -1,5 +1,6 @@ using System.Data; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.Views; using TerminalGuiDesigner.Operations.Generics; @@ -13,12 +14,14 @@ public class RenameColumnOperation : RenameOperation /// /// Initializes a new instance of the class. /// + /// The application instance. /// The wrapper for a . /// The column to rename. /// New name to use or null to prompt user. /// Thrown if does not wrap a . - public RenameColumnOperation(Design design, DataColumn column, string? newName) + public RenameColumnOperation(IApplication app, Design design, DataColumn column, string? newName) : base( + app, (v) => v.GetDataTable().Columns.Cast().ToArray(), (v, a) => v.ReOrderColumns(a), (c) => c.ColumnName, diff --git a/src/ToCode/TabToCode.cs b/src/ToCode/TabToCode.cs index 0760fe18..0a7f551d 100644 --- a/src/ToCode/TabToCode.cs +++ b/src/ToCode/TabToCode.cs @@ -53,7 +53,7 @@ public void ToCode(CodeDomArgs args) this.AddPropertyAssignment(args, $"{tabName}.View.CanFocus", new CodeSnippetExpression("true")); // create code statements for everything in the Tab (recursive) - var viewToCode = new ViewToCode(); + var viewToCode = new ViewToCode(design.App); viewToCode.AddSubViewsToDesignerCs(this.tab.View, args, new CodeSnippetExpression($"{tabName}.View")); // add the constructed tab to the TabView diff --git a/src/ToCode/ViewToCode.cs b/src/ToCode/ViewToCode.cs index d3491e60..b3c5f81e 100644 --- a/src/ToCode/ViewToCode.cs +++ b/src/ToCode/ViewToCode.cs @@ -2,6 +2,7 @@ using System.CodeDom.Compiler; using Microsoft.CSharp; using Terminal.Gui; +using Terminal.Gui.App; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; using TerminalGuiDesigner.FromCode; @@ -13,6 +14,16 @@ namespace TerminalGuiDesigner.ToCode; /// public class ViewToCode { + private readonly IApplication app; + + /// + /// Initializes a new instance of the class. + /// + /// The application instance. + public ViewToCode(IApplication app) + { + this.app = app; + } /// /// Returns the code that would be added to the MyWindow.cs file of a new window /// so that it is ready for use with the MyWindow.Designer.cs file (in which @@ -91,7 +102,7 @@ public Design GenerateNewView(FileInfo csFilePath, string namespaceName, Type vi FixDimensionsForNewRootView(prototype, viewType); // use the prototype to create a designer cs file - var design = new Design(sourceFile, Design.RootDesignName, prototype); + var design = new Design(app, sourceFile, Design.RootDesignName, prototype); design.CreateSubControlDesigns(); this.GenerateDesignerCs(design, viewType); @@ -100,7 +111,7 @@ public Design GenerateNewView(FileInfo csFilePath, string namespaceName, Type vi * NOTE: prototype is not the same instance that is returned; */ - var decompiler = new CodeToView(sourceFile); + var decompiler = new CodeToView(app, sourceFile); return decompiler.CreateInstance(); } @@ -135,7 +146,7 @@ private void FixDimensionsForNewRootView(View prototype, Type viewType) public void GenerateDesignerCs(Design rootDesign, Type viewType) { var file = rootDesign.SourceCode; - var rosylyn = new CodeToView(file); + var rosylyn = new CodeToView(app, file); var ns = new CodeNamespace(rosylyn.Namespace); ns.Imports.Add(new CodeNamespaceImport("System")); diff --git a/src/UI/Editor.cs b/src/UI/Editor.cs index 2148a5f0..46718fb5 100644 --- a/src/UI/Editor.cs +++ b/src/UI/Editor.cs @@ -941,6 +941,7 @@ private void CreateAndShowContextMenu(MouseEventArgs? m, Design? rightClicked) // BUG: This is an improper exception here and could have unexpected behavior if this method is ever called asynchronously. var factory = new OperationFactory( + app, (p, v) => ValueFactory.GetNewValue(app, p.Design, p, v, out var newValue) ? newValue : throw new OperationCanceledException() ); var operations = factory @@ -1108,7 +1109,7 @@ private void Paste() if (d != null) { - var paste = new PasteOperation(d); + var paste = new PasteOperation(app, d); if (paste.IsImpossible) { @@ -1121,7 +1122,7 @@ private void Paste() private void Copy() { - var copy = new CopyOperation(SelectionManager.Instance.Selected.ToArray()); + var copy = new CopyOperation(app, SelectionManager.Instance.Selected.ToArray()); OperationManager.Instance.Do(copy); } @@ -1159,7 +1160,7 @@ private void ShowHelp() private void MoveControl(int deltaX, int deltaY) { - this.DoForSelectedViews((d) => new MoveViewOperation(d, deltaX, deltaY)); + this.DoForSelectedViews((d) => new MoveViewOperation(app, d, deltaX, deltaY)); } private void Delete() @@ -1171,7 +1172,7 @@ private void Delete() if (SelectionManager.Instance.Selected.Any()) { - var cmd = new DeleteViewOperation(SelectionManager.Instance.Selected.ToArray()); + var cmd = new DeleteViewOperation(app, SelectionManager.Instance.Selected.ToArray()); if (cmd.IsImpossible && cmd.PreventDeleting.Any()) @@ -1209,6 +1210,7 @@ private void DoForSelectedViews(Func operationFunc, bool allo if (selected.Length > 1) { var op = new CompositeOperation( + app, SelectionManager.Instance.Selected .Select(operationFunc).ToArray()); @@ -1277,7 +1279,7 @@ private void Open(FileInfo toOpen) Task.Run(() => { - var decompiler = new CodeToView(new SourceCodeFile(toOpen)); + var decompiler = new CodeToView(app, new SourceCodeFile(toOpen)); instance = decompiler.CreateInstance(); }).ContinueWith( (t, _) => @@ -1381,7 +1383,7 @@ private static Type[] GetSupportedRootViews() private void New(FileInfo toOpen, Type typeToCreate, string? explicitNamespace) { - var viewToCode = new ViewToCode(); + var viewToCode = new ViewToCode(app); string? ns = explicitNamespace; // TODO: The following two if statements can be combined and run in a loop until the user either cancels or gets it right @@ -1471,7 +1473,7 @@ private void Save() return; } - var viewToCode = new ViewToCode(); + var viewToCode = new ViewToCode(app); viewToCode.GenerateDesignerCs( this.viewBeingEdited, diff --git a/src/UI/KeyboardManager.cs b/src/UI/KeyboardManager.cs index 357cfe44..bb23eae9 100644 --- a/src/UI/KeyboardManager.cs +++ b/src/UI/KeyboardManager.cs @@ -102,14 +102,14 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.Rename) { OperationManager.Instance.Do( - new RenameMenuItemOperation(menuItem)); + new RenameMenuItemOperation(this.app, menuItem)); return true; } if (keystroke == Key.Enter) { OperationManager.Instance.Do( - new AddMenuItemOperation(menuItem)); + new AddMenuItemOperation(this.app, menuItem)); ChangeKeyTo(keystroke, Key.CursorDown); return false; @@ -126,7 +126,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.MoveRight) { OperationManager.Instance.Do( - new MoveMenuItemRightOperation(menuItem)); + new MoveMenuItemRightOperation(this.app, menuItem)); ChangeKeyTo(keystroke, Key.CursorUp); return true; @@ -135,7 +135,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.MoveLeft) { OperationManager.Instance.Do( - new MoveMenuItemLeftOperation(menuItem)); + new MoveMenuItemLeftOperation(this.app, menuItem)); ChangeKeyTo(keystroke, Key.CursorDown); return false; @@ -144,7 +144,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.MoveUp) { OperationManager.Instance.Do( - new MoveMenuItemOperation(menuItem, true)); + new MoveMenuItemOperation(this.app, menuItem, true)); ChangeKeyTo(keystroke, Key.CursorUp); return false; } @@ -152,7 +152,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (keystroke.ToString( ) == this.keyMap.MoveDown) { OperationManager.Instance.Do( - new MoveMenuItemOperation(menuItem, false)); + new MoveMenuItemOperation(this.app, menuItem, false)); ChangeKeyTo(keystroke, Key.CursorDown); return false; } @@ -163,7 +163,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst { // deleting the menu item using backspace to // remove all characters in the title or the Del key - var remove = new RemoveMenuItemOperation(menuItem); + var remove = new RemoveMenuItemOperation(this.app, menuItem); if (OperationManager.Instance.Do(remove)) { // if we are removing the last item @@ -217,7 +217,7 @@ private bool HandleKeyPressInMenu(View focusedView, MenuItem menuItem, Key keyst if (newValue.Equals("---")) { if (OperationManager.Instance.Do( - new ConvertMenuItemToSeperatorOperation(menuItem))) + new ConvertMenuItemToSeperatorOperation(this.app, menuItem))) { return true; } @@ -275,7 +275,7 @@ private void StartOperation(Design d) if (textProp != null) { - this.currentOperation = new SetPropertyOperation(d, textProp, d.View.Text, d.View.Text); + this.currentOperation = new SetPropertyOperation(this.app, d, textProp, d.View.Text, d.View.Text); } } diff --git a/src/UI/MouseManager.cs b/src/UI/MouseManager.cs index b2ff8b85..4e9c1d16 100644 --- a/src/UI/MouseManager.cs +++ b/src/UI/MouseManager.cs @@ -100,7 +100,7 @@ public void HandleMouse(MouseEventArgs m, Design viewBeingEdited) if (isLowerRight) { - this.resizeOperation = new ResizeOperation(design, dest.X, dest.Y); + this.resizeOperation = new ResizeOperation(this.app, design, dest.X, dest.Y); } else { @@ -112,6 +112,7 @@ public void HandleMouse(MouseEventArgs m, Design viewBeingEdited) { // drag all the views at once this.dragOperation = new DragOperation( + this.app, design, dest.X, dest.Y, @@ -120,7 +121,7 @@ public void HandleMouse(MouseEventArgs m, Design viewBeingEdited) else { // else drag only the non selected one - this.dragOperation = new DragOperation(design, dest.X, dest.Y, new Design[0]); + this.dragOperation = new DragOperation(this.app, design, dest.X, dest.Y, new Design[0]); } // don't begin an impossible drag! diff --git a/src/UI/Windows/EditDialog.cs b/src/UI/Windows/EditDialog.cs index 6ba4ee47..6641168c 100644 --- a/src/UI/Windows/EditDialog.cs +++ b/src/UI/Windows/EditDialog.cs @@ -101,7 +101,7 @@ internal static bool SetPropertyToNewValue(IApplication app, Design design, Prop if (ValueFactory.GetNewValue(app, design, p, p.GetValue(), out object? newValue)) { OperationManager.Instance.Do( - new SetPropertyOperation(design, p, oldValue, newValue)); + new SetPropertyOperation(app, design, p, oldValue, newValue)); return true; } @@ -122,7 +122,7 @@ private void SetProperty(bool setNull) { // user wants to set this property to null/default OperationManager.Instance.Do( - new SetPropertyOperation(this.design, p, oldValue, null)); + new SetPropertyOperation(app, this.design, p, oldValue, null)); } else { From 66bec1db61cefbe4018b7873c318832807b71bf7 Mon Sep 17 00:00:00 2001 From: tznind Date: Mon, 15 Dec 2025 01:56:20 +0000 Subject: [PATCH 015/101] App for tests too --- tests/AddViewTests.cs | 14 ++--- tests/CopyPasteTests.cs | 44 +++++++------- tests/DesignTests.cs | 4 +- tests/EditorTests.cs | 2 +- tests/KeyboardManagerTests.cs | 10 ++-- tests/ListViewTests.cs | 2 +- tests/Operations/AddColumnOperationTests.cs | 16 +++--- tests/Operations/AddMenuOperationTests.cs | 18 +++--- tests/Operations/AddTabOperationTests.cs | 18 +++--- tests/Operations/AddViewOperationTests.cs | 20 +++---- tests/Operations/DeleteViewOperationTests.cs | 16 +++--- tests/Operations/DragOperationTests.cs | 60 ++++++++++---------- tests/Operations/MoveViewOperationTests.cs | 16 +++--- tests/Operations/ResizeOperationTests.cs | 8 +-- tests/PosTests.cs | 14 ++--- tests/SuppressedPropertyTests.cs | 4 +- tests/Tests.cs | 30 ++++++---- tests/TextViewTests.cs | 2 +- tests/UI/MouseManagerTests.cs | 12 ++-- tests/UnitTests.csproj | 2 + tests/ViewExtensionsTests.cs | 6 +- 21 files changed, 165 insertions(+), 153 deletions(-) diff --git a/tests/AddViewTests.cs b/tests/AddViewTests.cs index 2757443a..b027d68c 100644 --- a/tests/AddViewTests.cs +++ b/tests/AddViewTests.cs @@ -17,13 +17,13 @@ internal class AddViewTests : Tests [Test] public void TestAdd_Undo() { - var viewToCode = new ViewToCode(); + var viewToCode = new ViewToCode(App); var file = new FileInfo("TestAdd_Undo.cs"); var designOut = viewToCode.GenerateNewView(file, "YourNamespace", typeof(Dialog)); var lbl = ViewFactory.Create /// Root designer View type to create (e.g. ) /// Type of subview to create (e.g. ) + /// The IApplication instance to use. /// Mutator for making pre save changes you want to conform can be read in properly /// The view created and passed to /// /// The read in object state after round trip (generate code file then read that code back in) /// If is , empty, or whitespace - protected static T2 RoundTrip(Action adjust, out T2 viewOut, [CallerMemberName] string? caller = null) + protected static T2 RoundTrip(IApplication app, Action adjust, out T2 viewOut, [CallerMemberName] string? caller = null) where T1 : View, new() where T2 : View, new() { @@ -110,19 +119,19 @@ protected static T2 RoundTrip(Action adjust, out T2 viewOut, const string fieldName = "myViewOut"; - var viewToCode = new ViewToCode(); + var viewToCode = new ViewToCode(app); var file = new FileInfo(caller + ".cs"); var designOut = viewToCode.GenerateNewView(file, "YourNamespace", typeof(T1)); viewOut = (T2)ViewFactory.Create(typeof(T2)); - OperationManager.Instance.Do(new AddViewOperation(viewOut, designOut, fieldName)); + OperationManager.Instance.Do(new AddViewOperation(app, viewOut, designOut, fieldName)); adjust((Design)viewOut.Data, viewOut); viewToCode.GenerateDesignerCs(designOut, typeof(T1)); - var codeToView = new CodeToView(designOut.SourceCode); + var codeToView = new CodeToView(app, designOut.SourceCode); var designBackIn = codeToView.CreateInstance(); return designBackIn.View @@ -133,14 +142,15 @@ protected static T2 RoundTrip(Action adjust, out T2 viewOut, /// /// Performs a mouse drag from the first coordinates to the second (in screen space) /// + /// The IApplication instance to use. /// The root Design. Make sure you have added it to and run /// X coordinate to start drag at /// Y coordinate to start drag at /// X coordinate to end drag at /// Y coordinate to end drag at - protected static void MouseDrag(Design root, int x1, int y1, int x2, int y2) + protected static void MouseDrag(IApplication app, Design root, int x1, int y1, int x2, int y2) { - var mm = new MouseManager(); + var mm = new MouseManager(app); mm.HandleMouse( new MouseEventArgs diff --git a/tests/TextViewTests.cs b/tests/TextViewTests.cs index ab05a687..b8b766c8 100644 --- a/tests/TextViewTests.cs +++ b/tests/TextViewTests.cs @@ -12,7 +12,7 @@ public void TestSettingToNull() { var tv = new TextView(); - var d = new Design(new SourceCodeFile("Blah.cs"), "mytv", tv); + var d = new Design(App, new SourceCodeFile("Blah.cs"), "mytv", tv); tv.Data = d; tv.Text = "fff"; diff --git a/tests/UI/MouseManagerTests.cs b/tests/UI/MouseManagerTests.cs index 287c808a..a08c7804 100644 --- a/tests/UI/MouseManagerTests.cs +++ b/tests/UI/MouseManagerTests.cs @@ -14,14 +14,14 @@ internal class MouseManagerTests : Tests public void DragResizeView( [ValueSource( nameof( DragResizeView_Types ) )] T dummy ) where T : View, new( ) { - Design d = Get10By10View( ); + Design d = Get10By10View(App); Assume.That( dummy, Is.TypeOf( ) ); using T view = ViewFactory.Create( ); view.Width = 8; view.Height = 1; - Design design = new( d.SourceCode, "myView", view ); + Design design = new(App, d.SourceCode, "myView", view ); view.Data = design; d.View.Add( view ); @@ -31,7 +31,7 @@ public void DragResizeView( [ValueSource( nameof( DragResizeView_Types ) )] T } Assert.That( view.GetContentSize().Width, Is.EqualTo( 8 ) ); - MouseManager mgr = new( ); + MouseManager mgr = new(App); // we haven't done anything yet Assert.Multiple( ( ) => @@ -93,14 +93,14 @@ public void DragResizeView( [ValueSource( nameof( DragResizeView_Types ) )] T [Test] public void DragResize_ShadowButton() { - Design d = Get10By10View(); + Design d = Get10By10View(App); using Button btn = ViewFactory.Create