Xfce Foundation Classes
« Main Page
# XFC Object Properties Object properties are data members that define the internal state of an object. The GLib object system implements a generic mechanism to get and set object properties. When an object is instantiated, the object's 'class_init' handler is called to register any object properties and provide default values. GTK+ provides several functions that can get and set one or more object properties at a time, like g_object_get() and g_object_set(). As well most objects provides a getter and setter function for each property. For example, GtkWindow has a property called "gravity" and provides the functions gtk_window_get_gravity() and gtk_window_set_gravity() to get and set a window's gravity value. GTK+ implements the getting and setting of object properties in terms of an object's individual getter and setter functions. When you set an object property via the generic set function g_object_set(), it's actually the property's setter function that gets called to set the value. While it's important in GTK+ to be able to get and set properties both generically and specifically using the getter and setter functions, it's not in C++. The use of variable arguments lists is frowned upon in C++ because they're not typesafe, but they're still legal. In a C++ language binding it's overkill and unnecessary to provide both generic and specific wrappers to get and set properties, and it offers no real benefits. So why does XFC provide wrappers for some object properties? Because not all GTK+ objects provide getter and setter functions. Specifically the following objects don't: GtkAction GtkCellRenderer GtkCellRendererPixbuf GtkCellRendererText GtkCellRendererToggle GtkSettings GtkTextTag XFC adds C++ wrappers for their object properties to the corresponding XFC classes: Gtk::Action Gtk::CellRenderer Gtk::CellRendererPixbuf Gtk::CellRendererText Gtk::CellRendererToggle Gtk::Settings Gtk::TextTag Currently these are the only XFC objects that provide wrappers for GTK+ object properties. Getting and setting property values on these objects is the only way to read or alter their internal state. The template classes used to implement object properties can be found in the file <xfc/glib/properties.hh>. There are 3 template classes: G::Property - wraps properties that are both readable and writable. G::ReadableProperty - wraps properties that are readable only. G::WritableProperty - wraps properties that are writable only. Object properties are protected data members and are declared static. Lets look at Gtk::TextTag's 'size_property' declaration as an example: `typedef G::Property<int> SizePropertyType; typedef G::PropertyProxy<G::Object, SizePropertyType> SizePropertyProxy; static const SizePropertyType size_property;` For convenience the first line typedefs the size_property type G::Property<int> which is both a readable and writable property. The third line declares the static const variable size_property. You can use this variable to get and set the text tag's font size but only in dervied classes because it's declared protected. The functions used to get and set a property are: `void G::Property::get(const G::Object *object, DataType& data) const; void G::Property::set(const G::Object *object, const DataType& data) const;` These functions take a pointer to the object whose property is being accessed and a variable of type 'DataType'. DataType is the template argument and in the case of Gtk::TextTag::size_property it is an int. You would get a tag's font size like this: `int font_size; size_property.get(this, font_size);` and you would set a tag's font size like this: `size_property.set(this, 20 * PANGO_SCALE);` You wont set properties in derived classes very often. Instead you will use a property's public proxy function. That's what the second line in the size_property declaration is for. It typedefs a proxy object for size_property:`` `` `` `typedef G::PropertyProxy<G::Object, SizePropertyType> SizePropertyProxy;` G::PropertyProxy is an inline proxy object that is used to access a protected property's get() and set() methods. Its constructor takes an object pointer and the address of the protected property as arguments. G::PropertyProxy has its own get() and set() methods that take only the property data type as an argument. These methods then call the protected property's get() and set() methods, passing as the object pointer the pointer passed to the G::PropertyProxy constructor. The public proxy property for Gtk::TextTag's size_property is declared and defined inline like this: `inline const Xfc::Gtk::TextTag::SizePropertyProxy Xfc::Gtk::TextTag::property_size() { return SizePropertyProxy(this, &size_property); }` Using size_property's public proxy function, you could get a tag's font size like this: `int font_size; tag->property_size().get(font_size);` `` and you could set a tag's font size like this: `tag->property_size().set(20 * PANGO_SCALE);` Or alternatively, you could simply use assignment which is a lot easier: `int font_size = tag->property_size(); // gets font size tag->property_size() = 20 * PANGO_SCALE; // sets font size` If you look at the property declarations in the header files you will see some property typedefs have two template arguments. Take a look at the declaration for the Gtk::TextTag 'weight_property'. `typedef G::Property<Pango::Weight, int> WeightPropertyType; typedef G::PropertyProxy<G::Object, WeightPropertyType> WeightPropertyProxy; static const WeightPropertyType weight_property;` Here G::Property has two template arguments, Pango::Weight and int. Properties are accessed internally using a G::Value. G::Value handles an enum value as an integer, so Pango::Weight which is an enum value needs to be cast to an int. The first template argument is always the property data type and the second template argument is the standard data type G::Value needs to cast the property data type to. You can just ignore the second template argument because it's an implementation detail for internal use only.
Copyright © 2004-2005 The XFC Development Team | Top | XFC 4.4