Terminal.Gui icon indicating copy to clipboard operation
Terminal.Gui copied to clipboard

`Scenario` is complex, confusing, and causes errors

Open tig opened this issue 10 months ago • 2 comments

I over-engineered Scenario and tried to be both too helpful to devs and too cute. My intent was to make it super easy to create new scenarios. I thought it would be neat if Scenario developers only had to write a Setup override and the "default" logic in Init and Run would do magic for them. I also had UICatalog call Application.Shutdown when the Scenario exited instead of forcing Scenario authors to do this themselves.

This was a bad idea for these reasons:

  1. New developers looking at scenarios as examples don't see what ones supposed to do to setup/teardown a Terminal.Gui app. They don't see the proper way: Call Init, and ensure it's bracketed by a Shutdown, Call Run and make sure the Toplevel used gets disposed.
  2. It led to un-needed complexity in 4 overrides: Init, Setup, Run, and RequestStop. This is confusing to devs and a survey of the existing scenarios shows this confusion.
  3. It makes devs think that Application.Top can't be the actuall main view for the scenario, because Init, by default creates Win and adds it to Top.

My proposal:

  • Simplify Scenario to have only ONE virtual metods: Main. Developers should treat this just like the standard C# console app int Main (string [] args) method.
  • Change Init to NOT reset ConfigurationManager. This way whatever was configured in UI Catalog will naturally just pass onto the Scenario.
  • Change all Scenarios to merge their Init, Setup, and Run overrides into Main.

The Generic Scenario.Main will look like this:

    public override void Main ()
    {
        // Init
        Application.Init ();

        // 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!" };
        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 ();
    }

Originally posted by @tig in https://github.com/gui-cs/Terminal.Gui/issues/3339#issuecomment-2018897248

tig avatar Mar 25 '24 21:03 tig