Re: Win32 &'s --> GTK underlines

Shaw Terwilliger (sterwill@postman.sourcegear.com)
Fri, 15 Oct 1999 14:24:05 -0500


Stephen Hack wrote:
> I have most of the code implemented to add the accelerator code to the window
> group. All that I have left to do in create a new accel_group for each
> notebook page and added the approprate calls on a page switch to add/remove
> the accelerator groups.
>
> This works fine for any class derived from GtkButton. Changing pages will
> take a little bit of work, but isn't undo able. The trick will be when there
> is a label and control (like a label/combo box pair) where the label is not a
> child of the combo box. I think for that we will have to be hard coded the
> linkage between labels and the controls. May be I should look into added some
> user_data to the combo boxes? Does anybody have experience adding data to
> gtkobjects?

gtk_object_set_data() and gtk_object_get_data() are pretty easy to use.
GTK keeps a "miscellaneous data" hash for each widget with key/value
pairs of string/pointer. You get to choose the string component
and give it a "pointer" for a value (in which you could store anything
less than sizeof(void *), like integer values, or a real pointer to something).

So one might do the following:

// define a key visible to both our construction and callbacks
#define WIDGET_DATA_TAG "someuniquestring"

SomeDialog::constructSomeWidgets()
{
// our "data" will be "myExtraSpecialData", which we'd like
// to use in a callback, but can't pass it directly
structFoo myExtraSpecialData = new structFoo;

// GtkWidget is derived from GtkObject, so we can
// use the object_set/object_get methods on them
GtkWidget * mywidget = gtk_mywidget_new();

// the first arg is the key (object pointer), second is
// the string we defined above (so we can look it up later)
// notice how we set "myExtraSpecialData" as the value
gtk_object_set_data(GTK_OBJECT(mywidget), WIDGET_DATA_TAG,
(gpointer) myExtraSpecialData);

// notice how we used the "this" pointer as our data object
// for the callback, so we can map our way back to the dialog
gtk_signal_connect(GTK_OBJECT(mywidget), "somesignal",
GTK_SIGNAL_FUNC(s_callback), (gpointer) this);
}

// somewhere else in the file (probably at the top), we define
// the callback function

static void s_callback(GtkWidget * widget, SomeDialog * dlg)
{
// make sure we ended up in the right callback!
UT_ASSERT(widget && dlg);

// let's get the data back out of the "widget"!

structFoo * data = (structFoo *) gtk_object_get_data(GTK_OBJECT(widget),
WIDGET_DATA_TAG);
// data is now retrieved

// dlg maps to the dialog that attached us, so maybe we want to
// request that it does something with our cool data, or maybe
// we just sit and watch it, or maybe we don't want it now, but
// sometime later
dlg->doSomeThingCoolWithThis(data);
}

/// end almost-real-code ////

Some of the more complex Unix dialogs do this to handle getting
data between static functions (callbacks) and classes. It's
usually much easier than allocating callback structures.

I'm in the process of hooking up the Unix paragraph dialog to do
almost this very thing. Instead of using "structFoo"s all over,
I'm storing which value a menu item has so that when I get a
pointer to the menu item (on a "changed" event from its parent
menu), I can tell the dialog what value the member should store.

It'll be checked in soon.

-- 
Shaw Terwilliger


This archive was generated by hypermail 1.03b2.