Is there a generic event for all events?
I'm actually looking to pass the events in C++ to Lua so ideally I would be able to dynamically hook every controls event in the xaml up to 1 generic event in C++ and be able to get the control name and event name in string form. Is this possible? If I cold get this in C++ from Noesis then I could make the mapping to Lua on my own. You can think of this as a code behind in Lua instead of C++.
Re: Is there a generic event for all events?
I'm not finding anything in the API. Does anyone have any ideas if we are able to peak at an event that is about to be fired from the UI and able to see the string event name and string control name?
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: Is there a generic event for all events?
Hi,
That kind of generic event doesn't exist in NoesisGUI. I'm afraid you need to hook to each specific event. The only thing that may help with that process is that you can attach/detach an event handler to any RoutedEvent using a common API:
And also for some non-routed events you can use:
You can obtain a routed event given its name via the UI element type:
Hope this helps.
That kind of generic event doesn't exist in NoesisGUI. I'm afraid you need to hook to each specific event. The only thing that may help with that process is that you can attach/detach an event handler to any RoutedEvent using a common API:
Code: Select all
void UIElement::AddHandler(const RoutedEvent* ev, const RoutedEventHandler& handler);
void UIElement::RemoveHandler(const RoutedEvent* ev, const RoutedEventHandler& handler);
Code: Select all
void UIElement::AddNonRouted(NsSymbol key, const EventHandler& handler);
void UIElement::RemoveNonRouted(NsSymbol key, const EventHandler& handler);
Code: Select all
const RoutedEvent* Noesis::Gui::FindRoutedEventRecursive(const TypeClass* type, NsSymbol eventName);
Re: Is there a generic event for all events?
Besides, it is very important that you fully understand the architecture of Routed Events, Tunneling, Bubbling, Preview Events, etc that NoesisGUI borrows from WPF. It is described here:
Routed Events Overview
For our integration with PlayMaker, we needed to redirect all the events. As you can see in the source code, it is done case by case. The API is C# but the translation to C++ should be straightforward.
https://github.com/Noesis/Playmaker/blo ... isProxy.cs
Routed Events Overview
For our integration with PlayMaker, we needed to redirect all the events. As you can see in the source code, it is done case by case. The API is C# but the translation to C++ should be straightforward.
https://github.com/Noesis/Playmaker/blo ... isProxy.cs
Re: Is there a generic event for all events?
How can I loop over all loaded UIElements from a xaml file? Once I have that I assume I can store a list of all event string names and then for each UIElement loop over this event name list calling AddHandler() for each one.
Something like:
[EDIT]
Interesting jsantos. What I posted above seems like it would work but I may be missing something. What was the reason you guys were so specific in your PlayMaker object?
Just take a guess, I'm not at the PC that I have Noesis on, but like in .NET the event args can be a different object by the event? So I guess perhaps I'd need 1 "generic" event handler per unique event args sig, and then group them while that way while I'm looping over each element? Guessing there are groups of common event handlers with some unique per control. Having the groups could save me a little I suspect. From inside each one I would need the component string name and the event string name to build the Lua function I should be calling as I want the Lua functions to be specific to the control and event like:
function Button3_Click(e)
end
So inside my handler I need "Button3" and event "Click" so I can build "Button3_Click" and search if that function in Lua is defined and if it is, push the args to it and call it.
Something like:
Code: Select all
// find all elements in our loaded xaml
foreach(UIElement e in xaml->GetElements())
{
// loop over all string event names
foreach(string event in events)
{
// get the routed event from the event string name
const RoutedEvent* re = Noesis::Gui::FindRoutedEventRecursive(??, event);
// add the 1 generic handler for this event to this UIElement
e->AddHandler(re, &App::MyGenericEventHandler);
}
}
void App:MyGenericEventHandler(BaseComponent* sender, const RoutedEventArgs& e)
{
// so I'm sure via sender I can get the UIElement name but I'm curious about the event name that triggered this
}
[EDIT]
Interesting jsantos. What I posted above seems like it would work but I may be missing something. What was the reason you guys were so specific in your PlayMaker object?
Just take a guess, I'm not at the PC that I have Noesis on, but like in .NET the event args can be a different object by the event? So I guess perhaps I'd need 1 "generic" event handler per unique event args sig, and then group them while that way while I'm looping over each element? Guessing there are groups of common event handlers with some unique per control. Having the groups could save me a little I suspect. From inside each one I would need the component string name and the event string name to build the Lua function I should be calling as I want the Lua functions to be specific to the control and event like:
function Button3_Click(e)
end
So inside my handler I need "Button3" and event "Click" so I can build "Button3_Click" and search if that function in Lua is defined and if it is, push the args to it and call it.
Re: Is there a generic event for all events?
On the flip side of this, can I add my own tags to the xaml file and query those elements based on these tags? That way I could probably simulate the way you guys are doing codebehinds in C++ but do it in Lua for Leadwerks. Basically what I'm trying to do here is a codebehind idea in Lua for Leadwerks anyway (and I guess at some level generic Lua really).
This would for sure be a more efficient way to handle things as then only the events the user cares about gets registered "automatically" (I would code the mapping of common event signatures) to Lua functions (the user specifies in a tag the lua function).
This would for sure be a more efficient way to handle things as then only the events the user cares about gets registered "automatically" (I would code the mapping of common event signatures) to Lua functions (the user specifies in a tag the lua function).
-
sfernandez
Site Admin
- Posts: 3184
- Joined:
Re: Is there a generic event for all events?
You can name any element of the xaml tree by setting the x:Name attribute:
And then you can query the xaml root about any named element:
About the previous question, I don't think it is a good idea to attach an event handler for each event of each UI element in the tree. Do it only when it is necessary, that is, when you want to add an event handler from Lua.
What I would do is, as you said, some kind of auto-mapping between Lua and C++ using the function name. If user has a Button3_Click() function defined in Lua, then you can look for an element named Button3 in the xaml tree (as I just explained), find the Click event using that element:
Now you can attach your event handler that knows how to call Lua function from C++:
NOTE: As you already discovered, if you need to pass event information to Lua, you will need different event handlers for each args type.
Code: Select all
<Grid ...>
<Button x:Name="Button3" .../>
...
</Grid>
Code: Select all
FrameworkElement* root = GUI::LoadXaml<FrameworkElement>("test.xaml");
Button* button3 = root->FindName<Button>("Button3");
What I would do is, as you said, some kind of auto-mapping between Lua and C++ using the function name. If user has a Button3_Click() function defined in Lua, then you can look for an element named Button3 in the xaml tree (as I just explained), find the Click event using that element:
Code: Select all
const TypeClass* type = button3->GetClassType();
const RoutedEvent* clickEvent = Noesis::Gui::FindRoutedEventRecursive(type, clickEventName);
Code: Select all
button3->AddHandler(clickEvent, MakeDelegate(&App::SendEventToLua));
Re: Is there a generic event for all events?
Good idea. My mind was having the starting point be the xaml to determine if an event should be attached but starting from Lua is a good idea.If user has a Button3_Click() function defined in Lua, then you can look for an element named Button3 in the xaml tree (as I just explained), find the Click event using that element:
I think I'll first check for a global function and if none exists I'll look for a table that has the same name as the xaml file and look for the function inside that table (this is the method I'd mostly use as I dislike just global functions hanging out there but others may want this).
When I'm able to get this generic process going I'll talk with the guy who made the github project for LE and see if he minds that I add this functionality to it (and document what he has as I found it lacking. I don't like reading code for documentation. I prefer english explanations of what's going on).
Thanks for your help and the ideas.
[EDIT]
I think I might need to prefix the Lua function names with Noesis or something to make finding the ones we care about easier. Something like function Noesis_Button3_Click(e) end
Re: Is there a generic event for all events?
Code: Select all
Button* button3 = root->FindName<Button>("Button3");
Re: Is there a generic event for all events?
Yes, you can use any parent class. For example:
Code: Select all
FrameworkElement* button3 = root->FindName<FrameworkElement>("Button3");
Who is online
Users browsing this forum: No registered users and 2 guests