The Object class is the super-class of most Feelin's classes. It contains fundamentals methods to create and delete objects, set or get attributes, set notifications upon attributes, and a bunch of other useful methods.
typedef void * FObject;
FObject is an abstract definition.
[virtual attribute]
You supply a pointer to a previously created object here. This child object is added to the parent object at creation time. Usualy, the value for a Child attribute is a direct call to another F_NewObjA(). Of course you can specify any number of child objects, limited only by the available memory.
When a parent object is disposed, all of its children are disposed too. If one of the Child attributes found in the taglist is NULL, the parent object fails to create and, before returning, dispose all the valid objects found in the taglist.
This behaviour makes it possible to generate a complete family within one single (but long) F_NewObjA() call. Error checking is not necessary since every error, even if it occurs in a very deep nesting level, will cause the complete call to fail without leaving back any previously created object.
If you set up a notify on an attribute to react on user input, you will also recognize events when you change this attribute under program control using the F_Set() function or the Set method. Setting the attribute to TRUE together with your attributes will prevent this notification from being trigerred.
A general purpose value to fill in any kind of information.
IFEELIN F_DoA(Obj, FM_AddListener, FS_AddListener);
This function add a listener on an attribute. Each time the attribute will be modified, the callback provided will be called.
The attribute to listen to.
The callback to call when the attribute is modified.
Following the Callback parameter is a list of tag/value pairs. None is defined currently.
#include <libraries/feelin.h>
#include <proto/feelin.h> #include <proto/exec.h> #include <proto/dos.h>
struct FeelinBase *FeelinBase;
#ifdef __amigaos4__ struct FeelinIFace *IFeelin; #endif
F_HOOKM(uint32, _update, FS_Listener_Trigger) { IFEELIN F_Log(FV_LOG_USER, "DOS object '%s' has been modified", Msg->Value); return 0; }
int main(void) { if (F_FEELIN_OPEN) { FObject dn = DOSNotifyObject,
"Name", "ram:test.txt",
End;
if (dn) { struct Hook update = { { NULL, NULL }, (HOOKFUNC) _update, NULL, NULL };
IFEELIN F_Do(dn, FM_AddListener, "Update", &update, TAG_DONE);
IDOS_ Printf("Watching 'ram:test.txt'. Use Ctrl-C to terminate the demo.\n");
IEXEC Wait(SIGBREAKF_CTRL_C);
IFEELIN F_DisposeObj(dn); }
F_FEELIN_CLOSE; } return 0; }
[virtual method]
IFEELIN F_DoA(Obj, FM_AddMember, FS_AddMember);
Use this method to add objects to others, such as families, applications or groups.
Before an orphan actually becomes a member of a family, it is first invoked with the Connect method to know if it agrees with the adoption. Thus, only orphans which return TRUE become members.
FV_AddMember_Head - add an object as first object to the family. The Previous parameter is not used and may be omitted.
FV_AddMember_Tail - add an object as last object to the family. The Previous parameter is not used and may be omitted.
FV_AddMember_Insert - add an object after another object to the family. The Previous parameter is used and must be another object of the family.
This parameter is only used when inserting object (with Position FV_AddMember_Insert). The object must be a member of the family. If NULL, the object is added as first object to the family.
FObject gr = GroupObject, End; FObject o1 = WidgetObject, FA_Element_Style, "background: red;", End; FObject o2 = WidgetObject, FA_Element_Style, "background: lime;", End; FObject o3 = WidgetObject, FA_Element_Style, "background: blue;", End; IFEELIN F_Do(gr, FM_AddMember, o3, FV_AddMember_Tail); IFEELIN F_Do(gr, FM_AddMember, o1, FV_AddMember_Head); IFEELIN F_Do(gr, FM_AddMember, o2, FV_AddMember_Insert, o1);
IFEELIN F_DoA(Obj, FM_CallHook, FS_CallHook);
Call a standard Amiga callback hook, defined by a struct Hook. Together with the Notify method, you can easily bind hooks to buttons e.g. your hook will be called when the button is pressed.
Pointer to a struct Hook.
Zero or more parameters.
standalone:
IFEELIN F_Do(obj, FM_CallHook, &hookstruct, 13,42,"foobar","barfoo");
within a notification statement:
IFEELIN F_Do ( propobj, FM_Notify, "FA_Prop_First", FV_Notify_Always, propobj, FM_CallHook, 2, &prophook, FV_Notify_Value );
prophook will be called every time the knob is moving and gets a pointer to the knobs current level.
IFEELIN F_DoA(Obj, FM_CallHookEntry, FS_CallHookEntry);
This method is similar to the CallHook method, but it doesn't require a struct Hook because the function usualy referenced in h_Entry is called directly. Such a function should have been created with the F_HOOK() or F_HOOKM() macros.
Pointer to a function created with the F_HOOK() or F_HOOKM() macros.
Zero or more parameters.
standalone:
IFEELIN F_Do(obj, FM_CallHookEntry, MyFunc,13,42,"foobar","barfoo");
within a notification statement:
IFEELIN F_Do ( propobj, FM_Notify, "FA_Prop_First", FV_Notify_Always, propobj, FM_CallHookEntry,2, Hook_Prop,FV_Notify_Value );
Hook_Prop will be called every time the knob is moving and gets a pointer to the knobs current level in A1.
[virtual method]
IFEELIN F_Do(Obj, FM_Connect, FObject Parent);
Connect an orphan to a parent.
If you agree to the connection, you must return TRUE. If you return FALSE and you won't be connected to the family.
F_METHODM(uint32, Area_Connect, FS_Connect) { struct LocalObjectData *LOD = F_LOD(Class, Obj);
IFEELIN F_Log(FV_LOG_USER, "Parent: %s{%08lx}", _object_classname(Msg->Parent), Msg->Parent);
_area_parent = Msg->Parent;
return TRUE; }
[virtual method]
IFEELIN F_DoA(Obj, FM_Disconnect);
If you have agreed to the Connect method, this method is invoked when the family needs the object to be disconnected. (e.g. the family is about to be disposed, your object is about to be disposed).
If your object is ok to disconnect you must return TRUE, otherwise return FALSE and your object will not be disconnected from the family, which is not a good option.
F_METHOD(uint32,Area_Disconnect) { struct LocalObjectData *LOD = F_LOD(Class,Obj);
IFEELIN F_Log(FV_LOG_USER, NULL);
_area_parent = NULL;
return TRUE; }
[For use within classes only]
This method instruct an object to delete itself, it should do the following:
- Free any additionnal ressources the object explicitly allocated itself during the New method. If a class does not allocate any extra resources when it creates an object, it doesn't have to implement this method.
- Pass the message up to the superclass (as usual).
If the object has a Parent, it's invoked with the RemMember method before the object is actualy disposed. Also, all notifications are removed using the UnNotify method.
Don't ever use this method to dispose objects, instead use the feelin.library function F_DisposeObj().
IFEELIN F_DoA(Obj, FM_Get, TAGS);
Tells an object to report some attribute's values. Applications can call this method directly. The F_Get() function can also be used if only one attribute is requested.
A TAG_DONE-terminated array of struct TagItem describing which attributes should be reported, and where to save values.
uint32 val,min,max;
IFEELIN F_Do ( obj, FM_Get,
FA_Numeric_Value, &val, FA_Numeric_Min, &min, FA_Numeric_Max, &max,
TAG_DONE );
IFEELIN F_Do(Obj, FM_Lock, bits32 Flags);
This method is used to lock an object. The lock depends on the flags given as argument.
Each Lock invokation must be balanced by exactly one Unlock invokation. This is because there is a nesting count maintained of the number of times that the current task has locked the object. The object is not released to other tasks until the number of releases matches the number of obtains.
FF_Lock_Exclusive - Set this flag to gain an exlusive access. If another user (task) currently has the object locked the call will block until the object is made available. If the current task already has locked the object and attempts to lock it again the call will still succeed.
FF_Lock_Shared - Any number of tasks may simultaneously hold a shared lock on an object. Only one task may hold an exclusive lock. A typical application is a list that is often read, but only occasionally written to.
FF_Lock_Attempt - If this flag is set, the method tries to obtain the object without blocking e.i. the method will not block if the object cannot be locked. You can set this flags with FF_Lock_Exclusive and FF_Lock_Shared.
IFEELIN F_DoA(Obj, FM_MultiSet, FS_MultiSet);
Set an attribute for multiple objects. Receiving an attribute/value pair and a list of objects, this method sets the new value for all the objects in the list. This is especially useful for disabling/enabling lots of objects with one single function call.
The object that executes this method isn't affected !
Attribute to set.
New value for the attribute.
List of objects, terminated with a NULL pointer.
Disable all the addresses related gadgets. Note that xxx object doesn't get disabled.
IFEELIN F_Do ( xxx, FM_MultiSet, FA_Widget_Disabled, TRUE, ST_Name, ST_Street, ST_ity, ST_Country, ST_Phone, NULL );
[For use within classes only]
Each class keeps a record of how much memory its struct LocalObjectData requires. When an object is created, using the F_NewObjA() function, Feelin looks at the object's true class to find out how much memory to allocate for the object's data. Enough memory is allocated for the true class's local object data, plus enough memory for the local object data of each of the true class's superclasses. Afterward, the New method is invoked on the object.
During the New method, your class has to initialize its local object data. You can get a pointer to your local space by using the F_LOD() macro. You have to scan through the taglist of attribute/value pairs passed as argument to the method. If you recognize attributes, you have to initialize them to the value passed in the attribute/value pair.
Don't forget to pass the method to your superclass, using the F_SUPERDO() macro. It's a good idea to allocate memory or make further job after your superclass, this way, if your superclass fails, all your work won't have been made in vain. Also, always remember that in order to avoid each class from calling its local Set method, when the New method reaches the Object class, the Set method is invoked on the object's true class with the same taglist as the New method. Always check dependencies between attributes and any ressource that you may allocate. The F_SUPERDO() macro returns either the object's pointer or NULL if an error occured. If the object allocates any resources in this step, it has the chance to deallocat them later during the Dispose method.
When the New invokation finaly returns, it returns a pointer to the object or NULL if an error occured, in which case the Dispose method is invoked, giving each class a chance to free resources that it may have allocated.
F_METHOD(FObject,myNew) { struct LocalObjectData *LOD = F_LOD(Class,Obj); struct TagItem *Tags = Msg, item;
LOD->Device = "usb.device"; // Default values LOD->Unit = 0;
// Process [I..] attributes
while (IFEELIN F_DynamicNTI(&Tags,&item,Class)) switch (item.ti_Tag) { case FV_ATTRIBUTE_DEVICE: LOD->Device = (STRPTR) item.ti_Data; break; case FV_ATTRIBUTE_UNIT: LOD->Unit = item.ti_Data; break; }
if (F_SUPERDO() == 0) { return NULL; }
LOD->Request = IEXEC CreateIORequest(sizeof (struct MyRequest);
if (LOD->Request == NULL) { return NULL; }
return Obj; }
Return object pointer or NULL if something goes wrong.
IFEELIN F_DoA(Obj, FM_Notify, FS_Notify);
Add a notification event handler to an object. Notification is essential for Feelin applications.
A notification statement consists of a source object, an attribute/value pair, a target object (destination) and a notification method. The attribute/value pair belongs to the source object and determines when the notification method will be executed on the destination object.
Whenever the source object gets the given attribute set to the given value (this can happen because the user pressing some gadgets or because of your program explicitly setting the attribute with the F_Set() function or the Set method, the destination object will execute the notification method.
With some special values, you can trigger the notification every time the attribute is changing. In this case, you can include the trigerring attributes value within the notification method. See below.
Attribute that triggers notification.
Value that triggers the notification. The special value FV_Notify_Always makes Feelin execute the notification method every time when Attribute changes. In this case, the special value FV_Notify_Value in the notification method will be replaced with the value that Attribute has been set to. You can use FV_Notify_Value without restriction. You can also use FV_Notify_Toggle here. In this case, Feelin will replace TRUE values with FALSE and FALSE values with TRUE (e.g. !FV_Notify_Value). This can become quite useful when you try to set negative attributes like FA_Widget_Disabled.
Object on which to perform the notification method. Either supply a valid object pointer or one of the following special values which will be resolved at the time the event occurs:
FV_Notify_Self : Notifies the object itself.
FV_Notify_Parent : Notifies object parent.
FV_Notify_Window : Notifies object window.
FV_Notify_Application : Notifies object application.
The method to invoke on the Target. You can provide a Dynamic method name instead of its numerical representation.
Number of following arguments to the Method. If you e.g. have a notification method that sets an attribute to a value (like in a F_Do(Obj, FM_Set, attr, val, TAG_DONE)), you have to set NArgs to 2. This allows Feelin to copy the complete notification method into a private buffer for later use.
Following in the arguments to the Method.
A notification handler.
Although every notifications are removed when the object is disposed, it may be useful to use this returned value if you want to set a notification for a limited time.
Every time when the user release a button (and the mouse is still over it), the button object gets its FA_Widget_Pressed attribute set to FALSE. That's what a program can react on with notification, e.g. by opening another window.
IFEELIN F_Do ( buttonobj, FM_Notify, FA_Widget_Pressed, FALSE, winobj, FM_Set, 2, FA_Window_Open, TRUE );
Let's say we want to know the current value of a Prop gadget somewhere in a text field. FV_Notify_Value will be replaced with the current value of FA_Prop_First.
IFEELIN F_Do ( propobj, FM_Notify, FA_Prop_First, FV_Notify_Always, textobj, FM_SetAsString, 3, FA_Text_Contents,"Value is %ld !",FV_Notify_Value );
Inform our application to shutdown when the user close the main window:
IFEELIN F_Do ( win, FM_Notify, FA_Window_CloseRequest,TRUE, app,FM_Application_Shutdown,0 );
[virtual method]
IFEELIN F_Do(Obj, FM_RemMember, FObject Child);
Remove an object from a family.
The object to be removed, which before being actually removed is invoked with the Disconnect method. The object should have been previously added with the AddMember method.
IFEELIN F_DoA(Obj, FM_RemoveListener, FS_RemoveListener);
Used this function to remove a listener previously added with the AddListener method.
You don't have to manually remove all the listeners you've added to an object, because when the object gets disposed all remaining listeners will be automatically removed.
The attribute that was listened to.
The callback previously provided.
IFEELIN F_DoA(Obj, FM_Set, TAGS);
This method tells an object to set one or more of its attributes.
Applications can call this method directly. The function F_Set() can also be used if you only need to set one attribute, in which case the function will be faster and easier. The return value for this method is not explicitly defined, should be NULL.
When the method reaches the Object class, object's notifications are checked and handled. To avoid notifications set the attribute NoNotify to TRUE in the taglist.
A pointer to a tag list of attribute/value pairs. These pairs contain the IDs and the new values if the attributes to set. The dispatcher will look through this list using F_DynamicNTI() and set its private attributes (not superclass attributes). Once done, it will send the same list to its superclass.
Most objects will redraw themselves if one of their attribute is modified, e.g. a gauge will update its level display if its FA_Numeric_Value attribute is modified.
IFEELIN F_DoA(Obj, FM_SetAs, FS_SetAs);
This method can be used to set an attribute to a string. This method is really useful if you want to connect a numeric attribute of an object with a text attribute of another object.
FV_SetAs_String - A formated string is created. Data must be a pointer to a F_StrFmtA() formating string. The parameters used to format the string are the optionnal parameters following the FS_SetAs message.
FV_SetAs_Decimal - An int32 is created from a decimal string. Data must be a pointer to a decimal string such as "12" or "-65".
FV_SetAs_Hexadecimal - An uint32 is created from an hexadecimal string. Data must be a pointer to an hexadecimal string such as "12AF1C" or "ab4c6".
FF_SetAs_NoNotify - Set this flag if you want to set an attribute without triggering notifications.
The attribute to set.
The data to convert.
One or more parameters for the format string.
stand alone:
IFEELIN F_Do ( txobj, FM_SetAs, FV_SetAs_String, FA_Text_Contents, "My name is %s and I am %ld years old.", name, age );
within a notification statement:
IFEELIN F_Do ( propobj, FM_Notify, "FA_Prop_First", FV_Notify_Always, txobj, FM_SetAs,4, FV_SetAs_String, FA_Text_Contents, "prop gadget shows %ld.", FV_Notify_Value );
IFEELIN F_Do(Obj, FM_UnNotify, APTR Handler);
Remove notification(s) attached to the object specified.
Notification handlers are always removed when the object is disposed.
A notify handler, returned by the Notify method. If you provide ALL instead, all notifications attached to the object are removed.
In your setup method
LOD->nn_window_active = IFEELIN F_Do ( win, FM_Notify, FA_Window_Active, FV_Notify_Always, obj, FM_Set,2, FA_Widget_Active, FV_Notify_Value );
In your cleanup method
IFEELIN F_Do(win, FM_UnNotify, LOD->nn_window_active);
IFEELIN F_Do(Obj, FM_Unlock);
This method is the inverse of Lock, it makes the object lockable to other users. If tasks are waiting for the object and this task is done with it then the next waiting task is signalled.
Each Lock invokation must be balanced by exactly one Unlock invokation. This is because there is a nesting count maintained of the number of times that the current task has locked the object. The object is not released to other tasks until the number of releases matches the number of obtains.
F_HOOK(rc_type, function_name)
The macro F_HOOK() is used to define functions used by hooks.
F_HOOKM(rc_type, function_name, msg_type)
Same as the F_HOOK() macro except that this one allows defining the type of the variable Msg.
_object_class(object)
Use this macro to get the class of an object.
_object_classname(object)
Use this macro to get an object's class name.
IFEELIN F_Log(FV_LOG_USER, "Obj %s{%08lx}", _object_classname(Obj), Obj);