Purpose Of Properties
Properties is a mechanism to interface in formation to and from a class in a specific manner. Like a list can be asked for all properties defined for an object (also derived class properties). Dynamic properties become very important to store information which is temporary. Like the editing of canvas objects requires extra data to be stored inside the canvas object to edit. But only during editing. So one does not want to extend the class to store all this extra information. But still it is needed. The sultion is to store all that data into dynamic properties. After editing is done, all dynamic data is removed again. This keeps memory usage for canvas object low, while still being able to do many extra things on them. Users can use dynamic properties to store their own information in dynamic properties. All in all, the properties are essential to wxArt2D.
Use Of Properties
wxArt2D has an extensive system for having properties on objects. The a2dPropObject derived from a2dObject, is the class which can hold dynamic properties in a list. The dynamic property is a a2dNamedProperty derived class, designed to hold a specific type of information. To name a view:
a2dBoolProperty => a2dPropertyIdBool
a2dStringProperty => a2dPropertyIdString
a2dVoidPtrProperty => a2dPropertyIdVoidPtr
a2dInt16Property => a2dPropertyIdInt16
a2dDoubleProperty => a2dPropertyIdDouble
a2dProperty => a2dPropertyIdRefObject
a2dArrayStringProperty => a2dPropertyIdArrayString
a2dDateTimeProperty => a2dPropertyIdDateTime
As you can see, any kind data from simple to complex types can be stored as a property. Important to understand is that each type of data, has a specific id class behind it. The a2dPropertyId holds information on the type of data, and how the property is stored. This can be as a dynamic property wrapping the property data into a a2dNamedProperty object, stored on a a2dPropObject, or it can directly call a member function or field. The functions to get the property value in case of a member function or field, are stored as pointers to those functions or members, again as part of a2dPropertyId.
In a class, property id's are defined as static members, e.g.:
static const a2dPropertyIdUint16 PROPID_Layer; static const a2dPropertyIdBool PROPID_Selected; static const a2dPropertyIdCanvasObject PROPID_Editcopy;
So each instance of this class can have the property set or not. How the property data is stored in the class, depends on how the property Id is defined. The property id static members or initialized, and this includes information like its naming, class for which the property is defined, how the property valua is retrieved and stored.
For the generic types, a macro is available, for others the initialization is a bit more complex.
A2D_PROP_GSI( a2dPropertyIdUint16, a2dCanvasObject, Layer, false ); A2D_PROP_GSI( a2dPropertyIdBool, a2dCanvasObject, Selected, false ); const a2dPropertyIdCanvasObject a2dCanvasObject::PROPID_Editcopy( CLASSNAME( a2dCanvasObject ), wxT("editcopy"), a2dPropertyId::flag_temporary, 0 );
The member function DoExchangeMembers( a2dPropertyId::ExchangeMembersData *data ) is responsible for exchanging data stored as a property defined for a class. The property data stored someway (dynamic,members,member function) as part of a class instance, can be set or retrieved using as storage, again a2dNamedProperty. You could say that the property its value, being a member function or field or a dynamic property, is wrapped into a a2dNamedProperty. This way of setting properties through a single interface has its advantages when making un-doable commands in an application. Instead of writing many commands for setting and getting the value of a property of a specific class, now only one is needed. The command holds the a2dNamedProperty for the value + id, and a pointer to the object from which it did get the property. All information needed to set/get the property again is available.
Another usage is that all properties on an object, no matter of they are dynamically stored in the propertylist of a2dPropObject, or just a member field of teh class, they can be retrieved as a list of a2dNamedProperty's. And as such a property dialog can use it to change the properties on an object and later store them again.
Properties are in general specific to one class and its derived classes. But what if you want to interface a value stored in one class to another unrelated class. The member function DoExchangeMembers( a2dPropertyId::ExchangeMembersData *data ) can be used to exchange the property value of an unrelated class to this class.