BonoboPropertyBag

## BonoboPropertyBag BonoboPropertyBag — Implements a generic property storage interface |

## Synopsis

                BonoboPropertyBagClass;
                BonoboPropertyBag;
    #define     BONOBO_PROPERTY_READABLE
    #define     BONOBO_PROPERTY_WRITEABLE
    #define     BONOBO_PROPERTY_WRITABLE
    #define     BONOBO_PROPERTY_NO_LISTENING
    #define     BONOBO_PROPERTY_NO_AUTONOTIFY
                BonoboProperty;
    void        (*BonoboPropertyGetFn)          (BonoboPropertyBag *bag,
                                                 BonoboArg *arg,
                                                 guint arg_id,
                                                 CORBA_Environment *ev,
                                                 gpointer user_data);
    void        (*BonoboPropertySetFn)          (BonoboPropertyBag *bag,
                                                 const BonoboArg *arg,
                                                 guint arg_id,
                                                 CORBA_Environment *ev,
                                                 gpointer user_data);
    BonoboPropertyBag* bonobo_property_bag_new  (BonoboPropertyGetFn get_prop_cb,
                                                 BonoboPropertySetFn set_prop_cb,
                                                 gpointer user_data);
    BonoboPropertyBag* bonobo_property_bag_new_closure
                                                (GClosure *get_prop,
                                                 GClosure *set_prop);
    BonoboPropertyBag* bonobo_property_bag_new_full
                                                (GClosure *get_prop,
                                                 GClosure *set_prop,
                                                 BonoboEventSource *es);
    BonoboPropertyBag* bonobo_property_bag_construct
                                                (BonoboPropertyBag *pb,
                                                 GClosure *get_prop,
                                                 GClosure *set_prop,
                                                 BonoboEventSource *es);
    void        bonobo_property_bag_add         (BonoboPropertyBag *pb,
                                                 const char *name,
                                                 int idx,
                                                 BonoboArgType type,
                                                 BonoboArg *default_value,
                                                 const char *doctitle,
                                                 Bonobo_PropertyFlags flags);
    void        bonobo_property_bag_add_full    (BonoboPropertyBag *pb,
                                                 const char *name,
                                                 int idx,
                                                 BonoboArgType type,
                                                 BonoboArg *default_value,
                                                 const char *doctitle,
                                                 const char *docstring,
                                                 Bonobo_PropertyFlags flags,
                                                 GClosure *get_prop,
                                                 GClosure *set_prop);
    void        bonobo_property_bag_remove      (BonoboPropertyBag *pb,
                                                 const char *name);
    void        bonobo_property_bag_map_params  (BonoboPropertyBag *pb,
                                                 GObject *on_instance,
                                                 const GParamSpec **pspecs,
                                                 guint n_params);
    GList*      bonobo_property_bag_get_prop_list
                                                (BonoboPropertyBag *pb);

## Description

The PropertyBag is used for many things, particularly for the customization of controls. The important thing to remember about the BonoboPropertyBag implementation is that no live data is stored in the bag. ie. the Model for the properties is your code.

Consequently when someone requests a properties value, or sets a property the callbacks you supply at bag construction time are called, and the code therein must supply the property. Similarly, when a property changes value inside your object you need to notify the property bag's listeners that it has changed with a call to `bonobo_event_source_notify_listeners_full`.

Here is a simple example use of the property bag:

Example 3. PropertyBag Callbacks

    enum {
    	PROP_RUNNING,
    	PROP_COLOUR
    } MyArgs;

    static void
    get_prop (BonoboPropertyBag *bag,
    	  BonoboArg         *arg,
    	  guint              arg_id,
    	  CORBA_Environment *ev,
    	  gpointer           user_data)
    {
    	GtkObject *clock = user_data;

    	switch (arg_id) {

    	case PROP_RUNNING:
    		BONOBO_ARG_SET_BOOLEAN (arg, clock->is_running);
    		break;

    	case PROP_COLOUR:
    		BONOBO_ARG_SET_STRING (arg, clock->color);
    		break;

    	default:
    		bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
    		break;
    	}
    }

    static void
    set_prop (BonoboPropertyBag *bag,
    	  const BonoboArg   *arg,
    	  guint              arg_id,
    	  CORBA_Environment *ev,
    	  gpointer           user_data)
    {
    	GtkClock *clock = user_data;

    	switch (arg_id) {

    	case PROP_RUNNING: {
    		guint i = BONOBO_ARG_GET_BOOLEAN (arg);

    		if (i)
    			gtk_clock_start (clock);
    		else
    			gtk_clock_stop (clock);
    		break;
    	}

    	case PROP_COLOUR:
    		gtk_clock_set_color (clock, BONOBO_ARG_GET_STRING (arg));

    	default:
    		bonobo_exception_set (ev, ex_Bonobo_PropertyBag_NotFound);
    		break;
    	}
    }

Then to instantiate the property bag interface and associate it with a control perhaps we do:

Example 4. Adding a PropertyBag to a control

    	BonoboPropertyBag *pb;

    	pb = bonobo_property_bag_new (get_prop, set_prop, clock);
    	bonobo_control_set_properties (control, pb);

    	bonobo_property_bag_add (pb, "running", PROP_RUNNING,
    				 BONOBO_ARG_BOOLEAN, NULL,
    				 _("Whether or not the clock is running"),
    				 0);

    	bonobo_property_bag_add (pb, "colour", PROP_COLOUR,
    				 BONOBO_ARG_STRING, NULL,
    				 _("The colour of the clock face"),
    				 0);

    	bonobo_object_unref (BONOBO_OBJECT (pb));

And finally we need to notify listeners of changes in various properties so we could perhaps do:

Example 5. Notifying proterty bag listeners

    static void
    signal_handler (GtkClock *clock, BonoboPropertyBag *pb)
    {
    	BonoboArg *arg = bonobo_arg_new (TC_string);

    	BONOBO_ARG_SET_STRING (arg, gtk_clock_get_color (clock));

    	bonobo_event_source_notify_listeners_full (pb->es,
    					           "Bonobo/Property",
    					           "change",
    						   "colour",
    					           arg, NULL);
    	bonobo_arg_release (arg);
    }
    ...
    	gtk_signal_connect (GTK_OBJECT (clock), "color_changed",
    			    GTK_SIGNAL_FUNC (signal_handler), pb);

See also BonoboArg.

## Details

### BonoboPropertyBagClass

    typedef struct {
    	BonoboObjectClass        parent;

    	POA_Bonobo_PropertyBag__epv epv;
    } BonoboPropertyBagClass;

### BonoboPropertyBag

    typedef struct {
    	BonoboObject             parent;
    	BonoboPropertyBagPrivate *priv;
    	BonoboEventSource        *es;
    } BonoboPropertyBag;

### BONOBO_PROPERTY_READABLE

    #define BONOBO_PROPERTY_READABLE      Bonobo_PROPERTY_READABLE

If this flag is set, the property allows consulting its value.

### BONOBO_PROPERTY_WRITEABLE

    #define BONOBO_PROPERTY_WRITEABLE     Bonobo_PROPERTY_WRITEABLE

If this flag is set, the property supports modification of its value.

### BONOBO_PROPERTY_WRITABLE

    #define BONOBO_PROPERTY_WRITABLE      Bonobo_PROPERTY_WRITEABLE

Misspelling of BONOBO_PROPERTY_WRITEABLE.

### BONOBO_PROPERTY_NO_LISTENING

    #define BONOBO_PROPERTY_NO_LISTENING  Bonobo_PROPERTY_NO_LISTENING

If this flag set, when the property changes its value its listeners will *not* be notified.

### BONOBO_PROPERTY_NO_AUTONOTIFY

    #define BONOBO_PROPERTY_NO_AUTONOTIFY Bonobo_PROPERTY_NO_AUTONOTIFY

If this flag set, when the property changes its value its listeners will *not* be notified.

### BonoboProperty

    typedef struct {
    	char		      *name;
    	int                    idx;
    	BonoboArgType          type;
    	BonoboArg             *default_value;
    	char		      *doctitle;
    	char		      *docstring;
    	Bonobo_PropertyFlags   flags;

    	BonoboPropertyPrivate *priv;
    } BonoboProperty;

Structure that holds information about a property in a BonoboPropertyBag.

char *`name`; | the canonic name of the property
int `idx`; | unique numeric identifier of the property within the property bag
BonoboArgType `type`; | type of value contained by this property
BonoboArg *`default_value`; | the default value
char *`doctitle`; | documentation string title
char *`docstring`; | documentation string
Bonobo_PropertyFlags `flags`; | property flags (read/write, etc.)
BonoboPropertyPrivate *`priv`; | implementation private data

### BonoboPropertyGetFn ()

    void        (*BonoboPropertyGetFn)          (BonoboPropertyBag *bag,
                                                 BonoboArg *arg,
                                                 guint arg_id,
                                                 CORBA_Environment *ev,
                                                 gpointer user_data);

Property getter function.

`bag` : | the property bag
`arg` : | output parameter; the caller must place here the property value
`arg_id` : | unique numeric identifier of the property within the property bag
`ev` : | the relevant CORBA environment
`user_data` : | user data

### BonoboPropertySetFn ()

    void        (*BonoboPropertySetFn)          (BonoboPropertyBag *bag,
                                                 const BonoboArg *arg,
                                                 guint arg_id,
                                                 CORBA_Environment *ev,
                                                 gpointer user_data);

Property setter function.

`bag` : | the property bag
`arg` : | the new property value to be set
`arg_id` : | unique numeric identifier of the property within the property bag
`ev` : | the relevant CORBA environment
`user_data` : | user data

### bonobo_property_bag_new ()

    BonoboPropertyBag* bonobo_property_bag_new  (BonoboPropertyGetFn get_prop_cb,
                                                 BonoboPropertySetFn set_prop_cb,
                                                 gpointer user_data);

Creates a new property bag with the specified callbacks.

`get_prop_cb` : | the property get callback
`set_prop_cb` : | the property set callback
`user_data` : | user data for the callbacks
Returns : | A new BonoboPropertyBag object.

### bonobo_property_bag_new_closure ()

    BonoboPropertyBag* bonobo_property_bag_new_closure
                                                (GClosure *get_prop,
                                                 GClosure *set_prop);

Creates a new property bag with the specified callbacks.

`get_prop` : | the property get closure
`set_prop` : | the property set closure
Returns : | A new BonoboPropertyBag object.

### bonobo_property_bag_new_full ()

    BonoboPropertyBag* bonobo_property_bag_new_full
                                                (GClosure *get_prop,
                                                 GClosure *set_prop,
                                                 BonoboEventSource *es);

Creates a new property bag with the specified callbacks.

`get_prop` : | the property get closure
`set_prop` : | the property set closure
`es` : | an event source to aggregate
Returns : | A new BonoboPropertyBag object.

### bonobo_property_bag_construct ()

    BonoboPropertyBag* bonobo_property_bag_construct
                                                (BonoboPropertyBag *pb,
                                                 GClosure *get_prop,
                                                 GClosure *set_prop,
                                                 BonoboEventSource *es);

Constructor, only for use in wrappers and object derivation, please refer to the bonobo_property_bag_new for normal use.

This function returns `pb`, or `NULL` in case of error. If it returns `NULL`, the passed in `pb` is unrefed.

`pb` : | BonoboPropertyBag to construct
`get_prop` : | the property get closure
`set_prop` : | the property set closure
`es` : | an event source to aggregate
Returns : | BonoboPropertyBag pointer or `NULL`.

### bonobo_property_bag_add ()

    void        bonobo_property_bag_add         (BonoboPropertyBag *pb,
                                                 const char *name,
                                                 int idx,
                                                 BonoboArgType type,
                                                 BonoboArg *default_value,
                                                 const char *doctitle,
                                                 Bonobo_PropertyFlags flags);

Adds a property to the property bag.

`pb` : | property bag to add to
`name` : | name of new property
`idx` : | integer index for fast callback switch statement
`type` : | the CORBA type eg. TC_long
`default_value` : | the default value or NULL
`doctitle` : | the translated documentation string
`flags` : | various flags

### bonobo_property_bag_add_full ()

    void        bonobo_property_bag_add_full    (BonoboPropertyBag *pb,
                                                 const char *name,
                                                 int idx,
                                                 BonoboArgType type,
                                                 BonoboArg *default_value,
                                                 const char *doctitle,
                                                 const char *docstring,
                                                 Bonobo_PropertyFlags flags,
                                                 GClosure *get_prop,
                                                 GClosure *set_prop);

This adds a property to `pb` at the full tilt of complexity.

`pb` : | property bag to add to
`name` : | name of new property
`idx` : | integer index for fast callback switch statement
`type` : | the CORBA type eg. TC_long
`default_value` : | the default value or NULL
`doctitle` : | the translated documentation title
`docstring` : | the translated documentation string
`flags` : | various flags
`get_prop` : | a per property get callback
`set_prop` : | a per property set callback

### bonobo_property_bag_remove ()

    void        bonobo_property_bag_remove      (BonoboPropertyBag *pb,
                                                 const char *name);

removes the property with `name` from `b`.

`pb` : | the property bag
`name` : | name of property to remove.

### bonobo_property_bag_map_params ()

    void        bonobo_property_bag_map_params  (BonoboPropertyBag *pb,
                                                 GObject *on_instance,
                                                 const GParamSpec **pspecs,
                                                 guint n_params);

`pb` : |
`on_instance` : |
`pspecs` : |
`n_params` : |

### bonobo_property_bag_get_prop_list ()

    GList*      bonobo_property_bag_get_prop_list
                                                (BonoboPropertyBag *pb);

`pb` : | A BonoboPropertyBag.
Returns : | a GList of BonoboProperty structures. This function is private and should only be used internally, or in a PropertyBag persistence implementation. You should not touch the BonoboProperty structure unless you know what you're doing.