Board index FlightGear Development Canvas

Event Click Listener on SVG element  Topic is solved

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Re: Event Click Listener on SVG element

Postby Hooray » Sun Jul 27, 2014 10:46 am

all those links that I posted yesterday should help you understand closures properly, but here's the meat of it:

Code: Select all
foreach(var i; var mode = [1,2,3])
setlistener("foo["~i~"]", func() {
  print("mode =", i);
});


The callback (func expression) will only be evaluated once the listener is triggered - at that point, external variables, like "i", will be 3.
Thus, you need to capture such variables in a closure, i.e. by using a generator function or an anonymous function.

Code: Select all
foreach(var i; var mode = [1,2,3])

(func { # creates an anonymous function
var n = i;
setlistener("foo["~n~"]", func() {
  print("mode =", n);
}); # end of setlistener

}) # end of anonymous function
(); # directly calls the anonymous function
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby omega95 » Sun Jul 27, 2014 8:00 pm

Ok, I think I kind of understand what's wrong. So, is something like this what you're suggesting?

Code: Select all
var generator = {
   gen_click: func(object, svg_element, my_modes) return func {
      svg_element.addEventListener("click", func {
         object.function(my_modes);
      });
   },
   gen_textbox: func(object, svg_element, my_modes) return func {
       # FIXME
   },
   gen_click: func(object, svg_element, my_modes) return func {
      # FIXME
   }
}
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby Hooray » Sun Jul 27, 2014 8:58 pm

well, there are some copy&paste errors in there, but in general that "should" work - even though it's unnecessarily verbose probably:

You can basically have a single "generator" function and add any custom payload/callbacks via arguments - remember, you can easily pass around functions in Nasal.
So there's no need to have separate gen_foo* members in such a hash normally.

But you don't have to use a generator, you can also use an anonymous func - I just find generators easier to explain, and easier on the eyes syntax-wise.

Like Philosopher said previously: don't rely on external variables like "me", instead introduce a temporary variable and wrap it in a closure - and you'll be fine.

So it's better to find something that not only works for you, but that you also fully understand - copy & paste isn't helping here, or you're going to make the same mistake in other places.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 1:46 am

Code: Select all
var generator = {
   gen_click: func() {
      return func(object, svg_element) {
         svg_element.addEventListener("click", func {
            object.function();
         })
      }
   }
}


Yeah, there were also parse errors.

I went over a lot of that stuff and got a basic idea of how it should be, but I'm still confused as to how I can use it for this instrument - I'm not sure exactly which function (there are a lot of funcs) actually needs a closure, the event listener or the function that creates the event listener. :oops:

EDIT

Hmm, can I convert an SVG element into a widget button? :D

Another way I'm thinking of is very inefficient and requires a timer.
Would there maybe be a more intuitive way to do this efficiently? I mean, I know I could create 2 separate MFDs but that's just really inefficient and messy - and a pain to make edits to (I learnt from my old 787-8 development)

I'm really sorry for bothering you guys so much - but thanks a lot for the help!

Hmm, I just found that I've used function generators for the canvas Merlion ACARS Portal (I think you helped me with it) - looks like I didn't really understand what I did. :evil:
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby Philosopher » Mon Jul 28, 2014 5:03 am

You're using generators on the wrong things... that's why it's so hard to grasp how to use them ;)

But actually, you already have generators: not pure ones, but the function here creates a function bound in a closure (it doesn't directly return it though – but it doesn't need to).
Code: Select all
      func(object, svg_element) {
         svg_element.addEventListener("click", func {
            object.function();
         })
      }


So yeah, that's fine. What might be wrong is your usage of the function – may I see that too? I already spotted a problem with that over in the Nasal forum ;).
Philosopher
 
Posts: 1593
Joined: Sun Aug 12, 2012 7:29 pm

Re: Event Click Listener on SVG element

Postby Hooray » Mon Jul 28, 2014 6:49 am

whenever your callbacks refer to outside variables, you'd need to use a closure/generator.
Have you looked at the links that we posted ? What about the examples ?



If it's still unclear, maybe we should improve those docs ... so feel free to ask a ton of questions !

Regarding the SVG element -> Canvas widget question, see $FG_ROOT/Nasal/canvas/widgets/Button.nas and ../styles/DefaultStyle.nas
You would basically use/change the button constructor such that it can use your SVG element as an overlay/image, should be straightforward to do - and you could then easily reuse your widgets everywhere else.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 3:48 pm

Yeah, I think I understand what closures are for - I just didn't understand exactly where I'd use them for the MFDs but I think I get it now, thank you.

Also, when I made the ECAM SD, FG crashes (not every time) when I load a new SVG file over and over again, so I just put all the pages into various layers of 1 SVG file. Like the ND, I'll just show active page layer and hide the rest.

I was wondering how I would be able to do that - do I just treat layers are regular SVG elements?

Cheers and thanks! :)

EDIT

Oh and also, how would I pass the parent to a sub function?

I mean, say I have -
Code: Select all
var mfd = {
    fpln: {}, # Flight plan hash (something else)
    loadPage: func(page) {
        # Stuff that loads a page
        me.pages[page].load(HELP HERE PLEASE);
    },
    pages: {page1, page2} # These pages are actually loaded with an addPage function which is a member of MFD to help manage page titles, layers, etc.
};


So, instead of HELP HERE PLEASE, I need to send the equivalent of me. Because, the page needs to be able to access the mfd instance's functions such as loadPage (for loading another page) and the fpln. I tried using me before but that gives an error (I'll try to get it again, hold on)
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby Hooray » Mon Jul 28, 2014 4:07 pm

closures are not specific to MFDs - they're a matter of dealing with callbacks for your listeners and timers, like Philosopher said.
Whenever you want some callback to access/modify an existing NON-global object, you should wrap everything in a closure, i.e. using an anonymous function or simply a generator.
Thus, you only need to look at your callbacks (anything invoked via timers/listeners) and see if they are using external variables properly

PS: a "layer" can be easily mapped to a canvas "group".
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 4:14 pm

closures are not specific to MFDs - they're a matter of dealing with callbacks for your listeners and timers,


Yes, I understood that - I just meant that I didn't understand exactly where I'd need to use them but I think I got it.

PS: a "layer" can be easily mapped to a canvas "group".


How exactly would I do that? Any wiki articles out there? :)
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby Hooray » Mon Jul 28, 2014 4:21 pm

no need for any wiki articles at all: think about what a "layer" ultimately is: it is an entity to which you can render something and that you can easily show/hide, which kinda matches the definition of a canvas group - which is why ND/MapStructure layers are internally "just" Canvas groups - to see for yourself, use the property browser and inspect any ND/MapStructure tree.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 4:56 pm

use the property browser and inspect any ND/MapStructure tree.


Hmm ok, I see that the layers are subgroups - but how do I actually create/access them? I couldn't find the layers (from the ND svg file) CTR, PLAN and base anywhere in navdisplay.mfd and navdisplay.styles.

I'm looking for a resource/example code. I'm not entirely sure how to access the layer as a group.
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 5:13 pm

The layer id in the canvas property tree has a different name from the SVG layer name. that seems really inconvenient. :|

Image

Image
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

Re: Event Click Listener on SVG element

Postby Hooray » Mon Jul 28, 2014 5:16 pm

I haven't looked at the SVG file or our parser in a while - but basically, you can just get a handle to the element that you're interested in via findElementByName(), and then write it to a group via parsesvg(), implement depth-ordering via the z-index property - if something doesn't work as expected, you can also open svg.nas and extend the parser to support your specific use-case/XML tag.

Changing the naming behavior would seem straightforward - in this case, it seems that layers are sequentially named, what was the underlying code here ?
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Event Click Listener on SVG element

Postby Gijs » Mon Jul 28, 2014 5:20 pm

The layers in the ND svg are only used to ease altering the svg (in inkscape). The elements are then toggled per element or group. I don't think we can grab layers from Nasal (yet). You could group all elements per layer in inkscape though and then grab those like any other element.
Airports: EHAM, EHLE, KSFO
Aircraft: 747-400
User avatar
Gijs
Moderator
 
Posts: 9544
Joined: Tue Jul 03, 2007 3:55 pm
Location: Delft, the Netherlands
Callsign: PH-GYS
Version: Git
OS: Windows 10

Re: Event Click Listener on SVG element

Postby omega95 » Mon Jul 28, 2014 5:21 pm

Changing the naming behavior would seem straightforward - in this case, it seems that layers are sequentially named, what was the underlying code here ?


I did not use any code to load these layers - they're layers in the SVG file and the order doesn't seem right. The Layer on top is the Modes layer and that seems to be layer1, but the next right below it (next to it in the SVG file) is menu_fms but menu_fms seems to be layer4 in the property tree.

I was able to access the Modes layer with getElementById("layer1") though, but it would make a lot more sense if I could use "Modes" instead of "layer1".

The layers in the ND svg are only used to ease altering the svg (in inkscape). I don't think we can grab layers from Nasal (yet). You could group all elements per layer in inkscape though and then grab those like any other element.


That's brilliant - but then the layers ARE sub-grouped. Would this make a difference?
Merlion Virtual Airlines - the experience of a flight time...
Get high quality aircraft, airports, video tutorials or development tools from my hangar.
omega95
 
Posts: 1222
Joined: Sat Jul 30, 2011 1:59 am
Location: -unknown-
Callsign: MIA0001, OM-EGA
IRC name: omega95
Version: 2.12 git
OS: Ubuntu 13.04

PreviousNext

Return to Canvas

Who is online

Users browsing this forum: No registered users and 5 guests