In an example like you’re talking about where clicking a button does something to that particular button, it’d be crazy to use a listener at all - a special class of button that handles its own click event would be a much better, more OO solution.[/quote]
Well not always. The example of changing the color was a poor one (my fault). In cases where the button has to be modified to represent the state of the client application, then deriving a custom button is not a good solution. Say for example the event handler can have knowledge of application state, something that the derived button class cannot and should not have.
Also, a generic handler like the one we’re talking about may have to affect more than just the sender, but other parts of the application. Again, not something the derived button would know about.
[quote=“X-Ryl669”] Ok, searching is a lot faster because it is using integer instead of strings (of course, if you use a dynamic_cast then, the compiler generate RTTI code to check the conversion and then you directly loose the gain you expected).
…
At the same time, it is not with “no cost” like you are saying, because you have to cast it (which could lead to RTTI code if you use dynamic_cast or crash if you don’t), you have to take care of the usual pointer issues (if I delete it, it is going to crash when leaving the method), add documentation for the pointer issues in order to avoid them, all of these being a pain when maintaining such code.
[/quote]
dynamic_cast (while compiler specific) usualy costs no more than a virtual function call. If you were to take an event handler that gets a pointer to the base (in JUCE’s case, Component*) and has to cast it dynamicaly to MyButton*, and then compare it to an event handler from the current JUCE style, where you have to maintain (or have knowledge of) a list of potential components and then search through that list pivoting off the name (or an integer ID), the benefit is in the first pattern.
The problem (in my mind at least) is not the search performance really, because you can hash on the ID or name and get the component in ~O(1) most of the time, the real problem is the structure and maintainence of this event handler. The problem is having to maintain a proper list of components to search. What if you have components from different parent components, you can’t just search all children of one component, and so on.
As far as worrying about deleting the pointer, its not a problem to supply a const pointer.
[quote=“X-Ryl669”] The solution I am advertising is using an ID so you will still be able to keep the code readable and easy to write (with a correct enum), it is possible to check for ID ranges (so this solves the different component type issue, if you want to apply the same code to all your button, simple put a if (ID >= firstButtonID && ID <= lastButtonID).
With a switch, the search could be O(1) (instead of O(n)). [/quote]
I agree, that at least is headed in the right direction. You can also take it a step further and just give it a TYPEID, i.e. if (sender->getTypeID() == BUTTON_COMPONENT)… This way the event handler does not have to keep track of the range of IDs, since adding a new button would require incrementing the ID range and all code that checks it. This way the string name is used as the “ID” and the typeID is used to filter based on component type. Also, with this code you can use static_cast and avoid the (IMO usualy negligable) penalty of the RTTI.
Well I think its a case of horses for courses, as the saying goes. I’m not trying to force a usage down everyone’s throat, but rather suggest an event signature that enables the widest style of usage to client code. If client code just wants to use string name, then the pointer sender->getName() does not get in the way of that. Meanwhile, sender->doWhatever() is available for the rest of us.
[quote=“X-Ryl669”] A good solution, like I said earlier, would be to have both system (default handler with string (or better, ID), only called if you don’t override the non default handler with pointers).
Even better, the component could use a template argument for switching from both cases at compile time at no cost. [/quote]
I know what you mean, but wouldn’t it be less confusing to just have one signature that is widest use case possible?
Which example didnt make sense? I’m guilty of not being perfectly clear so far on several ocasions. Sorry about that.