[Request] GuiElement - user data field

Place to ask discuss and request the modding support of Factorio. Don't request mods here.
thelordodin
Fast Inserter
Fast Inserter
Posts: 153
Joined: Fri Jan 06, 2017 1:54 am
Contact:

[Request] GuiElement - user data field

Post by thelordodin »

Hi

I think there should be a field "user_data" on GuiElement.
This would be very useful for many mods which uses gui.

I'm now digging inside EficienSee sources and i've seen others - they all workaround this by adding suffixes to name field.
Which is for obvious reason is not a very good solution.

Is that possible to add user_data to GuiElement?

Use cases: if I have more then one button in interface and one handler for this button type - there is a problem to bind some portion of user data on these button.

Many desktop frameworks have this field on all gui elements (examples: Qt, MFC, C#, Delphi)
Rseding91
Factorio Staff
Factorio Staff
Posts: 14280
Joined: Wed Jun 11, 2014 5:23 am
Contact:

Re: [Request] GuiElement - user data field

Post by Rseding91 »

What kind of data are you talking about that someone would want to attach to a GUI element?
If you want to get ahold of me I'm almost always on Discord.
thelordodin
Fast Inserter
Fast Inserter
Posts: 153
Joined: Fri Jan 06, 2017 1:54 am
Contact:

Re: [Request] GuiElement - user data field

Post by thelordodin »

Example 1:

EfficienSee
A table with rows.
Each row shows you info about some production lines.
Every line has a button "Details".

So there is a handler "on_details_button_clicked", which shows next info.

But for which row is that called?

If the button have a field "user_data" you can store lua-array into it and identify row.

In this case:

Code: Select all

(line 1606 control.lua of EfficienSee)
			for _, ingr in pairs(recipe.ingredients) do
				-- debug_print("object=", ingr.name)
				local object = get_object(ingr.name,objects,force_mem)                                <======= This is user data
				local uplist_object = {object=object, is_item=(ingr.type=="item"), amount = -ingr.amount}
				build_obj_line(gui5,uplist_object,n)                                                               <======= Here a row in gui table is created. But since no user_data can be attached to it, links to temporary object (gui) has to be stored away from it - an array attached to a player
				n=n+1
				table.insert(uplist_objects, uplist_object)
			end

Example 2:
You have a table with blueprints and a button loading blueprint into an item.
Each line represents a blueprint.
You'd be able to make a handler "on_load_blueprint_clicked", but again on which row?

Example 3:
I want to create an item button and a dialog for it.
The button shows selected item, you can click it to change. If you click the button - it shows dialog and after you picked new item type it shoud be stored in button,
so a user of a library could retrive it from the button.

I've already done this, but i pass value through sprite field which isn't a good way to pass user data.

Example 4:
Since user_data is a lua array you can store component subtype into it.
This allows you to easily create components.

Code: Select all

You just put {button_type: "item_selector", object_id = 12345}
then inside

on_gui_click
...
if event.element.user_data.button_type == "item_selector" then
on_item_selector_clicked(event.element)
end
...
on_item_selector_clicked(element)
selected_object = my_objects[element.user_data.object_id]
end
...
---
In general - this happens every time you have a set of similar fields or buttons and you want one handler function for them all.
Then its quite a classic solution to attach specific user data to each gui element.

user_data is a field which can store null or lua-array.

Ofcourse everyone can live somehow without it, for example you can store links to gui from user data instead, but usually mod's user_data is permanent meanwhile gui is temporary.
So this just messes up gui code, because you store a ref to gui in user data. This ref is temporary since gui may exists or may be hidden, you have to validate it, you have to take care to update it
and also storing refs to gui in permanent data uses some memory .

If you have user_data inside gui element - it's much easier:
you create gui dialog, player selects whatever he wants, than it's closed - all the user data is deleted with gui.
- No verification problems: if you have gui you always have data in it, cause you put it in on creation, if gui is nil - no user_data is stored.
- Mod's data is separated from mod's gui (no refs from data to gui)
User avatar
Macros
Inserter
Inserter
Posts: 23
Joined: Mon Mar 07, 2016 11:42 am
Contact:

Re: [Request] GuiElement - user data field

Post by Macros »

thelordodin wrote:Example 3:
I want to create an item button and a dialog for it.
The button shows selected item, you can click it to change. If you click the button - it shows dialog and after you picked new item type it shoud be stored in button,
so a user of a library could retrive it from the button.

I've already done this, but i pass value through sprite field which isn't a good way to pass user data.
As a workaround to this very same problem, I use sprite-buttons with a custom style that has the font color set to be completely transparent ({a = 0}). I then store data, in the form of strings, in the button's caption.
>nature.destroy()
User avatar
Adil
Filter Inserter
Filter Inserter
Posts: 945
Joined: Fri Aug 15, 2014 8:36 pm
Contact:

Re: [Request] GuiElement - user data field

Post by Adil »

I wrote my own library to keep data connected to gui and handle the callbacks. I've put it on github https://github.com/Adilf/gui-lib .
Macros wrote: I use sprite-buttons with a custom style that has the font color set to be completely transparent ({a = 0}).
You can just make any gui element invisible.
I do mods. Modding wiki is friend, it teaches how to mod. Api docs is friend too...
I also update mods, some of them even work.
Recently I did a mod tutorial.
User avatar
aubergine18
Smart Inserter
Smart Inserter
Posts: 1264
Joined: Fri Jul 22, 2016 8:51 pm
Contact:

Re: [Request] GuiElement - user data field

Post by aubergine18 »

Maybe a very simple .metadata field which could contain a string or a number (but not tables, as that would open can of worms should other mods try and read a table that contains references to original mod).

I tried the approach of using non-visible GUI elements but found this to be undesirable, in particular any time I wanted to loop through child elements I was having to filter out the dummy elements. It's relatively trivial to do (eg. filter based on visibility) but it just feels hacky and wrong.

I also tried (and am currently using) the method of serialising information in to the element name. I often use a prefix to define element purpose (eg. button or whatever), then a hyphen, then serialised metadata. While this works, it's still hacky and wrong, but at least it avoids having dummy elements all over the place.

A dedicated .metadata field that can hold string or number would provide a decent balance between simplicity and flexibility IMO.
Better forum search for modders: Enclose your search term in quotes, eg. "font_color" or "custom-input" - it prevents the forum search from splitting on hypens and underscores, resulting in much more accurate results.
thelordodin
Fast Inserter
Fast Inserter
Posts: 153
Joined: Fri Jan 06, 2017 1:54 am
Contact:

Re: [Request] GuiElement - user data field

Post by thelordodin »

Yes, you can think of some workarounds, but maybe it's better just add that field?
I think there is no problem with it for devs.

About reading other mod's gui - i don't see a reason why to forbid this? Mod's already have a way to commuticate correctly, why someone would try to make such things you mentioned? Just to make a mod to ruin all? Well, then noone will install it.
Post Reply

Return to “Modding interface requests”