Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Is there a generic event for all events?

08 Apr 2015, 03:45

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++.
 
Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Re: Is there a generic event for all events?

08 Apr 2015, 14:45

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?
 
User avatar
sfernandez
Site Admin
Posts: 2995
Joined: 22 Dec 2011, 19:20

Re: Is there a generic event for all events?

08 Apr 2015, 16:21

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:
void UIElement::AddHandler(const RoutedEvent* ev, const RoutedEventHandler& handler);
void UIElement::RemoveHandler(const RoutedEvent* ev, const RoutedEventHandler& handler); 
And also for some non-routed events you can use:
void UIElement::AddNonRouted(NsSymbol key, const EventHandler& handler);
void UIElement::RemoveNonRouted(NsSymbol key, const EventHandler& handler); 
You can obtain a routed event given its name via the UI element type:
const RoutedEvent* Noesis::Gui::FindRoutedEventRecursive(const TypeClass* type, NsSymbol eventName);
Hope this helps.
 
User avatar
jsantos
Site Admin
Posts: 3919
Joined: 20 Jan 2012, 17:18
Contact:

Re: Is there a generic event for all events?

08 Apr 2015, 16:37

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
 
Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Re: Is there a generic event for all events?

08 Apr 2015, 16:46

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:
// 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.
 
Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Re: Is there a generic event for all events?

08 Apr 2015, 17:01

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).
 
User avatar
sfernandez
Site Admin
Posts: 2995
Joined: 22 Dec 2011, 19:20

Re: Is there a generic event for all events?

08 Apr 2015, 18:04

You can name any element of the xaml tree by setting the x:Name attribute:
<Grid ...>
  <Button x:Name="Button3" .../>
  ...
</Grid> 
And then you can query the xaml root about any named element:
FrameworkElement* root = GUI::LoadXaml<FrameworkElement>("test.xaml");
Button* button3 = root->FindName<Button>("Button3"); 
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:
const TypeClass* type = button3->GetClassType();
const RoutedEvent* clickEvent = Noesis::Gui::FindRoutedEventRecursive(type, clickEventName); 
Now you can attach your event handler that knows how to call Lua function from C++:
button3->AddHandler(clickEvent, MakeDelegate(&App::SendEventToLua)); 
NOTE: As you already discovered, if you need to pass event information to Lua, you will need different event handlers for each args type.
 
Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Re: Is there a generic event for all events?

08 Apr 2015, 18:33

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:
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.

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
 
Rick
Topic Author
Posts: 50
Joined: 26 Nov 2013, 15:35

Re: Is there a generic event for all events?

08 Apr 2015, 18:52

Button* button3 = root->FindName<Button>("Button3"); 
This is very specific since it has the Button class. Can I get some parent class and still have this work? Because otherwise I have to know what specific control it is and that'll start being a pain to manage.
 
User avatar
jsantos
Site Admin
Posts: 3919
Joined: 20 Jan 2012, 17:18
Contact:

Re: Is there a generic event for all events?

08 Apr 2015, 20:58

Yes, you can use any parent class. For example:
FrameworkElement* button3 = root->FindName<FrameworkElement>("Button3"); 

Who is online

Users browsing this forum: No registered users and 13 guests