LuaGuiElement.path, the full path of a gui element

Things that we aren't going to implement
Post Reply
User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

LuaGuiElement.path, the full path of a gui element

Post 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.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
DaveMcW
Smart Inserter
Smart Inserter
Posts: 3700
Joined: Tue May 13, 2014 11:06 am
Contact:

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

Post by DaveMcW »

If you're so concerned about performance, why not cache the names yourself?

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

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

Post 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.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

Rseding91
Factorio Staff
Factorio Staff
Posts: 13225
Joined: Wed Jun 11, 2014 5:23 am
Contact:

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

Post by Rseding91 »

What's your use case here?
If you want to get ahold of me I'm almost always on Discord.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5151
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

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

Post 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

Angamara
Inserter
Inserter
Posts: 39
Joined: Mon Oct 30, 2017 3:52 pm
Contact:

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

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

Rseding91
Factorio Staff
Factorio Staff
Posts: 13225
Joined: Wed Jun 11, 2014 5:23 am
Contact:

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

Post 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?
If you want to get ahold of me I'm almost always on Discord.

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

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

Post 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:
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

User avatar
Klonan
Factorio Staff
Factorio Staff
Posts: 5151
Joined: Sun Jan 11, 2015 2:09 pm
Contact:

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

Post 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

User avatar
eradicator
Smart Inserter
Smart Inserter
Posts: 5206
Joined: Tue Jul 12, 2016 9:03 am
Contact:

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

Post 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.
Author of: Belt Planner, Hand Crank Generator, Screenshot Maker, /sudo and more.
Mod support languages: 日本語, Deutsch, English
My code in the post above is dedicated to the public domain under CC0.

Angamara
Inserter
Inserter
Posts: 39
Joined: Mon Oct 30, 2017 3:52 pm
Contact:

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

Post 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"}

Post Reply

Return to “Won't implement”