Page 1 of 1

[Request] GuiElement - user data field

Posted: Sat Jan 28, 2017 10:04 pm
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)

Re: [Request] GuiElement - user data field

Posted: Sat Jan 28, 2017 10:38 pm
by Rseding91
What kind of data are you talking about that someone would want to attach to a GUI element?

Re: [Request] GuiElement - user data field

Posted: Sun Jan 29, 2017 6:57 am
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)

Re: [Request] GuiElement - user data field

Posted: Wed Feb 01, 2017 12:20 am
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.

Re: [Request] GuiElement - user data field

Posted: Wed Feb 01, 2017 9:59 am
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.

Re: [Request] GuiElement - user data field

Posted: Wed Feb 01, 2017 10:14 pm
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.

Re: [Request] GuiElement - user data field

Posted: Fri Feb 10, 2017 9:20 pm
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.