Skip to content
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

Attach event listeners upon attribute changes #189

Conversation

ZombieRaccoon
Copy link

I implemented the feature we discussed in #188, along with a couple of tiny improvements that presented themselves along the way.

A couple of notes about the end result:

  • I went with a simple linear search in EventDispatcher::DetachEvent, since I believe that only a relatively high listener count would warrant using binary search and I don't think that a UI library can reach that high a listener count for it to make the extra effort worthwhile.
  • In Element::OnAttributeChange it's necessary to traverse the whole dictionary to find attributes that start with "on", so for effectiveness' sake I converted the entire thing to build off of that.

Copy link
Owner

@mikke89 mikke89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Should be a nice little improvement.

I'm not sure it's working entirely correct in terms of replacing old on... attributes, see my comments for details. And I think we should also remove the listener when users remove the on... attribute.

We should add some tests to make sure it works as intended to the UnitTests suite, so that we know replacement and removal works properly. I'm also interested to see if the onload attribute is fired properly.

I did benchmark this just to be sure and I couldn't measure any regression, so that is all good!

Include/RmlUi/Core/Element.h Outdated Show resolved Hide resolved
Source/Core/Context.cpp Outdated Show resolved Hide resolved
Source/Core/Element.cpp Outdated Show resolved Hide resolved
Source/Core/Element.cpp Outdated Show resolved Hide resolved
Source/Core/Element.cpp Outdated Show resolved Hide resolved
Source/Core/EventDispatcher.h Show resolved Hide resolved
Source/Core/EventDispatcher.h Outdated Show resolved Hide resolved
Include/RmlUi/Core/Event.h Outdated Show resolved Hide resolved
Source/Core/EventDispatcher.cpp Outdated Show resolved Hide resolved
@mikke89 mikke89 added the enhancement New feature or request label May 15, 2021
@ZombieRaccoon
Copy link
Author

Trying to implement removal and taking the ability to set listener origin off the public interface actually gave me an idea for a different approach, which I think you'll also like. I'll push the commit soon.

Copy link
Owner

@mikke89 mikke89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this approach should work fine as far as I can tell.

Could you perhaps add some unit tests as well? Thanks!

Include/RmlUi/Core/Element.h Outdated Show resolved Hide resolved
@ZombieRaccoon
Copy link
Author

Yeah, this approach should work fine as far as I can tell.

Could you perhaps add some unit tests as well? Thanks!

Absolutely! Your original request didn't go unheard, it's just that I didn't manage to fit both into my time. I'll make sure to follow up with unit tests.

@ZombieRaccoon
Copy link
Author

@mikke89 have you thought about using a mocking framework? I'm in the midst of writing the unit tests and it'd come in quite handy. Seeing as the project is using doctest as its unit testing framework, I'd suggest trompeloeil based on some research on the matter. If you were to be in agreement, I'd integrate the library under Tests\Dependencies.

@mikke89
Copy link
Owner

mikke89 commented May 19, 2021

I don't really have any experience with mocking frameworks. I'm not really convinced by the reading I did on it, but if you think we can express some tests better I'll trust you on that. The library you mention looks good in terms of integration and licensing.

@ZombieRaccoon
Copy link
Author

In my opinion, the most important thing that mocking frameworks save you is writing custom fake implementations like the one I resorted to in FakeEventListenerInstancer.h. The main goal of such constructs is to verify certain dynamic characteristics of software - whether the InstanceEventListener method of the registered EventListenerInstancer implementation is invoked with certain parameters, in this particular case - that would be extremely tedious work otherwise because of the inherent opaqueness of object-oriented architectures from certain points of entry.

I'll implement the same thing using the library I've mentioned and you'll immediately see the difference in readability and likely recognize possible future use or even potential test refactors stemming from the opportunities its expressive power provides.

@mikke89
Copy link
Owner

mikke89 commented May 19, 2021

I see, please go ahead with it, I'm eager to see the results. Good work on the tests so far, thanks for the thorough work!

@mikke89
Copy link
Owner

mikke89 commented May 21, 2021

There you go, compiler finally gives in ;)

Let me know when you feel happy with it by marking it as ready. Could you clean up the commit history? I'm thinking one commit for the library integration, one or two for the core changes, and one or two for the unit tests. Thanks!

@ZombieRaccoon ZombieRaccoon force-pushed the feature/event-listener-on-attribute-change branch from bbc6f5d to 53e2f0c Compare May 22, 2021 05:29
@ZombieRaccoon
Copy link
Author

Yeah, that warning from GCC was interesting to say the least. Anyway, I believe that the deed is done. I do agree that the commit history got a little cluttered, so I cleaned it up.

@mikke89 mikke89 merged commit 50041d7 into mikke89:master May 22, 2021
@mikke89
Copy link
Owner

mikke89 commented May 22, 2021

Looks good, thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants