On Sun 11/26, [EMAIL PROTECTED] < [EMAIL PROTECTED] >
> I am about to start a new app, and would like to improve my
> programming style. I have been using global variables to pass data
> from "popup" windows back to a main window. I have seen discussion
> about using g_object_set_data, but have not progressed to being
> able to use it confidently.

g_object_set_data() simply stashes a pointer within the object, under the given 
name.  That's pretty much all you need to remember.  The only real gotcha, is 
that you have to be careful to free that pointer value if it points to 
allocated memory (hence the g_object_set_data_full() function, but that's 
another story).

One of the places where I've found g_object_set_data() invaluable, is in 
extending the operation of a widget; for example, linking two numeric entry 
widgets as a min/max pair.  You set the pointer for the min widget on the max 
widget, using g_object_set_data() (and an appropriately named slot), and 
vice-versa.  You then attach a value changed handler to each object which 
checks for the "min" widget pointer, and makes pulls it down if necessary, and 
checks for the "max" widget pointer, and pulls it up if necessary.  Then you 
wrap it up in a helper function which is passed two widgets, sets the data on 
each, and attaches the handler functions.  You can use the helper function time 
and again anywhere where you need a min/max pair of numeric entries.  (It'd 
probably work for a min/cur/max triplet too.)

Another which I've found handy (though slightly more complex), was to attach to 
each widget using g_object_set_data(), a pointer to a variable in which the 
value should be stored (usually within an already-g_malloc()'d struct).  
There's a few examples of a recursive foreach-widgets type function floating 
around, which can then walk the dialog, calling another function on each one as 
it goes.  This new function looks for widgets with the data item set, and 
either puts the value from the widget into the address specified, or plucks the 
value out of the variable and sticks it into the widget.  (Of course, it needs 
a little magic to test what sort of widget it is, and use the correct 
functions.)  The same principal can also be used for database connectivity, 
though there are generally better ways of achieving that, I'd expect.

This sort of mechanism comes in magical for those "OK", "APPLY", "REVERT", 
"CANCEL" type situations.  You have a master copy of the struct, then when you 
create your dialog you also allocate a copy of the struct.  Then once the 
dialog is built, you call a function to fill in the variable check boxes, 
entries, buttons, and what-not.  On an "OK" response, you copy everything back 
again.  On a "CANCEL", you simply ignore it, and "APPLY" and "REVERT" simply 
call the two functions to move data back and forth as appropriate.  As an added 
touch, you use g_object_set_data_full() to attach the malloc()'d copy of your 
master struct to the dialog widget itself, with the DestroyNotify function set 
to g_free().  This means that not only is the struct available if something 
needs it (or if, as I often do, you simply hide frequently-used dialogs instead 
of destroying them), but it'll get cleaned up along with the dialog itself.  If 
you keep the dialog around, you keep the struct also, and 
just re-fill it from the main struct, call the function to fill the dialog 
widgets from it, and then call gtk_window_present() to re-show the dialog.

Along the same vein, I've used g_object_set_data() to hold the original value 
of a widget, and attached a handler that set or cleared an indicator on the 
widget when the value was anything other than its original setting.  (It makes 
a bit more sense when linked with the apply/revert mechanism.)

These are the sorts of things I've personally used g_object_set_data() and 
friends for...  The best part of doing it this way, is the linkage of the 
dialog widgets to the variables within the struct is done right there as you're 
building the dialog (of course, it's not quite so much use if you're using 
Glade...  In that case, the usual mass-get/set function pair is probably 
cleaner).


> Does anyone know of a simple example using g_object_set_data. The
> sort of thing I am thinking about is a main window with a label
> and button, that pops up a child window with an entry and a
> button. Clicking the child windows button returns the string in
> the entry back to the main windows label.

In this case, the child window should probably be a dialog, and you'd attach to 
its response signal.  When you get the "OK" response, you'd fetch the value 
from the entry and assign it to the label, or whatever you plan on doing.  Not 
really much need for a g_object_set_data() there...


Fredderic

_______________________________________________
Join Excite! - http://www.excite.com
The most personalized portal on the Web!


_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Reply via email to