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