-
Notifications
You must be signed in to change notification settings - Fork 728
Description
The Cancellable Work Pattern is integral to Terminal.Gui, enabling flexible, decoupled workflows across scheme management, rendering, input, commands, and properties. Proposed helper classes streamline its implementation, particularly for property changes like Orientation. The Scheme system leverages the CWP for dynamic styling, while the Command system’s updates (Command.Activate, Handled, PropagatedCommands) enhance clarity and coordination. Ongoing documentation efforts ensure these improvements are well-communicated, supporting robust UI development in v2_develop.
This will be addressed in this PR:
Original Post
As mentioned in discussion #3206, event handling could use some TLC.
This issue is meant to be the main issue, though it may spawn others, depending on just how involved this ends up being.
Work items I wanted to address, many of which already have been partially completed in existing work on v2 or may not currently even exist/be problems in the current code, but I'm listing these out for completeness and as reminders for myself to at least confirm them all:
- Standardize event delegates according to design recommendations
- Basically, exactly how the Terminal.Gui design specification already says to do, but with an additional degree of scrutiny around the type arguments to
EventHandler<T>, considering potential needs for future changes/features added to TG.
- Basically, exactly how the Terminal.Gui design specification already says to do, but with an additional degree of scrutiny around the type arguments to
- OnX wrappers for raising events are public, but most should be
protected virtualand none should bepublic. - Declaring the actual events inside interfaces, which are then implemented by classes that need to expose those events.
- Making sure that events are first defined at the most-derived type that is reasonable or necessary for common handling (the interfaces will help with that, too).
- Ensure that, when relevant, derived classes ask their base class to raise the event, and that there are no virtual/overridden events nor any events hidden with
new(I don't think either of those last things exist in the code) - Ensuring that standard rules and practices for inheritance and related concepts such as overrides are followed as closely as possible.
- Consider and, if prudent, implement necessary constructs for thread-safety around event raising
- Including at least being aware that subscribers may provide an
async voidhandler that returns before the associated background work is actually complete. Though this doesn't necessarily mean actively attempting to defend against it, since that's 100% the consumer's fault.
- Including at least being aware that subscribers may provide an
- Ensure/implement more formal/recommended handling of exceptions thrown in subsribers' handlers, as appropriate, via the following methods, as appropriate:
- Stopping processing of the invocation list when an exception is caught and adding any relevant information to the stack trace before re-throwing the caught exception
- Cleaning up or undoing any work the wrapper has done, if possible.
- Cleaning up or undoing any work a handler has done, if it's safe to do so based on event or application state (this will probably be rare or not at all)
- Hard-crashing the application immediately, via Environment.FailFast, if/when appropriate
- Ensuring that raising of events (such as the wrappers themselves or the immediate call-sites of them) never throws exceptions, per design guidelines
- Ensuring that exceptions thrown by handlers are not swallowed by the wrappers
- If that behavior is desired and/or already exists anywhere, it will be modified to be an opt-in behavior, as that's a non-standard and counterindicated practice.
I think I'll start by getting an overall picture of all the events that exist and then work on creating appropriate interfaces that strike a balance between granularity and not needlessly creating tons of interfaces for no reason. Just as a guess based on what I know of TG, I'm betting there will probably be around 5ish interfaces, to group certain high-level categories of events common to types in specific hierarchies. But, we'll see. Could be more; Could be fewer.
Issues Potentially Impacted and/or Where Related Changes Are Needed
- Refactor
MouseEventandMouseEventEventArgsto simplify #3029 - InvokingKeyBindings event not invoked in OnInvokingKeyBindings overridden method. #3056
BeginInit/EndInitshould follow CWP #2235- Ability to set Action on StatusItem post creation #3070
- ConfigurationManager:
AppliedandUpdatedevents are clumsy #2871 - ProcessButtonClick strips any modifier keys from mouse events #2588
- TextValidateField doesn't show the cursor and doesn't have TextChanged event. #3189
Metadata
Metadata
Assignees
Labels
Type
Projects
Status