Add check support cancel note.
[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 dispose_objects  (gpointer key,
144                   gpointer value,
145                   gpointer user_data)
146 {
147         if (G_IS_OBJECT (value))
148             g_object_run_dispose (value);
149 }
150
151 static void
152 modest_ui_dimming_manager_dispose (GObject *obj)
153 {
154         ModestUIDimmingManagerPrivate *priv;
155
156         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(obj);
157
158         if (priv->delayed_calls != NULL && (g_hash_table_size (priv->delayed_calls) > 0)) {
159                 /* Remove all pending calls */
160                 g_hash_table_foreach (priv->delayed_calls,
161                                       remove_all_timeouts,
162                                       NULL);
163                 g_hash_table_remove_all (priv->delayed_calls);
164         }
165
166         if (priv->groups_map) {
167                 g_hash_table_foreach (priv->groups_map, dispose_objects, NULL);
168                 g_hash_table_unref (priv->groups_map);
169                 priv->groups_map = NULL;
170         }
171
172         G_OBJECT_CLASS(parent_class)->dispose (obj);
173 }
174
175
176 ModestUIDimmingManager*
177 modest_ui_dimming_manager_new()
178 {
179         ModestUIDimmingManager *obj;
180
181         obj = MODEST_UI_DIMMING_MANAGER(g_object_new(MODEST_TYPE_UI_DIMMING_MANAGER, NULL));
182
183
184         return obj;
185 }
186
187 void
188 modest_ui_dimming_manager_insert_rules_group (ModestUIDimmingManager *self,
189                                               ModestDimmingRulesGroup *group)
190 {
191         ModestUIDimmingManagerPrivate *priv;
192         gchar *group_name = NULL;
193         gboolean unique = FALSE;
194         
195         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
196         
197         /* Get group name */
198         group_name = modest_dimming_rules_group_get_name (group);
199         
200         /* Check group name is unique */
201         unique = g_hash_table_lookup (priv->groups_map, group_name) == NULL;
202         if (!unique) {
203                 g_free(group_name);
204                 g_return_if_fail (unique);
205         }
206         
207         
208         /* Insert new dimming rules group */
209         g_hash_table_insert (priv->groups_map, group_name, g_object_ref(group));
210 }
211
212 void
213 modest_ui_dimming_manager_process_dimming_rules (ModestUIDimmingManager *self)
214 {
215         ModestUIDimmingManagerPrivate *priv;
216         
217         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
218
219         /* Peforms a full dimming tules checking */
220         g_hash_table_foreach (priv->groups_map, _process_all_rules, NULL);
221 }
222
223 typedef struct
224 {
225         ModestDimmingRulesGroup *group;
226         ModestUIDimmingManager *manager;
227         gchar *name;
228         gboolean delete;
229 } DelayedDimmingRules;
230
231 static gboolean
232 process_dimming_rules_delayed (gpointer data)
233 {
234         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
235         gpointer timeout_handler;
236         ModestUIDimmingManagerPrivate *priv;
237
238         /* Let the destroyer remove it from the hash table */
239         helper->delete = TRUE;
240
241         /* We remove the timeout here because the execute action could
242            take too much time, and so this will be called again */
243         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
244         timeout_handler = g_hash_table_lookup (priv->delayed_calls, helper->name);
245
246         if (GPOINTER_TO_INT (timeout_handler) > 0) {
247                 g_source_remove (GPOINTER_TO_INT (timeout_handler));
248         }
249
250         gdk_threads_enter ();
251         modest_dimming_rules_group_execute (helper->group);
252         gdk_threads_leave ();
253
254         return FALSE;
255 }
256
257 static void
258 process_dimming_rules_delayed_destroyer (gpointer data)
259 {
260         DelayedDimmingRules *helper = (DelayedDimmingRules *) data;
261         ModestUIDimmingManagerPrivate *priv;
262
263         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(helper->manager);
264
265         /* We can only destroy it if we had really executed it. If the
266            source is removed because the manager is finalized then we
267            cannot remove it because it removes the sources in a
268            foreach, that does not allow you to modify the hash table
269            in the mean time */
270         if (helper->delete)
271                 g_hash_table_remove (priv->delayed_calls, helper->name);
272
273         g_free (helper->name);
274         g_object_unref (helper->manager);
275         g_slice_free (DelayedDimmingRules, helper);
276 }
277
278 void
279 modest_ui_dimming_manager_process_dimming_rules_group (ModestUIDimmingManager *self,
280                                                        const gchar *group_name)
281 {
282         ModestDimmingRulesGroup *group = NULL;
283         ModestUIDimmingManagerPrivate *priv;
284         guint *handler, new_handler;
285         DelayedDimmingRules *helper;
286
287         g_return_if_fail (group_name != NULL);
288
289         priv = MODEST_UI_DIMMING_MANAGER_GET_PRIVATE(self);
290
291         /* Search group by name */
292         group = MODEST_DIMMING_RULES_GROUP(g_hash_table_lookup (priv->groups_map, group_name));
293         g_return_if_fail (group != NULL);
294
295         /* If there was another pending dimming operation check then ignore this */
296         handler = g_hash_table_lookup (priv->delayed_calls, group_name);
297         if (!handler) {
298                 /* Create the helper and start the timeout */
299                 helper = g_slice_new (DelayedDimmingRules);
300                 helper->group = group;
301                 helper->manager = g_object_ref (self);
302                 helper->name = g_strdup (group_name);
303                 helper->delete = FALSE;
304                 new_handler = g_timeout_add_full (G_PRIORITY_DEFAULT, 100,
305                                                   process_dimming_rules_delayed,
306                                                   helper, process_dimming_rules_delayed_destroyer);
307                 g_hash_table_insert (priv->delayed_calls, 
308                                      g_strdup (group_name), 
309                                      GINT_TO_POINTER (new_handler));
310                 MODEST_DEBUG_BLOCK(g_print ("---------------------Adding %d\n", new_handler););
311         } else {
312                 MODEST_DEBUG_BLOCK(g_print ("---------------------Ignoring\n"););
313         }
314 }
315
316
317 static void
318 _process_all_rules (gpointer key, gpointer value, gpointer user_data)
319 {
320         g_return_if_fail (MODEST_IS_DIMMING_RULES_GROUP (value));
321
322         modest_dimming_rules_group_execute (MODEST_DIMMING_RULES_GROUP (value));
323 }
324
325 void
326 modest_ui_dimming_manager_set_widget_dimming_mode (GtkWidget *widget,
327                                                    ModestUIDimmingMode mode)
328 {
329         g_return_if_fail (GTK_IS_WIDGET (widget));
330
331         g_object_set_data (G_OBJECT (widget), WIDGET_DIMMING_MODE, GINT_TO_POINTER (mode));
332 }
333
334 ModestUIDimmingMode
335 modest_ui_dimming_manager_get_widget_dimming_mode (GtkWidget *widget)
336 {
337         g_return_val_if_fail (GTK_IS_WIDGET (widget), MODEST_UI_DIMMING_MODE_DIM);
338
339         return (ModestUIDimmingMode) GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), WIDGET_DIMMING_MODE));
340 }
341