-
Notifications
You must be signed in to change notification settings - Fork 696
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fixes #2579. MouseEvent/OnMouseEvent
are stoopid
#3281
Conversation
Not sure I love the consolidation of events goal there. If I want clicks, I don't want other mouse events. That's noise and I have to filter for it. The standard across many other frameworks, in multiple languages tends to be providing quite a few events, around mouse operations, such as MouseButtonDown, MouseButtonUp, Clicked, DoubleClicked, and pre-events for each of those, as well, to provide an intercept point if something needs to hijack and/or cancel it all. Heck, even look at what javascript has for standard web interactions on every displayable element in the DOM: |
Is a question on how the user want to handle it. All these events already exist on the |
Right. But the API for that is clumsy because it involves testing flags. See the cruft a the top of each OnMouseEvent override of "if not all these flags I don't care about". I'm prob not going to address this here but it is ugly. |
Each derived view must know what mouse events flags will be needed. They don't needed to tests for all flags they don't want. Only is needed to handle what they needed returning true and return false on the end or call the base class on flags that aren't needed. The reason they check for all flags they don't needed is for set focus on the view which is bad and can be done by call a method that do that on each flag the view need.
I agree, because the flags are checked twice, first to reject the unneeded flags and second to process each one that was referenced in the first. Is really ugly. Another flags users may need is check if the Ctrl, Alt, Shift keys were pressed along the mouse event. |
@tig did you already notice |
No, but thanks for the head's up. |
For now, I've met in the middle:
We can add additional, commonly used events, like |
…east makes them not public, so work can continue.
@BDisp & @dodexahedron this is ready for review. Future PRs will:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work. I only did some questions.
I started writing this a couple nights ago and apparently forgot to actually submit the comment. 😅 So... Here ya go...
Right. And there's no reason there can't also be a combined event like that (though it is kinda bad form). Lots of words that amount to "don't abuse events that way without a REALLY good reason." Expand if you like staring at diatribes in github comments.One of many problem is that having one event that covers multiple concepts creates a lot of unnecessary work for the publisher and all subscribers, when a subscriber only wants some or one of the events. It also leads to `EventHandler` delegates and their `T`s having to carry around dead weight. That's generation of garbage, heap allocations, and unclear behavior (and/or the need to document it heavily) in those cases where one or more fields, properties, or methods on that `T` are not relevant to a given event, yet the consumer can still interact with them. To prevent that requires throwing exceptions, but you're in an event handler and that's program crash territory, now (which is why you're not supposed to throw there). And, as a consumer of an API, I'm pretty annoyed when the API makes me do work that costs several lines at each event subscriber method that has to now do the work that events themselves already implicily would have done, when it would have cost the creator of the library just a few lines, per event, once per event, to avoid it all. If I, the consumer, need all of those events, I just subscribe to them all. Otherwise, why not simply have one delegate for the entire program called "OnStuff?" While that sounds absurd, that's the point. It is absurd, especially for what are already common/standard/expected behaviors. It costs us basically no effort (sometimes less, if you end up avoiding extra types to deal with handling dispatch....instead of letting events do what they do, which is dispatch). There's also a real performance cost to concatenating everything into one delegate/event. Each delegate is run in sequence, when you call .Invoke() on it. If I've got dozens of subscribers (not even a little bit unreasonable in even a smallish app), and if even one of them is expensive, crashes, or otherwise is a pain, ALL subscribers later in the chain just get to sit and wait while we do it all, for all listeners, whether the event that was just raised was even relevant to one out of a hundred of them. If you have unique events, all that melts away. There are a ton of concurrency pitfalls, many of which are so much easier to hit if you have that single universal If you just define the one, ALL calls to that event have to be synchronized, making an already hot path now extremely contentious, and difficult to debug, among other things. The UI latency can quickly grow to noticeable levels with that, especially if anything interesting changes and has to be re-calculated and re-drawn, and execution order still technically isn't guaranteed, so it's not like Another way to put it: You're basically using enums/strings/magic values/whatever and control flow statements like if/else and switch based on them in the place of named methods, when you do that. TFM...For R-ingWhether you read any of that or not, the below is key reading. Here are some excellent docs on delegates and events, and some concepts that build from there, at the bottom. Anyway... DelegatesSince events are essentially a special case of delegates, it's pretty clear why this doc series starts there first.
Events, or "Delegates 2: Method Dispatch Boogaloo" (I kid, but only mostly):
Something about stronger type-safety/static analysis? Huh?In what way? Well, the loosened guidance on event definitions (such as not being shamed into deriving the event args from EventArgs anymore), mostly. But be reasonable. Take Terminal.Gui, for example. But I wouldn't really go farther than that. Footnotes
|
Oh hey, and this is relevant to the above: https://learn.microsoft.com/en-us/dotnet/csharp/distinguish-delegates-events |
Yep yep. That's the goal. :) |
Fixes
Responder.MouseEvent
andView.OnMouseEvent
are backwards - Refactor #2579Proposed Changes/Todos
MouseEvent
fromResponder
toView
View.OnMouseEvent
andMouseEvent
into one method (calledView.OnMouseEvent
).MouseClick
event related thingsOnMouseClick
->protected
MouseClick
occurs for ANY click event (any button, single or double)OnMouseXX
protected internal` as a quick-fix workaround that at least makes them not public, so work can continue.Pull Request checklist:
CTRL-K-D
to automatically reformat your files before committing.dotnet test
before commit///
style comments)