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