Bonobo component properties, version 0.1 by Michael Meeks A brief discussion of how to use the property API to add a simple to use configuration mechanism to your bonobo component. 1. Properties and bags. A property is an attribute that is attached to a Bonobo object. It can have any type, although the standard types boolean, long, float, double, string are handled in a convenient fashion. Properties are attached to a PropertyBag object that is attached to your control or component in some way. 2. BonoboArgs. A bonobo arg contains the value of a property whilst it is 'in flight' between a property and a requestor. The bonobo arg system is designed to make ORBit's 'any' code easier to use and less error prone. A number of macros and helper functions are provided in bonobo-arg.h. Particularly, the type macros of BonoboArgType eg. BONOBO_ARG_BOOLEAN, BONOBO_ARG_LONG, BONOBO_ARG_STRING And a number of access procedures for getting and setting standard values from a BonoboArg. Eg. if 'a' is a BonoboArg * we should use: BONOBO_ARG_GET_STRING (a) to get its string value or BONOBO_ARG_SET_STRING (a, "GNU") to set its string value NB. Passing a NULL string to ARG_SET_STRING will result in internal ORBit crashes. The bonobo-arg code also provides functions for mapping GtkArgs to BonoboArgs and VV. 3. PropertyBag creation To add properties to an object first we must create a property bag hence: BonoboPropertyBag *bonobo_property_bag_new (BonoboPropertyGetFn get_prop, BonoboPropertySetFn set_prop, gpointer user_data); Each property has a get / set / user_data (GSU) triplet that handles that property's behavior. In a typical scenario all object properties in a bag utilise the same GSU triplet, and are identified inside the get / set functions by a unique enumerated constant arg_id. Inside the function this arg_id can then be used with a switch statement to provide efficient (de)multiplexing of property requests. For particularly obtuse persons wanting more flexibility it is possible to specify the GSU triplet per property using the add_full variant. 4. Property Creation Each basic property is created by this function: void bonobo_property_bag_add (BonoboPropertyBag *pb, const char *name, int idx, BonoboArgType type, BonoboArg *default_value, const char *docstring, BonoboPropertyFlags flags); It looks horrendous, but is horribly simple in most cases; the idx is the index that will be passed to a generic get / set function for this property. The type is one of the BonoboArgType macros discussed in section 2 which maps to an ORBit TypeCode [ hence any arbitary type can be added without the property-bag knowing anything about it ( allocation of that type is the users responsibility ) ]. Default_value is either NULL or a value created thusly: BonoboArg *def = bonobo_arg_new (BONOBO_ARG_DOUBLE); BONOBO_ARG_SET_DOUBLE (def, 0.3127); It's reference is stored in the property_bag. The rest of the code is internal and extremely transparent. In order to implement the get / set functions I would copy & paste the sample code in: bonobo/samples/controls/bonobo-clock-control.c. 5. Wrapping Gtk Objects If you have already implemented a GtkObject that has the set of GtkArgs that you wish to export as BonoboArgs then it is trivial to add them to the property bag using a transparent mapping. This means that you do not have to write any more code, simply use: bonobo_property_bag_add_gtk_args (pb, my_object); 6. Using properties in your client application Since the contract between client and server is very tight I have added some more tightness in the form of some vararg methods to possibly make using controls simpler and ( incidentaly ) to decrease type safety beyond all previous limits. eg. CORBA_double i; bonobo_widget_get_property (control, "value", &i, NULL); i+= 0.37; bonobo_widget_set_property (control, "value", i, NULL); This is theoreticaly slower than using the alternative bonobo_property_bag_client_get_value_gdouble (pb, "value", &i); since to determine the type of i the client has to query the bag and then do its varargs stuff. It is however far more convenient.