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 #include "cairo-dock-struct.h"
21 #include "cairo-dock-manager.h"
22 #include "cairo-dock-log.h"
23 #include "cairo-dock-object.h"
24
25 /* obj -> mgr0 -> mgr1 -> ... -> mgrN
26 * new_dialog -> new_object (mgr, attr) -> mgr->top_parent->init(attr) -> mgr->parent->init(attr) -> mgr->init(attr) --> notif
27 * unref_object -> ref-- -> notif -> mgr->destroy -> mgr->parent->destroy -> mgr->top_parent->destroy --> free
28 * GLDI_OBJECT_IS_xxx obj->mgr == pMgr || mgr->parent->mrg == pMgr || ...
29 * */
30
31
gldi_object_set_manager(GldiObject * pObject,GldiObjectManager * pMgr)32 void gldi_object_set_manager (GldiObject *pObject, GldiObjectManager *pMgr)
33 {
34 pObject->mgr = pMgr;
35 pObject->mgrs = g_list_copy (pMgr->object.mgrs);
36 pObject->mgrs = g_list_append (pObject->mgrs, pMgr);
37 gldi_object_install_notifications (pObject, pMgr->object.pNotificationsTab->len);
38 }
gldi_object_init(GldiObject * obj,GldiObjectManager * pMgr,gpointer attr)39 void gldi_object_init (GldiObject *obj, GldiObjectManager *pMgr, gpointer attr)
40 {
41 obj->ref = 1;
42 // set the manager
43 gldi_object_set_manager (obj, pMgr);
44
45 // init the object
46 GList *m;
47 for (m = obj->mgrs; m != NULL; m = m->next)
48 {
49 pMgr = m->data;
50 if (pMgr->init_object)
51 pMgr->init_object (obj, attr);
52 }
53 // emit a notification
54 gldi_object_notify (obj, NOTIFICATION_NEW, obj);
55 }
56
gldi_object_new(GldiObjectManager * pMgr,gpointer attr)57 GldiObject *gldi_object_new (GldiObjectManager *pMgr, gpointer attr)
58 {
59 GldiObject *obj = g_malloc0 (pMgr->iObjectSize);
60 gldi_object_init (obj, pMgr, attr);
61 return obj;
62 }
63
gldi_object_ref(GldiObject * pObject)64 void gldi_object_ref (GldiObject *pObject)
65 {
66 g_return_if_fail (pObject != NULL && pObject->ref > 0);
67 pObject->ref ++;
68 }
69
gldi_object_unref(GldiObject * pObject)70 void gldi_object_unref (GldiObject *pObject)
71 {
72 if (pObject == NULL)
73 return;
74 pObject->ref --;
75 if (pObject->ref == 0) // so if it was already 0, don't do anything
76 {
77 // emit a notification
78 gldi_object_notify (pObject, NOTIFICATION_DESTROY, pObject);
79
80 // reset the object
81 GldiObjectManager *pMgr = pObject->mgr;
82 while (pMgr)
83 {
84 if (pMgr->reset_object)
85 pMgr->reset_object (pObject);
86 pMgr = pMgr->object.mgr;
87 }
88
89 // clear notifications
90 GPtrArray *pNotificationsTab = pObject->pNotificationsTab;
91 guint i;
92 for (i = 0; i < pNotificationsTab->len; i ++)
93 {
94 GSList *pNotificationRecordList = g_ptr_array_index (pNotificationsTab, i);
95 g_slist_foreach (pNotificationRecordList, (GFunc)g_free, NULL);
96 g_slist_free (pNotificationRecordList);
97 }
98 g_ptr_array_free (pNotificationsTab, TRUE);
99
100 // free memory
101 g_free (pObject);
102 }
103 }
104
gldi_object_delete(GldiObject * pObject)105 void gldi_object_delete (GldiObject *pObject)
106 {
107 if (pObject == NULL)
108 return;
109
110 //\_________________ delete the object from the current theme
111 gboolean r = TRUE;
112 GldiObjectManager *pMgr = pObject->mgr;
113 while (pMgr)
114 {
115 if (pMgr->delete_object)
116 r = pMgr->delete_object (pObject);
117 if (!r)
118 return;
119 pMgr = pMgr->object.mgr;
120 }
121
122 //\_________________ destroy the object
123 gldi_object_unref (pObject);
124 }
125
gldi_object_reload(GldiObject * obj,gboolean bReloadConfig)126 void gldi_object_reload (GldiObject *obj, gboolean bReloadConfig)
127 {
128 GKeyFile *pKeyFile = NULL;
129 GList *m;
130 GldiObjectManager *pMgr;
131 for (m = obj->mgrs; m != NULL; m = m->next)
132 {
133 pMgr = m->data;
134 if (pMgr->reload_object)
135 pKeyFile = pMgr->reload_object (obj, bReloadConfig, pKeyFile);
136 }
137 if (pKeyFile)
138 g_key_file_free (pKeyFile);
139 }
140
gldi_object_is_manager_child(GldiObject * pObject,GldiObjectManager * pMgr)141 gboolean gldi_object_is_manager_child (GldiObject *pObject, GldiObjectManager *pMgr)
142 {
143 while (pObject)
144 {
145 if (pObject->mgr == pMgr)
146 return TRUE;
147 pObject = GLDI_OBJECT (pObject->mgr);
148 }
149 return FALSE;
150 }
151
152
gldi_object_register_notification(gpointer pObject,GldiNotificationType iNotifType,GldiNotificationFunc pFunction,gboolean bRunFirst,gpointer pUserData)153 void gldi_object_register_notification (gpointer pObject, GldiNotificationType iNotifType, GldiNotificationFunc pFunction, gboolean bRunFirst, gpointer pUserData)
154 {
155 g_return_if_fail (pObject != NULL);
156 // grab the notifications tab
157 GPtrArray *pNotificationsTab = GLDI_OBJECT(pObject)->pNotificationsTab;
158 if (!pNotificationsTab || pNotificationsTab->len < iNotifType)
159 {
160 cd_warning ("someone tried to register to an inexisting notification (%d) on an object of type '%s'", iNotifType, gldi_object_get_type(pObject));
161 return ; // don't try to create/resize the notifications tab, since noone will emit this notification.
162 }
163
164 // add a record
165 GldiNotificationRecord *pNotificationRecord = g_new (GldiNotificationRecord, 1);
166 pNotificationRecord->pFunction = pFunction;
167 pNotificationRecord->pUserData = pUserData;
168
169 GSList *pNotificationRecordList = g_ptr_array_index (pNotificationsTab, iNotifType);
170 pNotificationsTab->pdata[iNotifType] = (bRunFirst ? g_slist_prepend : g_slist_append) (pNotificationRecordList, pNotificationRecord);
171 }
172
173
gldi_object_remove_notification(gpointer pObject,GldiNotificationType iNotifType,GldiNotificationFunc pFunction,gpointer pUserData)174 void gldi_object_remove_notification (gpointer pObject, GldiNotificationType iNotifType, GldiNotificationFunc pFunction, gpointer pUserData)
175 {
176 g_return_if_fail (pObject != NULL);
177 // grab the notifications tab
178 GPtrArray *pNotificationsTab = GLDI_OBJECT(pObject)->pNotificationsTab;
179
180 // remove the record
181 GSList *pNotificationRecordList = g_ptr_array_index (pNotificationsTab, iNotifType);
182 GldiNotificationRecord *pNotificationRecord;
183 GSList *nr;
184 for (nr = pNotificationRecordList; nr != NULL; nr = nr->next)
185 {
186 pNotificationRecord = nr->data;
187 if (pNotificationRecord->pFunction == pFunction && pNotificationRecord->pUserData == pUserData)
188 {
189 pNotificationsTab->pdata[iNotifType] = g_slist_delete_link (pNotificationRecordList, nr);
190 g_free (pNotificationRecord);
191 break;
192 }
193 }
194 }
195