Skip to content

Discuss - There should only be one (Application.Top) #2502

@tig

Description

@tig

This is all debatable, but here's my thinking:

TopLevel is currently built around several concepts that are muddled and have led to overly complex code:

  • A Toplevel is a view that can host a Menu and StatusBar. Other views cannot.
  • A Toplevel can run modally, and have its own Runstate (via Application.Run(). It is unclear why ANY VIEW can't be run this way, but it seems to be a limitation of the current implementation.
  • A Toplevel can be moved by the user (actually only the Toplevel subclass, Window). It should be possible to enable the moving of any View (e.g. View.CanMove = true or similar).

Application is the place where all of the above TopLevel gunk happens in addition to other "application" stuff.

The MdiContainer stuff is complex, perhaps overly so, and is not actually used by anyone outside of the project. It's also misnamed because Terminal.Gui doesn't actually support "documents" nor does it have a full "MDI" system like Windows (did). It seems to represent features useful in overlapping Views, but it is super confusing on how this works, and the naming doesn't help. Application is full of code like if (MdiTop != null && top != MdiTop && top != Current && Current?.Running == false && !top.Running) which just screams poor-OO design and fragility. This all can be refactored to support specific scenarios and thus be simplified.

My proposal:

  • Application.Top should be set when an app starts, and should not be changeable. Changing it after Application.Begin has been called should result in an exception.

  • The Application class should do the following (and nothing else; other things should be moved elsewhere as appropriate):

    • Application-wide settings (like default quit key and diagnostics)
    • Initializing and configuring the console driver
    • Providing Runstate and managing the Mainloop
    • Providing a simple API for starting applications either with a default Top view or a developer-provided one
    • Proxying mouse/keyboard events from the driver to the Top
  • Stuff that will be moved out of (or deleted) from Application:

    • All the Mdi stuff
    • All the tracking of Current and toplevels. This stuff will just be part of View.
    • Code for moving from view to view in the focus or z-order heirarchies
  • All Views should support overlapping within a superview and have a menubar and statusbar.

  • All Views should support having subviews be overlapping

  • All the insane logic in Application.cs for dealing with Current, the stack of toplevels, etc, should be moved into the View hierarchy (either as part of View directly or a helper class)... and radically simplified. This includes getting rid of all of the Mdi stuff.

  • Any View can be run modally (as a popup that captures all user input) can be executed with a new API: view.Run(popupView) as is today, except they don't have to be of type Toplevel. When such a view is run, view.Modal is set to true letting the view know it's modal. We'll retain Application.Run() for backward compatibility, but it will simply do Application.Top.Run(popupView).

Making this happen requires the following to be done first:

But it seems doable, and will significantly simplify the programming model (and codebase).

What do folks think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions