From Feelin's point of view, classes are objects like any others, which allow the use of meta-classes : classes to create classes. Still, you must create classes with the F_CreateClassA() function.
Use this attribute to define the attributes of your class.
The attributes description is a NULL-terminated array of FClassAttribute items. The attributes defined are relative to the name of your class. e.g. If its name is "Numeric" and you define a "Value" attribute, the public name of the attribute will be "FA_Numeric_Value".
The array provided with this attribute must be valid during the life time of the class. Once the class is created, the array is accessible through Class->Attributes. Use the following macros to build and access the array :
Get the numeric representation of a dynamic attribute by accessing the Class->Attributes array through the Class variable, which is usualy defined by the F_METHOD() or F_METHODM() macros.
For safety reason, you need to enumerate your attributes prepending their actual name with the FV_ATTRIBUTE_ identifier, and only use the actual name with the macro.
enum {
FV_ATTRIBUTE_WINDOW, FV_ATTRIBUTE_TITLE, FV_ATTRIBUTE_OPEN, FV_ATTRIBUTE_ACTIVEOBJECT
};
Create the attributes array. The array must be valid during the life time of the class. Usually the macro is preceded by the STATIC macro.
Add an attribute of a specified type. The attribute type is used, when creating objects from XML files. The following types are currently defined :
Add an attribute of a specified type, with special values defined with the F_VALUES_ARRAY macro. These values are used when creating objects from XML files, or when using dynamic attributes to replace keywords with special values.
Add an attribute of a specified type, with a dynamic name and a static ID. You should rarely use this macro because only low-level classes have registered static IDs.
Same as above but with special values too, defined with the F_VALUES_ARRAY macro.
Create an array of FClassAttributeValue items.
Add a special value with it numeric representation.
Add the attributes to the taglist used to create your class.
enum {
FV_ATTRIBUTE_WINDOW, FV_ATTRIBUTE_TITLE, FV_ATTRIBUTE_OPEN, FV_ATTRIBUTE_ACTIVEOBJECT,
...
};
STATIC F_VALUES_ARRAY(ActiveObject) { F_VALUES_ADD("next", FV_Window_ActiveObject_Next), F_VALUES_ADD("prev", FV_Window_ActiveObject_Prev), F_VALUES_ADD("none", FV_Window_ActiveObject_None),
F_ARRAY_END };
STATIC F_ATTRIBUTES_ARRAY = { F_ATTRIBUTES_ADD_BOTH("Window", FV_TYPE_POINTER, FA_Window), F_ATTRIBUTES_ADD_BOTH("Title", FV_TYPE_STRING, FA_Window_Title), F_ATTRIBUTES_ADD_BOTH("Open", FV_TYPE_BOOLEAN, FA_Window_Open),
F_ATTRIBUTES_ADD_BOTH_VALUES("ActiveObject", FV_TYPE_OBJECT, FA_Window_ActiveObject),
...
F_ARRAY_END };
...
IFEELIN F_Set(Obj, F_ATTRIBUTE_ID(OPEN), TRUE);
IFEELIN F_Set(Obj, (uint32) "ActiveObject", (uint32) "next");
Similar to the Resolveds attribute, this attribute is used to retreive the numeric representation of attributes and methods, but because the provided array is passed to the F_DynamicAddAutoTable() function, these numeric representations are resolved as they are defined. Thus, you can get numeric the representation of attribute and methods of objects that you might use at some point in your class.
You must provide a pointer to a NULL-terminated array of FDynamicEntry items, which will be passed to the F_DynamicAddAutoTable() function once the class has been created.
The provided array must be valid during the life time of the class. Once the class is created, the array is accessible through Class->Autos. Use the following macros to build and access the array :
Get the numeric representation of a dynamic entry by accessing the Class->Autos array through the Class variable, which is usualy defined by the F_METHOD() or F_METHODM() macros.
For safety reason, you need to enumerate your items prepending their actual name with the FV_AUTO_ identifier, and only use the actual name with the macro.
enum {
FV_AUTO_INCREASE, FV_AUTO_VALUE
};
Use this macro to create the array.
Add an item to the array.
Add the array to the taglist used to create your class.
enum {
FV_AUTO_INCREASE, FV_AUTO_VALUE
};
STATIC F_AUTOS_ARRAY = { F_AUTOS_ADD("FM_Numeric_Increase"), F_AUTOS_ADD("FA_Numeric_Value"),
F_ARRAY_END };
...
IFEELIN F_Do(Obj, F_AUTO_ID(INCREASE), 30); IFEELIN F_Set(Obj, F_AUTO_ID(VALUE), 12);
Pointer to the function that will be used as the dispatcher of the class. Use the F_METHOD() or F_METHODM() macros to create the function.
If your class defines some methods (using the Methods attribute) the dispatcher is only called if an invoked method is not defined in the methods table. If there is no dispatcher and the method is not found in the table, the method is passed to the superclass.
Using a dispatcher is considered obsolete, especially because Feelin IDs are not static. You might have hard time trying to cope. Please use the Methods attribute to add methods to your class.
The size of the data used by your class in an object. You usually defines a struct LocalObjectData for your data, and use the F_TAGS_LOD macro to define this attribute within the initial tag list of your class.
Later, you'll be able to access this private space using the F_LOD() macro within the methods of your class.
Use this attribute to define the methods implemented by your class, whereas they override superclass methods or add new ones.
You must provide a NULL-terminated array of FClassMethod items, which must be valid during the entire life time of the class. A static array is usually provided. Once the class is created, this array is accessible through Class->Methods. Use the following macros to build and access the array :
Get the numeric representation of a dynamic method by accessing the Class->Methods array through the Class variable, which is usually defined by the F_METHOD() or F_METHODM() macros.
For safety reason, you need to enumerate your methods, prepending their actual name with the FV_METHOD_ identifier, and only use the actual name with the macro :
enum {
FV_METHOD_INCREASE, FV_METHOD_DECREASE, FV_METHOD_RESET
};
...
IFEELIN F_Do(Obj, F_METHOD_ID(RESET));
Use this macro to create the methods table, and use the F_METHODS_PTR macro to get its pointer.
The methods table must be valid during the lifetime of the class because various information are wrote directly within the array. The STATIC macro is usually preceding the F_METHODS_ARRAY() macro.
Use this macro to add a method to your class. The method that you add is relative to your class' name. If your class' name is "Numeric" and you add a "Increase" method, the public name of the method will be "FM_Numeric_Increase".
Similar to the F_METHODS_ADD() macro, this macro is only used by low-level classes, which have their methods statically defined in <libraries/feelin.h>.
Use this macro to override a method of one of your superclasses. For example, if you want to override the "Increase" method of your superclass "Numeric" :
STATIC F_METHODS_ARRAY() { F_METHODS_OVERRIDE(Gauge_Increase, "Numeric", "Increase");
F_ARRAY_END };
Similar to the F_METHODS_OVERRIDE() macro, this macro should be used to override methods which are statically defined in <libraries/feelin.h>. For example, if you want to override the New method of your superclass Object :
STATIC F_METHODS_ARRAY() { F_METHODS_OVERRIDE_STATIC(Gauge_New, FM_New);
F_ARRAY_END };
Get the pointer of the array created with the F_METHODS_ARRAY() macro.
Add the methods array to the taglist used to create your class.
enum {
FV_METHOD_INCREASE, FV_METHOD_DECREASE, FV_METHOD_RESET
};
STATIC F_METHODS_ARRAY = { F_METHODS_ADD(Numeric_Increase, "Increase"), F_METHODS_ADD(Numeric_Decrease, "Decrease"), F_METHODS_ADD(Numeric_Reset, "Reset"),
F_METHODS_OVERRIDE_STATIC(Numeric_New, FM_New), F_METHODS_OVERRIDE_STATIC(Numeric_Dispose, FM_Dispose), F_METHODS_OVERRIDE_STATIC(Numeric_Get, FM_Get), F_METHODS_OVERRIDE_STATIC(Numeric_Set, FM_Set),
F_ARRAY_END };
...
IFEELIN F_Do(Obj, F_METHOD_ID(INCREASE), 30);
The unique name of your class.
To create a private class just leave the attribute alone. If the attribute is NULL (or not defined) a unique ID string is created. You will then be able to create objects from this private class as usualy, using Class->Name.
This name serves as a basis for dynamic attributes and methods. If the name of the class is "Numeric" and one of its attributes is "Value", the public name of the attribute will be "FA_Numeric_Value" ("FA_" is used to indicate an attribute, "FM_" is used to indicate a method). The underscore character "_" is not allowed in the name because it's used as a seperator.
This attribute should not be used by external classes (libraries). In that case, the class name is created from the library's name (stripped of its extension).
Each class creates a memory pool from which instances are allocated. Setting this tag to FALSE disable the creation of this pool, instances will then be allocated from the default memory pool.
It's not a good idea to disable the creation of the pool, unless you know that only one instance of this class will be created (e.g. shared objects).
This attributes is used to retreive the numeric representation of method and attributes defined by your superclasses.
You must provide a pointer to a NULL-terminated array of FDynamicEntry items, which will be passed to the F_DynamicResolveTable() function once your class is created.
The array provided with this attribute must be valid during the life time of the class. Once the class is created, the array is accessible through Class->Resolveds. Use the following macros to build and access the array :
Get the numeric representation of a dynamic entry by accessing the Class->Resolveds array through the Class variable, which is usualy defined by the F_METHOD() or F_METHODM() macros.
For safety reason, you need to enumerate your items prepending their actual name with the FV_RESOLVED_ identifier, and only use the actual name with the macro.
enum {
FV_RESOLVED_INCREASE, FV_RESOLVED_VALUE
};
Use this macro to define the array.
Add an item to the array.
Used to add the array to the taglist used to create your class.
enum {
FV_RESOLVED_INCREASE, FV_RESOLVED_VALUE
};
STATIC F_RESOLVEDS_ARRAY = { F_RESOLVEDS_ADD("FM_Numeric_Increase"), F_RESOLVEDS_ADD("FA_Numeric_Value"),
F_ARRAY_END };
...
IFEELIN F_Do(Obj, F_RESOLVED_ID(INCREASE), 30); IFEELIN F_Set(Obj, F_RESOLVED_ID(VALUE), 12);
The name of your class superclass.
A subclass inherits every properties of its superclass and may override the methods of its superclass to extend them or add its own.
Use the F_TAGS_SUPER macro to define this attribute within the initial tag list of your class.
If the superclass cannot be opened, the subclass is not be created.
The version of the class.
This is only valid for external classes, available as shared libraries.
F_LOD(class, object)
Use this macro to obtain a pointer to you local object data.
A pointer to a FClass.
A pointer to an object.
F_METHOD(return_type, function_name)
This macro is used to define a method function, that is : a function called to handle a method. It can also be used to define dispatchers, althought they are considered obsolete.
If you need to prototype the function, use the F_METHOD_PROTO() macro.
The kind of data returned by the function e.g. uint32 or struct BitMap *.
The name of the method handler (or dispatcher) e.g. myDispatcher or mySetup.
F_METHODM(<return_type>,>function_name>,<msg_type>)
This macro is the same as F_METHOD() except that it allow defining the type of Msg.
If you need to prototype the function, use the F_METHODM_PROTO() macro.
The kind of data returned by the function e.g. uint32 or struct BitMap *.
The name of the method handler (or dispatcher) e.g. myDispatcher or mySetup.
The type of the variable Msg e.g. struct TagItem * or struct FS_Element_Setup *.
F_METHODM(<return_type>,>function_name>,<msg_type>)
Use this macro if your need to prototize the methods defined with the F_METHODM() macro.
F_METHOD(return_type, function_name)
Use this macro if your need to prototize the methods defined with the F_METHOD() macro.
F_OBJDO(<obj>)
Use this macro to forward the a method to an object.
This macro should only be used when creating external classes (libraries). External classes have only one function, no need to say that this function is very important. The function is called to ask the library precious information such as tag items to create the class from the library or tag items to create the preference group object to adjust class settings.
F_QUERY() { switch (Which) { case FV_Query_ClassTags: { STATIC F_ATTRIBUTES_ARRAY = { F_ATTRIBUTES_ADD_STATIC("Id ", FV_TYPE_STRING, FA_Element_Id), F_ATTRIBUTES_ADD_STATIC("Class", FV_TYPE_STRING, FA_Element_Class), F_ATTRIBUTES_ADD_STATIC("Style", FV_TYPE_STRING, FA_Element_Style), F_ATTRIBUTES_ADD_STATIC("Persist", FV_TYPE_STRING, FA_Element_Persist), F_ATTRIBUTES_ADD_STATIC("Parent", FV_TYPE_OBJECT, FA_Element_Parent), F_ARRAY_END };
STATIC F_METHODS_ARRAY = { F_METHODS_OVERRIDE_STATIC(Element_New, FM_New), F_METHODS_OVERRIDE_STATIC(Element_Dispose, FM_Dispose), F_METHODS_OVERRIDE_STATIC(Element_Get, FM_Get), F_METHODS_OVERRIDE_STATIC(Element_Connect, FM_Connect), F_METHODS_OVERRIDE_STATIC(Element_Disconnect, FM_Disconnect),
F_METHODS_ADD_STATIC(Element_Setup, "Setup", FM_Element_Setup), F_METHODS_ADD_STATIC(Element_Cleanup, "Cleanup", FM_Element_Cleanup), F_METHODS_ADD_STATIC(Element_CreateDecodedStyle, "CreateDecodedStyle", FM_Element_CreateDecodedStyle), F_METHODS_ADD_STATIC(Element_DeleteDecodedStyle, "DeleteDecodedStyle", FM_Element_DeleteDecodedStyle), F_METHODS_ADD_STATIC(Element_LoadPersistentAttributes, "LoadPersistentAttributes", FM_Element_LoadPersistentAttributes), F_METHODS_ADD_STATIC(Element_SavePersistentAttributes, "SavePersistentAttributes", FM_Element_SavePersistentAttributes), F_METHODS_ADD_STATIC(Element_GetProperty, "GetProperty", FM_Element_GetProperty),
F_ARRAY_END };
STATIC F_AUTOS_ARRAY = { F_AUTOS_ADD("FM_PDRDocument_FindHandle"), F_AUTOS_ADD("FM_PDRDocument_CreateHandle"),
F_AUTOS_ADD("FM_Preference_ObtainStyle"), F_AUTOS_ADD("FM_Preference_ReleaseStyle"),
F_ARRAY_END };
STATIC F_TAGS_ARRAY = { F_TAGS_ADD_SUPER(Object), F_TAGS_ADD_LOD, F_TAGS_ADD_ATTRIBUTES, F_TAGS_ADD_METHODS, F_TAGS_ADD_AUTOS,
F_ARRAY_END };
return F_TAGS_PTR; } } return NULL; }
F_STORE(<value>)
This macro is only used within the FM_Get method when tag items are parsed using the F_DynamicNTI() function. It's only a quick shortcut to save attributes value.
F_METHOD(uint32, Numeric_Get) { struct LocalObjectData *LOD = F_LOD(Class, Obj); struct TagItem *Tags = Msg, item;
while (F_DynamicNTI(&Tags, &item, Class) != NULL) switch (item.ti_Tag) { case FV_ATTRIBUTE_DEFAULT: F_STORE(LOD->Default); break; case FV_ATTRIBUTE_VALUE: F_STORE(LOD->Value); break; case FV_ATTRIBUTE_MIN: F_STORE(LOD->Min); break; case FV_ATTRIBUTE_MAX: F_STORE(LOD->Max); break; case FV_ATTRIBUTE_STEP: F_STORE(LOD->Step); break; case FV_ATTRIBUTE_BUFFER: F_STORE(LOD->String); break; }
return F_SUPERDO();
}
Use this macro to pass a method to your superclass.
F_METHOD(uint32, Numeric_New) { struct LocalObjectData *LOD = F_LOD(Class, Obj);
LOD->Min = 0; LOD->Max = 100; LOD->Step = 10; LOD->Format = "%ld";
if ((LOD->String = F_New(64)) != NULL) { return F_SUPERDO(); } else { F_Log(FV_LOG_USER,"Unable to allocate Stringify Buffer"); }
return 0; }