1 /* 2 * This file is a part of the Cairo-Dock project 3 * 4 * Copyright : (C) see the 'copyright' file. 5 * E-mail : see the 'copyright' file. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 3 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef __CAIRO_DOCK_OBJECT__ 21 #define __CAIRO_DOCK_OBJECT__ 22 23 #include <glib.h> 24 #include "cairo-dock-struct.h" 25 26 G_BEGIN_DECLS 27 28 /** 29 *@file cairo-dock-object.h This class defines the Objects, the base class of libgldi. 30 * Every element in this library is an Object. 31 * An object is defined by an ObjectManager, which defines its capabilities and signals. 32 * 33 * Any object is created with \ref gldi_object_new and destroyed with \ref gldi_object_unref. 34 * An object can be deleted from the current theme with \ref gldi_object_delete. 35 * An object can be reloaded with \ref gldi_object_reload. 36 * 37 * You can listen for notifications on an object with \ref gldi_object_register_notification and stop listening with \ref gldi_object_remove_notification. 38 * To listen for notifications on any object of a given type, simply register yourself on its ObjectManager. 39 */ 40 41 /// Definition of an Object. 42 struct _GldiObject { 43 gint ref; 44 GPtrArray *pNotificationsTab; 45 GldiObjectManager *mgr; 46 GList *mgrs; // sorted in reverse order 47 }; 48 49 /// Definition of an ObjectManager. 50 struct _GldiObjectManager { 51 GldiObject object; 52 const gchar *cName; 53 gint iObjectSize; 54 void (*init_object) (GldiObject *pObject, gpointer attr); 55 void (*reset_object) (GldiObject *pObject); 56 gboolean (*delete_object) (GldiObject *pObject); 57 GKeyFile* (*reload_object) (GldiObject *pObject, gboolean bReloadConf, GKeyFile *pKeyFile); 58 }; 59 60 61 /// signals (any object has at least these ones) 62 typedef enum { 63 /// notification called when an object has been created. data : the object 64 NOTIFICATION_NEW, 65 /// notification called when the object is going to be destroyed. data : the object 66 NOTIFICATION_DESTROY, 67 NB_NOTIFICATIONS_OBJECT 68 } GldiObjectNotifications; 69 70 #define GLDI_OBJECT(p) ((GldiObject*)(p)) 71 72 73 void gldi_object_init (GldiObject *obj, GldiObjectManager *pMgr, gpointer attr); 74 75 /** Create a new object. 76 * @param pMgr the ObjectManager 77 * @param attr the attributes of the object 78 * @return the new object, with a reference of 1; use \ref gldi_object_unref to destroy it 79 */ 80 GldiObject *gldi_object_new (GldiObjectManager *pMgr, gpointer attr); 81 82 /** Take a reference on an object. 83 * @param pObject the Object 84 */ 85 void gldi_object_ref (GldiObject *pObject); 86 87 /** Drop your reference on an object. If it's the last reference, the object is destroyed, otherwise nothing happens. 88 * @param pObject the Object 89 */ 90 void gldi_object_unref (GldiObject *pObject); 91 92 /** Delete an object from the current theme. The object is unref'd, and won't be created again on next startup. 93 * @param pObject the Object 94 */ 95 void gldi_object_delete (GldiObject *pObject); 96 97 /** Reload an object. 98 * @param pObject the Object 99 * @param bReloadConfig TRUE to read its config file again (if the object has one) 100 */ 101 void gldi_object_reload (GldiObject *pObject, gboolean bReloadConfig); 102 103 /* Sets the ObjectManager of an object. It is only useful to make an ObjectManager derive from another one. For any other object, it is done automatically. 104 */ 105 void gldi_object_set_manager (GldiObject *pObject, GldiObjectManager *pMgr); 106 107 gboolean gldi_object_is_manager_child (GldiObject *pObject, GldiObjectManager *pMgr); 108 109 #define gldi_object_get_type(obj) (GLDI_OBJECT(obj)->mgr ? GLDI_OBJECT(obj)->mgr->cName : "ObjectManager") 110 111 112 /// Generic prototype of a notification callback. 113 typedef gboolean (* GldiNotificationFunc) (gpointer pUserData, ...); 114 115 typedef struct { 116 GldiNotificationFunc pFunction; 117 gpointer pUserData; 118 } GldiNotificationRecord; 119 120 typedef guint GldiNotificationType; 121 122 /// Use this in \ref gldi_object_register_notification to be called before the core. 123 #define GLDI_RUN_FIRST TRUE 124 /// Use this in \ref gldi_object_register_notification to be called after the core. 125 #define GLDI_RUN_AFTER FALSE 126 127 /// Return this in your callback to prevent the other callbacks from being called after you. 128 #define GLDI_NOTIFICATION_INTERCEPT TRUE 129 /// Return this in your callback to let pass the notification to the other callbacks after you. 130 #define GLDI_NOTIFICATION_LET_PASS FALSE 131 132 133 #define gldi_object_install_notifications(pObject, iNbNotifs) do {\ 134 GPtrArray *pNotificationsTab = (GLDI_OBJECT(pObject))->pNotificationsTab;\ 135 if (pNotificationsTab == NULL) {\ 136 pNotificationsTab = g_ptr_array_new ();\ 137 (GLDI_OBJECT(pObject))->pNotificationsTab = pNotificationsTab; }\ 138 if (pNotificationsTab->len < iNbNotifs)\ 139 g_ptr_array_set_size (pNotificationsTab, iNbNotifs); } while (0) 140 141 /** Register an action to be called when a given notification is broadcasted from a given object. 142 *@param pObject the object (Icon, Container, Manager). 143 *@param iNotifType type of the notification. 144 *@param pFunction callback. 145 *@param bRunFirst GLDI_RUN_FIRST to be called before Cairo-Dock, GLDI_RUN_AFTER to be called after. 146 *@param pUserData data to be passed as the first parameter of the callback. 147 */ 148 void gldi_object_register_notification (gpointer pObject, GldiNotificationType iNotifType, GldiNotificationFunc pFunction, gboolean bRunFirst, gpointer pUserData); 149 150 /** Remove a callback from the list of callbacks of a given object for a given notification and a given data. 151 Note: it is safe to remove the callback when it is called, but not another one. 152 *@param pObject the object (Icon, Container, Manager) for which the action has been registered. 153 *@param iNotifType type of the notification. 154 *@param pFunction callback. 155 *@param pUserData data that was registerd with the callback. 156 */ 157 void gldi_object_remove_notification (gpointer pObject, GldiNotificationType iNotifType, GldiNotificationFunc pFunction, gpointer pUserData); 158 159 160 #define __notify(pNotificationRecordList, bStop, ...) do {\ 161 GldiNotificationRecord *pNotificationRecord;\ 162 GSList *pElement = pNotificationRecordList, *pNextElement;\ 163 while (pElement != NULL && ! bStop) {\ 164 pNotificationRecord = pElement->data;\ 165 pNextElement = pElement->next;\ 166 bStop = pNotificationRecord->pFunction (pNotificationRecord->pUserData, ##__VA_ARGS__);\ 167 pElement = pNextElement; }\ 168 } while (0) 169 170 #define __notify_on_object(pObject, iNotifType, ...) \ 171 __extension__ ({\ 172 gboolean _stop = FALSE;\ 173 GPtrArray *pNotificationsTab = (pObject)->pNotificationsTab;\ 174 if (pNotificationsTab && iNotifType < pNotificationsTab->len) {\ 175 GSList *pNotificationRecordList = g_ptr_array_index (pNotificationsTab, iNotifType);\ 176 __notify (pNotificationRecordList, _stop, ##__VA_ARGS__);} \ 177 else {_stop = TRUE;}\ 178 _stop; }) 179 180 /** Broadcast a notification on a given object, and on all its managers. 181 *@param pObject the object (Icon, Container, Manager, ...). 182 *@param iNotifType type of the notification. 183 *@param ... parameters to be passed to the callbacks that have registered to this notification. 184 */ 185 #define gldi_object_notify(pObject, iNotifType, ...) \ 186 __extension__ ({\ 187 gboolean _bStop = FALSE;\ 188 GldiObject *_obj = GLDI_OBJECT (pObject);\ 189 while (_obj && !_bStop) {\ 190 _bStop = __notify_on_object (_obj, iNotifType, ##__VA_ARGS__);\ 191 _obj = GLDI_OBJECT (_obj->mgr); }\ 192 }) 193 194 195 196 #define GLDI_STR_HELPER(x) #x 197 #define GLDI_STR(x) GLDI_STR_HELPER(x) 198 199 #define GLDI_MGR_NAME(name) my##name##ObjectMgr 200 #define GLDI_OBJECT_NAME(name) Gldi##name 201 202 #define GLDI_OBJECT_MANAGER_REGISTER(name) gldi_##name##_object_manager_register() 203 204 #define GLDI_OBJECT_MANAGER_DEFINE_H(name) void GLDI_OBJECT_MANAGER_REGISTER(name) 205 206 //name=Dock, NAME=DOCK 207 #define GLDI_OBJECT_MANAGER_DEFINE_BEGIN(name, NAME) \ 208 GLDI_OBJECT_MANAGER_DEFINE_H(name) \ 209 { \ 210 GldiObjectManager *mgr = &GLDI_MGR_NAME(name); \ 211 memset (mgr, 0, sizeof (GldiObjectManager)); \ 212 mgr->cName = GLDI_STR(name); \ 213 mgr->iObjectSize = sizeof (GLDI_OBJECT_NAME(name)); \ 214 gldi_object_install_notifications (mgr, NB_NOTIFICATIONS_##NAME); 215 216 #define GLDI_OBJECT_MANAGER_HAS_INIT mgr->init_object = init_object; 217 #define GLDI_OBJECT_MANAGER_HAS_RESET mgr->reset_object = reset_object; 218 #define GLDI_OBJECT_MANAGER_HAS_DELETE mgr->delete_object = delete_object; 219 #define GLDI_OBJECT_MANAGER_HAS_RELOAD mgr->reload_object = reload_object; 220 221 #define GLDI_OBJECT_MANAGER_DERIVES_FROM(mgr2) gldi_object_set_manager (GLDI_OBJECT (mgr), mgr2) 222 223 #define GLDI_OBJECT_MANAGER_DEFINE_END } 224 225 226 G_END_DECLS 227 #endif 228