-
Notifications
You must be signed in to change notification settings - Fork 699
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 - #2359 All events now use sender EventArgs #2406
Conversation
- Loaded, - Ready - Unloaded - AllChildClosed
- Activate - Deactivate - ChildClosed - Closed - ChildLoaded - ChildUnloaded
20 down, 48 to go 😓 |
Terminal.Gui/Core/View.cs
Outdated
view.IsAdded = true; | ||
view.x ??= view.frame.X; | ||
view.y ??= view.frame.Y; | ||
view.width ??= view.frame.Width; | ||
view.height ??= view.frame.Height; | ||
|
||
view.Added?.Invoke (this); | ||
view.Added?.Invoke (this,e); |
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.
Hmn so in the old version of virtual void OnAdded (View view)
the view
passed into this method was not passed on to Invoke
. Instead this
was passed to Invoke
.
That means that the view
reported by the Added
event is the parent and not the child being added.
This is why the test is failing. Added_Removed
asserts the following:
v.Added += (s,e) => {
Assert.True (v.SuperView == e.View);
};
I propose we change this test to instead say
v.Added += (s,e) => {
Assert.True (v.SuperView == s);
Assert.True (v == e.View);
};
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.
Actually I am confused about this test. This is what it looks like in v2_develop
(see below)
The description for the Added
event says:
Event fired when a subview is being added to this view.
But the test is registering the event on the child (v
) and then calling add on the parent (t
).
Is this to say then that Added
event covers both
- When a subview is added to yourself
- When you are added as a subview to someone else?
public void Added_Removed ()
{
var v = new View (new Rect (0, 0, 10, 24));
var t = new View ();
v.Added += (View e) => {
Assert.True (v.SuperView == e);
};
v.Removed += (View e) => {
Assert.True (v.SuperView == null);
};
t.Add (v);
Assert.True (t.Subviews.Count == 1);
t.Remove (v);
Assert.True (t.Subviews.Count == 0);
}
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.
I agree. This event is normally used by the subview to get notified when the superview has add it and so your logic is perfectly right. By the way thanks for great effort.
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.
When a subview is added to yourself
When you are added as a subview to someone else?
Ok this is not the case. I think the description and my expectation is in fact wrong. Based on the Add
method, the Added event
is fired on a View
when it is aded to a parent. And not "when a subview is being added" [to it].
public virtual void Add (View view)
{
if (view == null)
return;
[...]
OnAdded (view);
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.
Yes, that why it's invoke view.Added?.Invoke (this);
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.
I propose this change, because if the user use the arg passed will think it's the superview and that why the test is failing.
public virtual void OnAdded (ViewEventArgs e)
{
var view = e.View;
view.IsAdded = true;
view.x ??= view.frame.X;
view.y ??= view.frame.Y;
view.width ??= view.frame.Width;
view.height ??= view.frame.Height;
e.View = this;
view.Added?.Invoke (this, e);
}
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.
The same for the OnRemoved
;
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.
Ok I have added a new EventArgs
called SuperViewChangedEventArgs
so it is clear to user what view is being talked about (since it contains both Parent
and Child
). Test now passes as:
Note: I thought about calling it ParentChangedEventArgs
but its called SuperView
in View
so I thought better stick to it. Although I did go with Parent
and Child
for the properties.
[Fact]
public void Added_Removed ()
{
var v = new View (new Rect (0, 0, 10, 24));
var t = new View ();
v.Added += (s,e) => {
Assert.Same (v.SuperView, e.Parent);
Assert.Same (t, e.Parent);
Assert.Same (v, e.Child);
};
v.Removed += (s, e) => {
Assert.Same (t, e.Parent);
Assert.Same (v, e.Child);
Assert.True (v.SuperView == null);
};
t.Add (v);
Assert.True (t.Subviews.Count == 1);
t.Remove (v);
Assert.True (t.Subviews.Count == 0);
}
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.
Much better solution, congrats for your brilliant implementation.
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.
Fantastic stuff.
What about cancelable events?
Thanks. I'm keeping this in draft though as still working my way through all the
Hopefully most would already use an event args with Handled (or similar) so should be ok I think? |
Only 7 more to go 🏁 👁️ but looks like they will all need event args classes. I've added any new EventArgs classes I've created in the EventArgs folder but using the normal namespace ( |
@tznind I submitted the PR tznind#163 to help a little on your awesome work. Thanks. |
Well, I think we sure don't need to create a default |
That's right, Now that we are using |
Now the problem is the lot of warnings due the use of |
Hmn thats odd, must have been a bad autocomplete suggestion or a side effect of refactoring command I used to pull out to seperate file. Seems they started appearing in 2ed71e2 I didn't mean to add it so I will just get rid of them. |
Ah actually some of them were added by @tig for example in UICatalog in c94f916 See c94f916#diff-81646b59a9d4df0e26e5e72c0dddde6f499db0ae941481edcd40326d5ec800eeR17-R18 Maybe this is a work in progress, I had better not go chop them out just yet. |
Ah ok we wait for @tig answer. Thanks. |
I'm quite confused about nullable. It just confuses the hell out of me. We need a clear and concise set of guidelines for v2. I'm not smart enough (apparently) to author such a thing. |
Before NRTC# has value types and classes (aka reference types). Value types (int, bool, float, struct) cannot be null. Classes can be null. A while ago the Classes can be null, so You do not need the NRT - Nullable Reference TypesYou can turn on NRT for a file with the Enabling NRT changes Obviously when you turn this on you immediately start getting compiler warnings that basically say: "You told me this variable will never be null but then you assigned it null!" So you have to manually add a question mark to the class i.e. You also have to do this for methods e.g. if you return null from a method it needs to have the question mark on the class name returned too e.g. This means you end up with questionmarks all over the place to limited value. You can see this when methods like Worse still is that when you call string? name = thing.ToString(); or (my prefered option) string name = thing.ToString() ?? throw new Exception("ToString method unexpectedly returned null"); The first case has the big down side that anyone who references or takes When is NRT a good ideaNRT is a great idea when you are first starting a project (Terminal.Gui.Designer has it for example) since it is not too much work when writing code to make informed decisions about whether a class instance should be allowed to be null. NRT does make you think a lot more about nullability and if you have the spare effort to put in (think 2-3 weeks of solid work for a library our size) then it can reduce the number of null references client libraries end up with. |
Well if it's for to have sure that a class never can be null and ensuring that all the consumers are instantiating a non null class, that really a good advantage of NRT. But if it's for end up putting |
Yes that is the trade off. NRT is great for a new codebase. But when you start getting into NRT in an existing big codebase then it starts to proliferate throughout the codebase. Despite the ability to enable it per file it still ends up spilling everywhere. So you either spend a lot of effort doing it properly or you do a half way job (either suppressing the warnings or putting But its a big enough task that we should probably make a branch specifically for implementing NRT if that's the way we want to go down rather than just turning it on ad-hoc as part of other work. |
What do y'all think about adopting |
I think this is a worthy goal but maybe do it as a seperate PR? |
Tests are passing and the only warnings are around those nullability issues. I'm happy if you are ready to merge this? |
Excellent work @tznind !! This is huge. |
/// than the wrapped <see cref="MouseEvent"/> class and is used for the events defined on <see cref="View"/> | ||
/// and subclasses of View (e.g. <see cref="View.MouseEnter"/> and <see cref="View.MouseClick"/>). | ||
/// </summary> | ||
public class MouseEventEventArgs : EventArgs { |
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.
Looks like I misnamed this now as MouseEventEventArgs
instead of MouseEventArgs
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.
Fix is in #2435
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.
@tznind I did the change on purpose to MouseEventEventArgs
because it's related with the MouseEvent
class, for the same reason why there is a MouseFlagsEventArgs
related with MouseFlags
enum.
Fixes - #2359 Include a terse summary of the change or which issue is fixed.
Pull Request checklist:
CTRL-K-D
to automatically reformat your files before committing.dotnet test
before commit///
style comments)