Page 1 of 1

LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 6:37 pm
by eradicator
What?
The ability to get the full (absolute) path of a LuaGuiElement.
Whaat?
I would like to be able to access a full list of parent element names from any given LuaGuiElement. For examble if i have a button in a table in a submenu the full path might look something like this:

Code: Select all

local path = {"center","mymodname_gui_frame","submenu1_frame",1,"submenu1_table","button1"}.
This would nicely complement the already existing .children_names property.
Why?
On a (not so recent anymore) thread i was discussion the performance cost of checking for a LuaGuiElement's parent vs checking for a name prefix with string.sub(). For my guis so far i've often felt the need to check an elements parent or root names, but rarely (never?) needed to retrive the actual parent object.

As far as i understand the internals of the C->Lua transfer of objects it would be much faster to fetch a table of strings from the api than to recurse (on the lua side) upwards through all parent objects just to fetch the name of each object. If that assumption is wrong feel free to point fingers at me and laugh :p.

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 7:28 pm
by DaveMcW
If you're so concerned about performance, why not cache the names yourself?

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 7:37 pm
by eradicator
DaveMcW wrote:If you're so concerned about performance, why not cache the names yourself?
I don't see how that would be possible. LuaGuiElement doesn't have a .unit_number equivalent to identify an element uniquely (and if it was recreated in the meantime that would just mean the cache grows to infinity). And (obviously) after i fetch the list of names at the start of on_gui_click i already keep it until the end of that event.

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 8:05 pm
by Rseding91
What's your use case here?

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 9:40 pm
by Klonan
eradicator wrote:As far as i understand the internals of the C->Lua transfer of objects it would be much faster to fetch a table of strings from the api than to recurse (on the lua side) upwards through all parent objects just to fetch the name of each object. If that assumption is wrong feel free to point fingers at me and laugh :p.
Even going through 20+ parent gui's it won't take so much time

Secondly, not all LuaGui elements have names, in which case your system would not work

There are ways to do as you want, the best would be to store widget references in global:

Code: Select all

global.button[player.name] = game.player.gui.center.add{type = "button", caption = "Free gold"}
and then compare it to this on gui click

Code: Select all

function on_gui_click(event) if event.element == global.button[game.players[event.player_index].name] then game.print("Free gold button was pressed) end

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 11:41 pm
by Angamara
Klonan wrote:Secondly, not all LuaGui elements have names, in which case your system would not work
Why ?

If you give a name to all your elements, all your elements have a name.

I give a name to all my elements (same identical) and my system works.


eradicator: Put the information of your "GuiElement" in an object instead of using global for each one. It is much better for the execution of your program.

Including the path, do a recursive function on parent when you save your item in your object and you will not have to check every click.

Re: LuaGuiElement.path, the full path of a gui element

Posted: Wed Nov 15, 2017 11:47 pm
by Rseding91
Angamara wrote: eradicator: Put the information of your "GuiElement" in an object instead of using global for each one. It is much better for the execution of your program.

Including the path, do a recursive function on parent when you save your item in your object and you will not have to check every click.
What?

Re: LuaGuiElement.path, the full path of a gui element

Posted: Thu Nov 16, 2017 5:14 am
by eradicator
Klonan wrote: Even going through 20+ parent gui's it won't take so much time

Secondly, not all LuaGui elements have names, in which case your system would not work
I even had that case in my example. As far as i understand nameless LuaGuiElements use a numerical index? I'm not sure why that couldn't be included in a table of names. I guess it's not a .name as such, but:
a) if i gave it a numerical index i probably don't care about the name, but just about the depth/length of the path.
b) numerical indexes can afaiu still be used to access gui elements? e.g game.player.gui.center.myguimainframe[1]

If you say that recursing upwards (to root) to fetch 20 parent objects just for their name is fast enough, then this request is mostly void. Also i don't think that comparibility would be of any help for this because of the large number of possible combinations.
Rseding91 wrote:What's your use case here?
Well, the first thing i need to do in any on_gui_clicked event is determine if the event.element belongs to my mod or to a different mod. For that i usually check if i know the upmost parents name, tho in the thread linked in the OP people suggested to me that i should prefix "mymodname_" to every gui element instead.
Secondly suppose my GUI has several buttons labeled "ok" or "cancel" (not visible at the same time), then i need to either check another prefix to see what menu it belongs to (so button.name becomes "mymodname_mysubmenu1_button1"), or i can just look at the list of parent names again to see if parentnames[#parentnames-1] is the right menu.
The GUI in question is a menu with several tabs, each of which has completely different functionality. Some of the tabs have a large number of sprite-buttons generated off of item/technology lists. And i just feel that putting 2-3 different prefixes on each of those buttons names is not a "clean" way of doing this.


TL;DR: I basically thought this would be a good complement to .children_names. So, kind of a "would be nice to have" request. But if it's too complicated to implement (or not worth your time)... i'll just build the list of names on the lua side and move on (unless someone shows me that there's different much better way). Sorry for the disturbance :oops:

Re: LuaGuiElement.path, the full path of a gui element

Posted: Thu Nov 16, 2017 11:50 am
by Klonan
eradicator wrote:
Klonan wrote: Even going through 20+ parent gui's it won't take so much time

Secondly, not all LuaGui elements have names, in which case your system would not work
a) if i gave it a numerical index i probably don't care about the name, but just about the depth/length of the path.
b) numerical indexes can afaiu still be used to access gui elements? e.g game.player.gui.center.myguimainframe[1]
You don't give an index, there is no index, a nameless child just doesn't have a name. It still has its position in the children table of the parent:

Code: Select all

player.gui.center.add{type = "label"}
player.gui.center.children[1].caption = "This is how we access with an index"
But there is no way to get this index without going through the parent, as it isn't a property of the GUI element

Re: LuaGuiElement.path, the full path of a gui element

Posted: Thu Nov 16, 2017 4:58 pm
by eradicator
Klonan wrote:But there is no way to get this index without going through the parent, as it isn't a property of the GUI element
.children_names reports the name for such elements as "" (empty string) too, which ofc results in an error if one tries to access a child by that name. So having a "" in the table of parent names would be consistent (though admitteldy somewhat ugly :/) if it's too expensive to fetch the numerical index. And as i said, imho if a modder choses to not have a name for an element then they would know they needs to look out for that empty string.

Re: LuaGuiElement.path, the full path of a gui element

Posted: Thu Nov 16, 2017 5:51 pm
by Angamara
To avoid any problem with another mod, I think it is neccessary to put a generic name to all your elements. (example: sn_btn_close [sn = short name])

What I was trying to explain is to have a class for your GUI system and; LUA is all you need to do, no need to add this function to the API.

And that you record in this class all the information of your elements.

A golden rule in computer development: Never do 15 times the same thing if the result is the same.

Example:
- Never count the number of elements of a table 3 times in the same function.
- Never browse a table for each function
- Etc.

Use a generic name to solve your problem but if you want to check the path. Check the path once and store it.

Also remember to check that a name is not already taken before adding an element

Either by removing the element already present, or by creating a function of random generation of name.

Code: Select all

if gui.top[my_name] then
    gui.top[my_name].destroy()
end
gui.top.add{name = "my_name"}