GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Wed Dec 17, 2014 9:28 pm

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Passing multiple pieces of data to callback
PostPosted: Wed Mar 07, 2012 10:58 pm 
Offline
Familiar Face

Joined: Mon Feb 27, 2012 8:40 pm
Posts: 6
As far as GTK Goes from what I have learned so far (got an awesome GTK Foundations book to help me along), I am seeing that you can only freely pass 1 pointer to a callback function. The first parameter passed to the callback is the object which fired the signal your connecting to it, and the second (or 3rd if its an event signal) is a pointer to whatever you want, or NULL.

This undoubtedly leads me to say, well what If I want a button, to grab text from an entry, and write it to a label.

I cannot simply say
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(getAndWrite), label)
As that has no access to the entry object.

To accomplish this I have thus far found only 1 solution, to make something like the following
Code:
typedef struct {
GtkWidget *label;
GtkWidget *entry;
} examplecomponents;

and pass in the callback a pointer to examplecomponents.

This is completely acceptable and even preferred as I like to orginize things, but I cannot help but think that the items will not always fall into those categories. What if I then want to have the entrys text written to a label in a different struct, then Im running into the same problem.

My idea, and Im wondering if this has already been gone over and if anyone can tell me why i should NOT try and make this happen, is to create a special event the label can fire, like a "write-and-swap" event or something I create, then pass the label to the callback which gets called on my buttons clicked signal, and force it to fire the 'write-and-swap' event. This way I can attach a special callback to the "write-and-swap" event, making the label my first parameter, and pass the entry as the data. I hope that makes sense, and I just want an opinion of, no your stupid because of this this and this, or yes GTK is standardly written in that way.

I honestly cannot think of any different way to get multiple pieces of data into a callback for a problem such as this.


Top
 Profile  
 
 Post subject: Re: Passing multiple pieces of data to callback
PostPosted: Thu Mar 08, 2012 12:30 am 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
I probably don't know enough about the event system to comment on your suggestion though I feel that there is likely an easier way.
With callbacks the simple method is to use global variables. A global variable can be accessed from anywhere. Global variables are more efficient but have the downside of overuse making code disorganised, difficult to maintain and those who read it call down curses on you and all your ancestry. For an example see one of my repositories.
Of course if taking the global variable approach you don't want 20 functions to work on box1-box20 when they do exactly the same thing; having a generalised function and box variable is much better.
For people that like neat well organised code, the passing a structure approach you mention is excellent. You do however, present a good problem with dealing with widgets outside the normal structure groupings.
In answering, I must ask:
How is this label in a different structure determined? It's obviously not any label but a praticular one. As such there must be a logical way of representing how the labels structure is related to the entry's structure. This relationship will define a natural structuring of your structures which can then be passed to the function (though you can only pass one pointer, you can pass a pointer to an array of pointers which is what you are doing with your structure, this just takes it one step further in terms of structures of structures).
An examples to come down from the abstraction: lets say you wanted to make a program to input someone's geneology. After putting a name into an entry, the next two entry's labels should say [name's] mother and [name's] father and so on. In this case structures grouping the entry and its assciated widgets could be organised in a tree hierarchy (don't know if glib actually has a data type for this one, but can be indexed in an array -- e.g. represent mothers fathers mother => MFM => x=010 [0s for Ms and 1s for Fs] then the index is [2^#digits]-1+binary value of x). You can then pass a pointer to this hierarchy and the widget that triggered the event/signal will index where in this hierarchy to work from. Ok I've gone rambling and you're unlikely to have this being the case, it's just to show that you can make a data model for virtually any situation.
Of course if there's only a few instances where you want more than one parameter you can just pass a pointer to an array that you've created just for that callback.
If you let us know more about how your GUI is set up and what buttons are used for editing which labels (andaccording to which entries) we might be able to give better direction.
There is really no standardisation as to the paradigm in which you program; some of course perform better than others, but if your code is error free I hardly see how anyone would label you as stupid.
By the way you should be setting up atk relationships for all labels and what they label e.g.:
Code:
  atk_widget=gtk_widget_get_accessible(entry);
  atk_label=gtk_widget_get_accessible(GTK_WIDGET(label));
  atk_object_add_relationship(atk_label, ATK_RELATION_LABEL_FOR, atk_widget);
  atk_object_add_relationship(atk_widget, ATK_RELATION_LABELLED_BY, atk_label);

so that assitive technology knows how things are related (I'm a little pissed off that this never gets mentioned in the official GTK tutorials). In this case you have no need for the structure you had originally set up as your callback could delve into atk to determine the label for any given entry or vice versa.


Top
 Profile  
 
 Post subject: Re: Passing multiple pieces of data to callback
PostPosted: Thu Mar 08, 2012 1:52 pm 
Offline
Familiar Face

Joined: Mon Feb 27, 2012 8:40 pm
Posts: 6
Paul, Thank you so much for your answer, I got a lot of useful information out of it. Specifically the ATK things I want to look into as for some reason I have not heard anything aside from what its generally used for about atk.

Your absolutely correct in that really, my program should be structured in a way where my structs are logically grouped and my 'what-if' scenario should be rare at best. Even in those cases passing an array will overcome. Im trying to stay away from passing too much unneeded data as an unfortunate result of the way my program is written, for example, if I did something rediculous like this:

Code:
typedef struct {
    GtkWidget *every;
    GtkWidget *widget;
    GtkWidget *in;
    GtkWidget *my;
    GtkWidget *program;
} mywholeapp;

static void myCallback(GtkWidget*, mywholeapp*);

int main(int argc, gchar *argv[]) {
   gtk_init(&argc, &argv);

   mywholeapp *prog = new mywholeapp();
   prog->every = gtk_window_new(GTK_WINDOW_TOPLEVEL);

   //Define the rest of my widgets, say a few labels and a button

   gtk_widget_show_all(prog->every);

   gtk_main();
   delete mywholeapp;
   return 0;
}

static void myCallbac(GtkWidget *obj, mywholeap *mcb) {

   //I can now get to anything in my program via this callbacks mcb-> parameter

}

Obviously i would not do the above, however my point is that im trying to avoid passing unnecessary data around and hogging memory, as with the above anytime i had to pass ANYTHING to ANY callback i would have to pass EVERYTHING. This leads me to say, I should probably take your suggestions to heart, and also consider the fact that you said there is no "standard this is the way" approach to gtk, theres no 1 correct way. This is something I will have to get used to, and figure out what the best way I should structure a program for the app at hand when the time comes. I do however, taking the above code snippit into consideration, have one last question which seems like more of a C question than anything.

Can I split my app up into logical sensible structs like this:
Code:
typedef struct {
   GtkWidget *window;
   GtkWidget *statusbar;
   GtkWidget *menubar;
} windowcomponents;
typedef struct {
   GtkWidget *label1;
   GtkWidget *button2;
} mypanel;

and than make a structure of those structures in case I ever need it such as
typedef struct {
windowcomponents *wc;
mypanel *mp;
} wholeapp;

The code itself wont work as it is obviously, as simply initializing the struct members of wholeapp would be a terrible pain, however if there is any way to make a 'structure of structures' it would be very appreciated for you to explain it to me.

Thank you again for your time and advise


Top
 Profile  
 
 Post subject: Re: Passing multiple pieces of data to callback
PostPosted: Thu Mar 08, 2012 9:06 pm 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
yes you can make structures of structures, and in fact you have already been doing this as every widget is a structure and even some subcomponents are structures. E.g. widget->window->allocation->width (at least I think that works. Never strung it out that long in practice). I wasn't advocating putting everything in a structure, more of an array of entry-label groupings. It will only increase memory by the amount of pointers if you do things right (you shouldn't instantiate entire copies of widgets just to store in a structure). You're not actually passing `everything' just a pointer to `everything'; even if you use an array rather than a structure. If you want a more dynamic `everything' then you could use singly or doubly linked lists or GArrays to add elements to.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group