Now, what's a control without a container? I will now show you how to write a control container to contain the pathetic little ipctrl, or any control you like. The code for the container you can find in test-container.c of the source code that accompanies this article.
The control container is a lot like a normal GTK+/GNOME applications, with some specifics, on which I will focus. The main() looks a bit like this:
int main (int argc, char** argv) { CORBA_ORB orb; gnome_init_with_popt_table ("test-container", "0.0", argc, argv, oaf_popt_options, 0, NULL); /* * initialize CORBA, OAF and bonobo */ orb = oaf_init (argc,argv); if (!orb) g_error ("initializing orb failed"); if (!bonobo_init (orb, NULL, NULL)) g_error ("could not initialize Bonobo"); /* * We can't make any CORBA calls unless we're in the main * loop. So we delay creating the container here. */ gtk_idle_add ((GtkFunction) create_app, NULL); bonobo_main (); return 0; } |
The interesting stuff of the program is done in container_create. Again, most of it is standard GTK+/GNOME stuff, so let's focus on the Bonobo specifics.
static guint create_app (void) { GtkWidget *box, *control, *label, *button; BonoboUIContainer *uic; /* * create a bonobo application (window) */ bonobo_win = bonobo_window_new ("ipctrl-container", "a container for ipctrl's"); gtk_widget_set_usize (GTK_WIDGET(bonobo_win), 200, 120); /* * connect a ui container to the application */ uic = bonobo_ui_container_new (); bonobo_ui_container_set_win (uic, BONOBO_WINDOW(bonobo_win)); /* get a widget, containing the control */ control = bonobo_widget_new_control (IPCTRL_OAFIID, BONOBO_OBJREF (uic)); if (!control) g_error ("Can't create control\n"); (...) /* lights, camera, action */ gtk_widget_show_all (GTK_WIDGET(bonobo_win)); return FALSE; /* putting TRUE here is a bad idea. I warned you. */ } |
/* get a widget, containing the control */ control = bonobo_widget_new_control (IPCTRL_OAFIID, bonobo_object_corba_objref(BONOBO_OBJECT(uic))); if (!control) g_error ("Can't create control\n"); |
In the control, we made a property bag to manipulate the octets of the ipctrl. In the container application, we must get a reference to this property bag. In create_app there's the magic line (which we omitted in the previous):
/* add listener to this control's property bag */ install_property_bag_listener (BONOBO_WIDGET(control), BONOBO_WINDOW(bonobo_win)); |
static void install_property_bag_listener (BonoboWidget *control, BonoboWindow *bonobo_win) { Bonobo_Listener corba_listener; BonoboListener *listener; BonoboControlFrame *control_frame; CORBA_Environment ev; CORBA_exception_init (&ev); /* * the property bag is associated with the control frame, so get the * control frame first */ control_frame = bonobo_widget_get_control_frame (BONOBO_WIDGET(control)); if (!control_frame) g_error ("can't find control frame\n"); /* * now, get a ref to the property bag */ prop_bag = bonobo_control_frame_get_control_property_bag (control_frame, NULL); if (prop_bag == CORBA_OBJECT_NIL) g_error ("can't connect to property bag\n"); /* * connect a listener to the property-bag */ bonobo_event_source_client_add_listener (prop_bag, on_prop_changed, "Bonobo/Property:change:octet1", NULL, bonobo_win); CORBA_exception_free (&ev); } |
Then, we can create a new property listener through bonobo_property_listener_new. We then do two things with the newly created 'listener'. First, we define a GTK+ signal handler, which will call on_prop_change when anything changes in the property bag. Second, we get a reference to the CORBA object that's wrapped by the listener. Using the bare CORBA object reference, we notify the property bag we are interested in notifications of any changes, through Bonobo_PropertyBag_addChangeListener. Note that the second argument to this function (""), means that we are interested in changes for any property.
Now, the on_prop_change is, again, very straightforward, and will update the title of the container window whenever it is called (whenever there's change in the property bag). The code doesn't contain too many surprises, the only interesting thing is probably the call to retrieve a value from the property bag, for example:
octets[0] = (guint8) bonobo_property_bag_client_get_value_gint (prop_bag, "octet1", NULL); |
We also have a function on_clear which will set values. Very easy:
bonobo_property_bag_client_set_value_gint (prop_bag, "octet1", 0, NULL); |