Browse Source

Added Main to Scenario. Updated a few scenarios to test out.

Tig 1 year ago
parent
commit
fffae452e2

+ 5 - 3
Terminal.Gui/Application.cs

@@ -93,7 +93,7 @@ public static partial class Application
         {
             t.Running = false;
 #if DEBUG_IDISPOSABLE
-            // Don't dispose the tolevels. It's up to caller dispose them
+            // Don't dispose the toplevels. It's up to caller dispose them
             Debug.Assert (t.WasDisposed);
 #endif
         }
@@ -105,7 +105,7 @@ public static partial class Application
         if (Top is { })
         {
             Debug.Assert (Top.WasDisposed);
-            // If End wasn't called _latestClosedRunStateToplevel may be null
+            // If End wasn't called _cachedRunStateToplevel may be null
             if (_cachedRunStateToplevel is { })
             {
                 Debug.Assert (_cachedRunStateToplevel.WasDisposed);
@@ -246,7 +246,8 @@ public static partial class Application
         // multiple times. We need to do this because some settings are only
         // valid after a Driver is loaded. In this cases we need just 
         // `Settings` so we can determine which driver to use.
-        Load (true);
+        // Don't reset, so we can inherit the theme from the previous run.
+        Load (false);
         Apply ();
 
         // Ignore Configuration for ForceDriver if driverName is specified
@@ -350,6 +351,7 @@ public static partial class Application
     /// </remarks>
     public static void Shutdown ()
     {
+        // TODO: Throw an exception if Init hasn't been called.
         ResetState ();
         PrintJsonErrors ();
     }

+ 2 - 3
Terminal.Gui/Configuration/ConfigurationManager.cs

@@ -147,9 +147,8 @@ public static class ConfigurationManager
         {
             if (_settings is null)
             {
-                throw new InvalidOperationException (
-                                                     "ConfigurationManager has not been initialized. Call ConfigurationManager.Reset() before accessing the Settings property."
-                                                    );
+                // If Settings is null, we need to initialize it.
+                Reset ();
             }
 
             return _settings;

+ 19 - 16
UICatalog/Scenario.cs

@@ -88,18 +88,6 @@ public class Scenario : IDisposable
     /// </summary>
     public Window Win { get; set; }
 
-    public void Dispose ()
-    {
-        // BUGBUG: Top should have already been disposed. We dispose it here until we can fix the scenarios that are doing it wrong.
-        Top?.Dispose ();
-
-        // We created Win, so we Dispose it.
-        Win?.Dispose ();
-
-        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
-        Dispose (true);
-        GC.SuppressFinalize (this);
-    }
 
     /// <summary>
     ///     Helper function to get the list of categories a <see cref="Scenario"/> belongs to (defined in
@@ -140,6 +128,15 @@ public class Scenario : IDisposable
         return objects.OrderBy (s => s.GetName ()).ToList ();
     }
 
+
+    public virtual void Main ()
+    {
+        Init ();
+        Setup ();
+        Run ();
+    }
+
+
     /// <summary>
     ///     Helper that calls <see cref="Application.Init"/> and creates the default <see cref="Terminal.Gui.Window"/> implementation with a frame and label
     ///     showing the name of the <see cref="Scenario"/> and logic to exit back to the Scenario picker UI. Override
@@ -186,7 +183,7 @@ public class Scenario : IDisposable
     /// </remarks>
     public virtual void Run ()
     {
-        // Must explicit call Application.Shutdown method to shutdown.
+        // Must explicitly call Application.Shutdown method to shutdown.
         Application.Run (Top);
     }
 
@@ -197,6 +194,13 @@ public class Scenario : IDisposable
     /// <summary>Gets the Scenario Name + Description with the Description padded based on the longest known Scenario name.</summary>
     /// <returns></returns>
     public override string ToString () { return $"{GetName ().PadRight (_maxScenarioNameLen)}{GetDescription ()}"; }
+    
+    public void Dispose ()
+    {
+        // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
+        Dispose (true);
+        GC.SuppressFinalize (this);
+    }
 
     protected virtual void Dispose (bool disposing)
     {
@@ -204,11 +208,10 @@ public class Scenario : IDisposable
         {
             if (disposing)
             {
-                // TODO: dispose managed state (managed objects)
+                Top?.Dispose ();
+                Win?.Dispose ();
             }
 
-            // TODO: free unmanaged resources (unmanaged objects) and override finalizer
-            // TODO: set large fields to null
             _disposedValue = true;
         }
     }

+ 14 - 0
UICatalog/Scenarios/BackgroundWorkerCollection.cs

@@ -354,6 +354,20 @@ public class BackgroundWorkerCollection : Scenario
                 Source = new ListWrapper (_log)
             };
             Add (_listLog);
+
+            Closing += WorkerApp_Closing;
+        }
+        private void WorkerApp_Closing (object sender, ToplevelClosingEventArgs e)
+        {
+            Toplevel top = Application.OverlappedChildren.Find (x => x.Data.ToString () == "WorkerApp");
+
+            if (Visible && top == this)
+            {
+                Visible = false;
+                e.Cancel = true;
+
+                Application.OverlappedMoveNext ();
+            }
         }
 
         public void CancelWorker ()

+ 20 - 23
UICatalog/Scenarios/ChineseUI.cs

@@ -6,21 +6,18 @@ namespace UICatalog.Scenarios;
 [ScenarioCategory ("Unicode")]
 public class ChineseUI : Scenario
 {
-    public override void Init ()
+    public override void Main ()
     {
         Application.Init ();
 
-        Toplevel top = new ();
-
         var win = new Window
         {
-            Title = "Test",
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}",
             X = 0,
             Y = 0,
             Width = Dim.Fill (),
             Height = Dim.Fill ()
         };
-        top.Add (win);
 
         var buttonPanel = new FrameView
         {
@@ -35,20 +32,20 @@ public class ChineseUI : Scenario
         var btn = new Button { X = 1, Y = 1, Text = "你" }; // v1: A
 
         btn.Accept += (s, e) =>
-                       {
-                           int result = MessageBox.Query (
-                                                          "Confirm",
-                                                          "Are you sure you want to quit ui?",
-                                                          0,
-                                                          "Yes",
-                                                          "No"
-                                                         );
-
-                           if (result == 0)
-                           {
-                               Application.RequestStop ();
-                           }
-                       };
+                      {
+                          int result = MessageBox.Query (
+                                                         "Confirm",
+                                                         "Are you sure you want to quit ui?",
+                                                         0,
+                                                         "Yes",
+                                                         "No"
+                                                        );
+
+                          if (result == 0)
+                          {
+                              Application.RequestStop ();
+                          }
+                      };
 
         buttonPanel.Add (
                          btn,
@@ -56,10 +53,10 @@ public class ChineseUI : Scenario
                          new Button { X = 22, Y = 1, Text = "呀" } // v1: C
                         );
 
-        Application.Run (top);
+        Application.Run (win);
 
-        top.Dispose ();
-    }
+        win.Dispose ();
 
-    public override void Run () { }
+        Application.Shutdown ();
+    }
 }

+ 17 - 26
UICatalog/Scenarios/Generic.cs

@@ -4,37 +4,28 @@ namespace UICatalog.Scenarios;
 
 [ScenarioMetadata ("Generic", "Generic sample - A template for creating new Scenarios")]
 [ScenarioCategory ("Controls")]
-public class MyScenario : Scenario
+public sealed class MyScenario : Scenario
 {
-    public override void Init ()
+    public override void Main ()
     {
-        // The base `Scenario.Init` implementation:
-        //  - Calls `Application.Init ()`
-        //  - Adds a full-screen Window to Application.Top with a title
-        //    that reads "Press <hotkey> to Quit". Access this Window with `this.Win`.
-        //  - Sets the Theme & the ColorScheme property of `this.Win` to `colorScheme`.
-        // To override this, implement an override of `Init`.
-
-        //base.Init ();
-
-        // A common, alternate, implementation where `this.Win` is not used is below. This code
-        // leverages ConfigurationManager to borrow the color scheme settings from UICatalog:
-
+        // Init
         Application.Init ();
-        ConfigurationManager.Themes.Theme = Theme;
-        ConfigurationManager.Apply ();
-        Top = new Toplevel ();
-        Top.ColorScheme = Colors.ColorSchemes [TopLevelColorScheme];
-    }
 
-    public override void Setup ()
-    {
-        // Put scenario code here (in a real app, this would be the code
-        // that would setup the app before `Application.Run` is called`).
-        // With a Scenario, after UI Catalog calls `Scenario.Setup` it calls
-        // `Scenario.Run` which calls `Application.Run`. Example:
+        // Setup - Create a top-level application window and configure it.
+        Window appWindow = new ()
+        {
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+        };
 
         var button = new Button { X = Pos.Center (), Y = Pos.Center (), Text = "Press me!" };
-        Top.Add (button);
+        button.Accept += (s, e) => MessageBox.ErrorQuery ("Error", "You pressed the button!", "Ok");
+        appWindow.Add (button);
+
+        // Run - Start the application.
+        Application.Run (appWindow);
+        appWindow.Dispose ();
+
+        // Shutdown - Calling Application.Shutdown is required.
+        Application.Shutdown ();
     }
 }

+ 111 - 107
UICatalog/Scenarios/Notepad.cs

@@ -12,15 +12,92 @@ public class Notepad : Scenario
 {
     private TabView _focusedTabView;
     private StatusItem _lenStatusItem;
-    private int _numbeOfNewTabs = 1;
+    private int _numNewTabs = 1;
     private TabView _tabView;
 
-    // Don't create a Window, just return the top-level view
-    public override void Init ()
+    public override void Main ()
     {
         Application.Init ();
-        Top = new ();
-        Top.ColorScheme = Colors.ColorSchemes ["Base"];
+
+        Toplevel top = new ();
+
+        var menu = new MenuBar
+        {
+            Menus =
+            [
+                new (
+                     "_File",
+                     new MenuItem []
+                     {
+                         new (
+                              "_New",
+                              "",
+                              () => New (),
+                              null,
+                              null,
+                              KeyCode.N
+                              | KeyCode.CtrlMask
+                              | KeyCode.AltMask
+                             ),
+                         new ("_Open", "", () => Open ()),
+                         new ("_Save", "", () => Save ()),
+                         new ("Save _As", "", () => SaveAs ()),
+                         new ("_Close", "", () => Close ()),
+                         new ("_Quit", "", () => Quit ())
+                     }
+                    ),
+                new (
+                     "_About",
+                     "",
+                     () => MessageBox.Query ("Notepad", "About Notepad...", "Ok")
+                    )
+            ]
+        };
+        top.Add (menu);
+
+        _tabView = CreateNewTabView ();
+
+        _tabView.Style.ShowBorder = true;
+        _tabView.ApplyStyleChanges ();
+
+        // Start with only a single view but support splitting to show side by side
+        var split = new TileView (1) { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
+        split.Tiles.ElementAt (0).ContentView.Add (_tabView);
+        split.LineStyle = LineStyle.None;
+
+        top.Add (split);
+
+        _lenStatusItem = new (KeyCode.CharMask, "Len: ", null);
+
+        var statusBar = new StatusBar (
+                                       new []
+                                       {
+                                           new (
+                                                Application.QuitKey,
+                                                $"{Application.QuitKey} to Quit",
+                                                () => Quit ()
+                                               ),
+
+                                           // These shortcut keys don't seem to work correctly in linux 
+                                           //new StatusItem(Key.CtrlMask | Key.N, "~^O~ Open", () => Open()),
+                                           //new StatusItem(Key.CtrlMask | Key.N, "~^N~ New", () => New()),
+
+                                           new (KeyCode.CtrlMask | KeyCode.S, "~^S~ Save", () => Save ()),
+                                           new (KeyCode.CtrlMask | KeyCode.W, "~^W~ Close", () => Close ()),
+                                           _lenStatusItem
+                                       }
+                                      );
+        _focusedTabView = _tabView;
+        _tabView.SelectedTabChanged += TabView_SelectedTabChanged;
+        _tabView.Enter += (s, e) => _focusedTabView = _tabView;
+
+        top.Add (statusBar);
+        top.Ready += (s, e) => New ();
+
+        Application.Run (top);
+        top.Dispose ();
+
+        Application.Shutdown ();
     }
 
     public void Save () { Save (_focusedTabView, _focusedTabView.SelectedTab); }
@@ -58,97 +135,24 @@ public class Notepad : Scenario
         if (string.IsNullOrWhiteSpace (fd.Path))
         {
             fd.Dispose ();
+
             return false;
         }
 
         if (fd.Canceled)
         {
             fd.Dispose ();
+
             return false;
         }
 
-        tab.File = new FileInfo (fd.Path);
+        tab.File = new (fd.Path);
         tab.Text = fd.FileName;
         tab.Save ();
 
         fd.Dispose ();
-        return true;
-    }
-
-    public override void Setup ()
-    {
-        var menu = new MenuBar
-        {
-            Menus =
-            [
-                new MenuBarItem (
-                                 "_File",
-                                 new MenuItem []
-                                 {
-                                     new (
-                                          "_New",
-                                          "",
-                                          () => New (),
-                                          null,
-                                          null,
-                                          KeyCode.N
-                                          | KeyCode.CtrlMask
-                                          | KeyCode.AltMask
-                                         ),
-                                     new ("_Open", "", () => Open ()),
-                                     new ("_Save", "", () => Save ()),
-                                     new ("Save _As", "", () => SaveAs ()),
-                                     new ("_Close", "", () => Close ()),
-                                     new ("_Quit", "", () => Quit ())
-                                 }
-                                ),
-                new MenuBarItem (
-                                 "_About",
-                                 "",
-                                 () => MessageBox.Query ("Notepad", "About Notepad...", "Ok")
-                                )
-            ]
-        };
-        Top.Add (menu);
-
-        _tabView = CreateNewTabView ();
-
-        _tabView.Style.ShowBorder = true;
-        _tabView.ApplyStyleChanges ();
-
-        // Start with only a single view but support splitting to show side by side
-        var split = new TileView (1) { X = 0, Y = 1, Width = Dim.Fill (), Height = Dim.Fill (1) };
-        split.Tiles.ElementAt (0).ContentView.Add (_tabView);
-        split.LineStyle = LineStyle.None;
-
-        Top.Add (split);
-
-        _lenStatusItem = new StatusItem (KeyCode.CharMask, "Len: ", null);
-
-        var statusBar = new StatusBar (
-                                       new []
-                                       {
-                                           new (
-                                                Application.QuitKey,
-                                                $"{Application.QuitKey} to Quit",
-                                                () => Quit ()
-                                               ),
-
-                                           // These shortcut keys don't seem to work correctly in linux 
-                                           //new StatusItem(Key.CtrlMask | Key.N, "~^O~ Open", () => Open()),
-                                           //new StatusItem(Key.CtrlMask | Key.N, "~^N~ New", () => New()),
-
-                                           new (KeyCode.CtrlMask | KeyCode.S, "~^S~ Save", () => Save ()),
-                                           new (KeyCode.CtrlMask | KeyCode.W, "~^W~ Close", () => Close ()),
-                                           _lenStatusItem
-                                       }
-                                      );
-        _focusedTabView = _tabView;
-        _tabView.SelectedTabChanged += TabView_SelectedTabChanged;
-        _tabView.Enter += (s, e) => _focusedTabView = _tabView;
 
-        Top.Add (statusBar);
-        Top.Ready += (s, e) => New ();
+        return true;
     }
 
     private void Close () { Close (_focusedTabView, _focusedTabView.SelectedTab); }
@@ -244,7 +248,7 @@ public class Notepad : Scenario
         return tv;
     }
 
-    private void New () { Open (null, $"new {_numbeOfNewTabs++}"); }
+    private void New () { Open (null, $"new {_numNewTabs++}"); }
 
     private void Open ()
     {
@@ -264,7 +268,7 @@ public class Notepad : Scenario
                 }
 
                 // TODO should open in focused TabView
-                Open (new FileInfo (path), Path.GetFileName (path));
+                Open (new (path), Path.GetFileName (path));
             }
         }
 
@@ -335,27 +339,27 @@ public class Notepad : Scenario
 
         if (e.Tab == null)
         {
-            items = new MenuBarItem (
-                                     new MenuItem [] { new ("Open", "", () => Open ()) }
-                                    );
+            items = new (
+                         new MenuItem [] { new ("Open", "", () => Open ()) }
+                        );
         }
         else
         {
             var tv = (TabView)sender;
             var t = (OpenedFile)e.Tab;
 
-            items = new MenuBarItem (
-                                     new MenuItem []
-                                     {
-                                         new ("Save", "", () => Save (_focusedTabView, e.Tab)),
-                                         new ("Close", "", () => Close (tv, e.Tab)),
-                                         null,
-                                         new ("Split Up", "", () => SplitUp (tv, t)),
-                                         new ("Split Down", "", () => SplitDown (tv, t)),
-                                         new ("Split Right", "", () => SplitRight (tv, t)),
-                                         new ("Split Left", "", () => SplitLeft (tv, t))
-                                     }
-                                    );
+            items = new (
+                         new MenuItem []
+                         {
+                             new ("Save", "", () => Save (_focusedTabView, e.Tab)),
+                             new ("Close", "", () => Close (tv, e.Tab)),
+                             null,
+                             new ("Split Up", "", () => SplitUp (tv, t)),
+                             new ("Split Down", "", () => SplitDown (tv, t)),
+                             new ("Split Right", "", () => SplitRight (tv, t)),
+                             new ("Split Left", "", () => SplitLeft (tv, t))
+                         }
+                        );
         }
 
         Rectangle screen = ((View)sender).BoundsToScreen (new (e.MouseEvent.X, e.MouseEvent.Y, 0, 0));
@@ -368,14 +372,6 @@ public class Notepad : Scenario
 
     private class OpenedFile : Tab
     {
-        public FileInfo File { get; set; }
-
-        /// <summary>The text of the tab the last time it was saved</summary>
-        /// <value></value>
-        public string SavedText { get; set; }
-
-        public bool UnsavedChanges => !string.Equals (SavedText, View.Text);
-
         public OpenedFile CloneTo (TabView other)
         {
             var newTab = new OpenedFile { DisplayText = base.Text, File = File };
@@ -407,6 +403,8 @@ public class Notepad : Scenario
             };
         }
 
+        public FileInfo File { get; set; }
+
         public void RegisterTextViewEvents (TabView parent)
         {
             var textView = (TextView)View;
@@ -436,6 +434,12 @@ public class Notepad : Scenario
                               };
         }
 
+        /// <summary>The text of the tab the last time it was saved</summary>
+        /// <value></value>
+        public string SavedText { get; set; }
+
+        public bool UnsavedChanges => !string.Equals (SavedText, View.Text);
+
         internal void Save ()
         {
             string newText = View.Text;

+ 4 - 6
UICatalog/UICatalog.cs

@@ -290,11 +290,10 @@ internal class UICatalogApp
             Application.Init (driverName: _forceDriver);
             _selectedScenario.Theme = _cachedTheme;
             _selectedScenario.TopLevelColorScheme = _topLevelColorScheme;
-            _selectedScenario.Init ();
-            _selectedScenario.Setup ();
-            _selectedScenario.Run ();
+            _selectedScenario.Main ();
             _selectedScenario.Dispose ();
             _selectedScenario = null;
+            // TODO: Throw if shutdown was not called already
             Application.Shutdown ();
             VerifyObjectsWereDisposed ();
 
@@ -322,13 +321,12 @@ internal class UICatalogApp
             Apply ();
             scenario.Theme = _cachedTheme;
             scenario.TopLevelColorScheme = _topLevelColorScheme;
-            scenario.Init ();
-            scenario.Setup ();
-            scenario.Run ();
+            scenario.Main ();
             scenario.Dispose ();
 
             // This call to Application.Shutdown brackets the Application.Init call
             // made by Scenario.Init() above
+            // TODO: Throw if shutdown was not called already
             Application.Shutdown ();
 
             VerifyObjectsWereDisposed ();