The dimming manager now runs dispose over the rules groups in dispose method to break...
[modest] / src / modest-ui-dimming-manager.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-debug.h"
31 #include "modest-ui-dimming-manager.h"
32 #include "modest-dimming-rules-group-priv.h"
33
34 static void modest_ui_dimming_manager_class_init (ModestUIDimmingManagerClass *klass);
35 static void modest_ui_dimming_manager_init       (ModestUIDimmingManager *obj);
36 static void modest_ui_dimming_manager_finalize   (GObject *obj);
37 static void modest_ui_dimming_manager_dispose    (GObject *obj);
38
39 static void _process_all_rules (gpointer key, gpointer value, gpointer user_data);
40
41 #define WIDGET_DIMMING_MODE "widget-dimming-mode"
42
43
44 typedef struct _ModestUIDimmingManagerPrivate ModestUIDimmingManagerPrivate;
45 struct _ModestUIDimmingManagerPrivate {
46         GHashTable *groups_map;
47         GHashTable *delayed_calls;
48 };
49
50 #define MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
51                                                    MODEST_TYPE_UI_DIMMING_MANAGER, \
52                                                    ModestUIDimmingManagerPrivate))
53
54 /* globals */
55 static GObjectClass *parent_class = NULL;
56
57 GType
58 modest_ui_dimming_manager_get_type (void)
59 {
60         static GType my_type = 0;
61         if (!my_type) {
62                 static const GTypeInfo my_info = {
63                         sizeof(ModestUIDimmingManagerClass),
64                         NULL,           /* base init */
65                         NULL,           /* base finalize */
66                         (GClassInitFunc) modest_ui_dimming_manager_class_init,
67                         NULL,           /* class finalize */
68                         NULL,           /* class data */
69                         sizeof(ModestUIDimmingManager),
70                         1,              /* n_preallocs */
71                         (GInstanceInitFunc) modest_ui_dimming_manager_init,
72                         NULL
73                 };
74                 my_type = g_type_register_static (G_TYPE_OBJECT,
75                                                   "ModestUIDimmingManager",
76                                                   &my_info, 0);
77         }
78         return my_type;
79 }
80
81 static void
82 modest_ui_dimming_manager_class_init (ModestUIDimmingManagerClass *klass)
83 {
84         GObjectClass *gobject_class;
85         gobject_class = (GObjectClass*) klass;
86
87         parent_class            = g_type_class_peek_parent (klass);
88         gobject_class->finalize = modest_ui_dimming_manager_finalize;
89         gobject_class->dispose  = modest_ui_dimming_manager_dispose;
90
91         g_type_class_add_private (gobject_class, sizeof(ModestUIDimmingManagerPrivate));
92 }
93
94 static void
95 modest_ui_dimming_manager_init (ModestUIDimmingManager *obj)
96 {
97         ModestUIDimmingManagerPrivate *priv;
98
99         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
100
101         priv->groups_map = g_hash_table_new_full ((GHashFunc) g_str_hash,
102                                                   (GEqualFunc) g_str_equal,
103                                                   (GDestroyNotify) g_free,
104                                                   (GDestroyNotify) g_object_unref);
105         priv->delayed_calls = g_hash_table_new_full (g_str_hash,
106                                                      g_str_equal,
107                                                      g_free,
108                                                      NULL);
109 }
110
111 static void
112 remove_all_timeouts (gpointer key, 
113                      gpointer value, 
114                      gpointer user_data)
115 {
116         if (GPOINTER_TO_INT (value) > 0)
117                 g_source_remove (GPOINTER_TO_INT (value));
118 }
119
120 static void
121 modest_ui_dimming_manager_finalize (GObject *obj)
122 {
123         ModestUIDimmingManagerPrivate *priv;
124
125         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
126
127         if (priv->groups_map != NULL)
128                 g_hash_table_unref (priv->groups_map);
129
130         if (priv->delayed_calls != NULL) {
131                 /* Remove all pending calls */
132                 g_hash_table_foreach (priv->delayed_calls,
133                                       remove_all_timeouts,
134                                       NULL);
135
136                 g_hash_table_unref (priv->delayed_calls);
137         }
138
139         G_OBJECT_CLASS(parent_class)->finalize (obj);
140 }
141
142 static void
143 modest_ui_dimming_manager_dispose (GObject *obj)
144 {
145         ModestUIDimmingManagerPrivate *priv;
146
147         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
148
149         if (priv->delayed_calls != NULL && (g_hash_table_size (priv->delayed_calls) > 0)) {
150                 /* Remove all pending calls */
151                 g_hash_table_foreach (priv->delayed_calls,
152                                       remove_all_timeouts,
153                                       NULL);
154                 g_hash_table_remove_all (priv->delayed_calls);
155         }
156
157         if (priv->groups_map) {
158                 g_hash_table_foreach (priv->groups_map, g_object_run_dispose, NULL);
159                 g_hash_table_unref (priv->groups_map);
160                 priv->groups_map = NULL;
161         }
162
163         G_OBJECT_CLASS(parent_class)->dispose (obj);
164 }
165
166
167 ModestUIDimmingManager*
168 modest_ui_dimming_manager_new()
169 {
170         ModestUIDimmingManager *obj;
171
172         obj = MODEST_UI_DIMMING_MANAGER(g_object_new(MODEST_TYPE_UI_DIMMING_MANAGER, NULL));
173
174
175         return obj;
176 }
177
178 void
179 modest_ui_dimming_manager_insert_rules_group (ModestUIDimmingManager *self,
180                                               ModestDimmingRulesGroup *group)
181 {
182         ModestUIDimmingManagerPrivate *priv;
183         gchar *group_name = NULL;
184         gboolean unique = FALSE;
185         
186         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
187         
188         /* Get group name */
189         group_name = modest_dimming_rules_group_get_name (group);
190         
191         /* Check group name is unique */
192         unique = g_hash_table_lookup (priv->groups_map, group_name) == NULL;
193         if (!unique) {
194                 g_free(group_name);
195                 g_return_if_fail (unique);
196         }
197         
198         
199         /* Insert new dimming rules group */
200         g_hash_table_insert (priv->groups_map, group_name, g_object_ref(group));
201 }
202
203 void
204 modest_ui_dimming_manager_process_dimming_rules (ModestUIDimmingManager *self)
205 {
206         ModestUIDimmingManagerPrivate *priv;
207         
208         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
209
210         /* Peforms a full dimming tules checking */
211         g_hash_table_foreach (priv->groups_map, _process_all_rules, NULL);
212 }
213
214 typedef struct
215 {
216         ModestDimmingRulesGroup *group;
217         ModestUIDimmingManager *manager;
218         gchar *name;
219         gboolean delete;
220 } DelayedDimmingRules;
221
222 static gboolean
223 process_dimming_rules_delayed (gpointer data)
224 {
225         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
226         gpointer timeout_handler;
227         ModestUIDimmingManagerPrivate *priv;
228
229         /* Let the destroyer remove it from the hash table */
230         helper->delete = TRUE;
231
232         /* We remove the timeout here because the execute action could
233            take too much time, and so this will be called again */
234         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
235         timeout_handler = g_hash_table_lookup (priv->delayed_calls, helper->name);
236
237         if (GPOINTER_TO_INT (timeout_handler) > 0) {
238                 g_source_remove (GPOINTER_TO_INT (timeout_handler));
239         }
240
241         gdk_threads_enter ();
242         modest_dimming_rules_group_execute (helper->group);
243         gdk_threads_leave ();
244
245         return FALSE;
246 }
247
248 static void
249 process_dimming_rules_delayed_destroyer (gpointer data)
250 {
251         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
252         ModestUIDimmingManagerPrivate *priv;
253
254         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
255
256         /* We can only destroy it if we had really executed it. If the
257            source is removed because the manager is finalized then we
258            cannot remove it because it removes the sources in a
259            foreach, that does not allow you to modify the hash table
260            in the mean time */
261         if (helper->delete)
262                 g_hash_table_remove (priv->delayed_calls, helper->name);
263
264         g_free (helper->name);
265         g_object_unref (helper->manager);
266         g_slice_free (DelayedDimmingRules, helper);
267 }
268
269 void
270 modest_ui_dimming_manager_process_dimming_rules_group (ModestUIDimmingManager *self,
271                                                        const gchar *group_name)
272 {
273         ModestDimmingRulesGroup *group = NULL;
274         ModestUIDimmingManagerPrivate *priv;
275         guint *handler, new_handler;
276         DelayedDimmingRules *helper;
277
278         g_return_if_fail (group_name != NULL);
279
280         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
281
282         /* Search group by name */
283         group = MODEST_DIMMING_RULES_GROUP(g_hash_table_lookup (priv->groups_map, group_name));
284         g_return_if_fail (group != NULL);
285
286         /* If there was another pending dimming operation check then ignore this */
287         handler = g_hash_table_lookup (priv->delayed_calls, group_name);
288         if (!handler) {
289                 /* Create the helper and start the timeout */
290                 helper = g_slice_new (DelayedDimmingRules);
291                 helper->group = group;
292                 helper->manager = g_object_ref (self);
293                 helper->name = g_strdup (group_name);
294                 helper->delete = FALSE;
295                 new_handler = g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
296                                                   process_dimming_rules_delayed,
297                                                   helper, process_dimming_rules_delayed_destroyer);
298                 g_hash_table_insert (priv->delayed_calls, 
299                                      g_strdup (group_name), 
300                                      GINT_TO_POINTER (new_handler));
301                 MODEST_DEBUG_BLOCK(g_print ("---------------------Adding %d\n", new_handler););
302         } else {
303                 MODEST_DEBUG_BLOCK(g_print ("---------------------Ignoring\n"););
304         }
305 }
306
307
308 static void
309 _process_all_rules (gpointer key, gpointer value, gpointer user_data)
310 {
311         g_return_if_fail (MODEST_IS_DIMMING_RULES_GROUP (value));
312
313         modest_dimming_rules_group_execute (MODEST_DIMMING_RULES_GROUP (value));
314 }
315
316 void
317 modest_ui_dimming_manager_set_widget_dimming_mode (GtkWidget *widget,
318                                                    ModestUIDimmingMode mode)
319 {
320         g_return_if_fail (GTK_IS_WIDGET (widget));
321
322         g_object_set_data (G_OBJECT (widget), WIDGET_DIMMING_MODE, GINT_TO_POINTER (mode));
323 }
324
325 ModestUIDimmingMode
326 modest_ui_dimming_manager_get_widget_dimming_mode (GtkWidget *widget)
327 {
328         g_return_val_if_fail (GTK_IS_WIDGET (widget), MODEST_UI_DIMMING_MODE_DIM);
329
330         return (ModestUIDimmingMode) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), WIDGET_DIMMING_MODE));
331 }
332