Draw main message directly using cairo/pango
[conv-inbox] / src / el-home-applet.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /*
3  *  Copyright (C) 2009 Artem Garmash. All rights reserved.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * Contact: Artem Garmash <artemgarmash@gmail.com>
20  *
21  */
22
23 #include "config.h"
24 #include "el-home-applet.h"
25
26 #include <hildon/hildon.h>
27 #include <rtcom-eventlogger/eventlogger.h>
28 #include <sqlite3.h>
29 #include <string.h>
30
31 #define EL_HOME_APPLET_GET_PRIVATE(obj) ( \
32         G_TYPE_INSTANCE_GET_PRIVATE (obj, \
33                 EL_TYPE_HOME_APPLET, ELHomeAppletPrivate))
34
35 #define BOX_WIDTH 352
36 #define BOX_HEIGHT 256
37
38 #define C_WIDTH (BOX_WIDTH - 2*HILDON_MARGIN_HALF)
39 #define C_HEIGHT (BOX_HEIGHT - 2*HILDON_MARGIN_HALF)
40 #define C_X HILDON_MARGIN_HALF
41 #define C_Y HILDON_MARGIN_HALF
42
43 #define HEADER_HEIGHT 48
44 #define MESSAGE_HEIGHT (C_HEIGHT - HEADER_HEIGHT)
45 #define MESSAGE_WIDTH (C_WIDTH - 2*HILDON_MARGIN_DEFAULT)
46
47 #define BOX_RADIOUS 10
48
49 #define DEBUG_LAYOUT
50
51 struct _ELHomeAppletPrivate
52 {
53         RTComEl *eventlogger;
54
55         GtkWidget *sender;
56         GtkWidget *icon;
57         GtkWidget *unread;
58         GtkWidget *received;
59         GtkWidget *empty;
60
61         gchar *message;
62         gint event_id;
63
64         gboolean active;
65
66         guint unread_count;
67
68         const gchar *current_font;
69
70         guint idle_id;
71 };
72
73 HD_DEFINE_PLUGIN_MODULE (ELHomeApplet, el_home_applet, HD_TYPE_HOME_PLUGIN_ITEM);
74
75 const gchar* g_module_check_init(GModule *module);
76 const gchar*
77 g_module_check_init(GModule *module)
78 {
79         g_module_make_resident (module);
80         return NULL;
81 }
82
83 static void
84 el_home_applet_class_finalize (ELHomeAppletClass *klass)
85 {
86 }
87
88 static void
89 el_home_applet_realize (GtkWidget *widget)
90 {
91         GdkScreen *screen;
92
93         screen = gtk_widget_get_screen (widget);
94         gtk_widget_set_colormap (widget,
95                                  gdk_screen_get_rgba_colormap (screen));
96
97         gtk_widget_set_app_paintable (widget,
98                                       TRUE);
99
100         GTK_WIDGET_CLASS (el_home_applet_parent_class)->realize (widget);
101 }
102
103 /*
104  * Thanks http://cairographics.org/cookbook/roundedrectangles/
105  */
106 static void
107 rounded_rectangle (cairo_t *cr,
108                    double   x,
109                    double   y,
110                    double   w,
111                    double   h,
112                    double   r)
113 {
114         cairo_move_to (cr, x + r, y);
115         cairo_line_to (cr, x + w - r, y);
116         cairo_curve_to (cr, x + w, y,
117                         x + w, y,
118                         x + w, y + r);
119         cairo_line_to (cr, x + w, y + h - r);
120         cairo_curve_to (cr, x + w, y + h,
121                         x + w, y + h,
122                         x + w - r, y + h);
123         cairo_line_to (cr, x + r, y + h);
124         cairo_curve_to (cr, x, y + h,
125                         x, y + h,
126                         x, y + h - r);
127         cairo_line_to (cr, x, y + r);
128         cairo_curve_to (cr, x, y,
129                         x, y,
130                         x + r, y);
131 }
132
133 static void
134 draw_text (cairo_t *cr,
135            const gchar *text,
136            double x,
137            double y,
138            int width,
139            int height)
140 {
141         PangoLayout *layout;
142         PangoFontDescription *desc;
143
144         /* Create a PangoLayout, set the font and text */
145         layout = pango_cairo_create_layout (cr);
146         pango_layout_set_text (layout,
147                                text,
148                                -1);
149         desc = pango_font_description_from_string ("Sans 17");
150         pango_layout_set_font_description (layout, desc);
151         pango_font_description_free (desc);
152
153         pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
154         pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END);
155         pango_layout_set_width (layout, PANGO_SCALE*width);
156         pango_layout_set_height (layout, PANGO_SCALE*height);
157
158         /* draw shadow */
159         cairo_move_to (cr, x + 1, y + 1);
160         cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.8);
161         pango_cairo_show_layout (cr, layout);
162
163         /* draw fg */
164         cairo_move_to (cr, x, y);
165         cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
166         pango_cairo_show_layout (cr, layout);
167
168         g_object_unref (layout);
169 }
170
171 static gboolean
172 expose_event (GtkWidget *self, GdkEventExpose *event)
173 {
174         ELHomeAppletPrivate *priv = EL_HOME_APPLET(self)->priv;
175
176         cairo_t *cr;
177         GdkColor color;
178         float red, green, blue;
179
180         /* find theme active color */
181         gtk_style_lookup_color (self->style, "ActiveTextColor", &color);
182         red = color.red/(float)G_MAXUINT16;
183         green = color.green/(float)G_MAXUINT16;
184         blue = color.blue/(float)G_MAXUINT16;
185
186         cr = gdk_cairo_create (self->window);
187         gdk_cairo_region (cr, event->region);
188         cairo_clip (cr);
189
190         /* draw bound box */
191         cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
192
193         cairo_set_source_rgba (cr, 0.4f, 0.4f, 0.4f, 0.1f);
194         cairo_set_line_width (cr, 3.0f);
195
196         rounded_rectangle (cr,
197                            C_X,
198                            C_Y,
199                            BOX_WIDTH - 2*C_X,
200                            BOX_HEIGHT - 2*C_Y,
201                            BOX_RADIOUS);
202
203         cairo_close_path(cr);
204         cairo_stroke (cr);
205
206         /* draw header */
207         cairo_set_line_width (cr, 1.0f);
208
209         cairo_translate (cr, C_X, C_Y);
210         cairo_move_to (cr, 0, HEADER_HEIGHT);
211         cairo_line_to (cr, 0, BOX_RADIOUS);
212         cairo_curve_to (cr, 0, 0, 0, 0, BOX_RADIOUS, 0);
213         cairo_line_to (cr, C_WIDTH - BOX_RADIOUS, 0);
214         cairo_curve_to (cr, C_WIDTH, 0, C_WIDTH, 0, C_WIDTH, BOX_RADIOUS);
215         cairo_line_to (cr, C_WIDTH, HEADER_HEIGHT);
216         cairo_line_to (cr, 0, HEADER_HEIGHT);
217
218         cairo_close_path(cr);
219
220         cairo_set_source_rgba (cr, 0.2f, 0.2f, 0.2f, 0.8f);
221         cairo_fill_preserve (cr);
222         cairo_set_source_rgba (cr, red, green, blue, 1.0f);
223         cairo_stroke (cr);
224
225         /* draw body */
226         cairo_move_to (cr, 0, HEADER_HEIGHT);
227         cairo_line_to (cr, 0, C_HEIGHT - BOX_RADIOUS);
228         cairo_curve_to (cr, 0, C_HEIGHT, 0, C_HEIGHT, BOX_RADIOUS, C_HEIGHT);
229         cairo_line_to (cr, C_WIDTH - BOX_RADIOUS, C_HEIGHT);
230         cairo_curve_to (cr, C_WIDTH, C_HEIGHT, C_WIDTH, C_HEIGHT, C_WIDTH, C_HEIGHT - BOX_RADIOUS);
231         cairo_line_to (cr, C_WIDTH, HEADER_HEIGHT);
232         cairo_line_to (cr, 0, HEADER_HEIGHT);
233         cairo_close_path(cr);
234
235         /* draw body filling depending on (in)active state */
236         cairo_pattern_t *grad;
237         grad = cairo_pattern_create_linear(0, HEADER_HEIGHT,
238                                            0, C_HEIGHT);
239
240         if (priv->active){
241                 cairo_pattern_add_color_stop_rgba (grad, 0.5f,
242                                                    red, green, blue, 0.8f);
243                 cairo_pattern_add_color_stop_rgba (grad, 1.0f,
244                                                    red/2, green/2, blue/2, 0.8f);
245         }
246         else {
247                 cairo_pattern_add_color_stop_rgba (grad, 0.5f,
248                                                    0.4f, 0.4f, 0.4f, 0.8f);
249                 cairo_pattern_add_color_stop_rgba (grad, 1.0f,
250                                                    0.2f, 0.2f, 0.2f, 0.8f);
251         }
252         cairo_set_source (cr, grad);
253         cairo_fill (cr);
254
255         /* cairo_set_source_rgba (cr, red, green, blue, 1.0f); */
256         /* cairo_translate (cr, -C_X, -C_Y); */
257         /* rounded_rectangle (cr, */
258         /*                    C_X, */
259         /*                    C_Y, */
260         /*                    BOX_WIDTH - 2*C_X, */
261         /*                    BOX_HEIGHT - 2*C_Y, */
262         /*                    BOX_RADIOUS); */
263         /* cairo_close_path(cr); */
264         /* cairo_stroke (cr); */
265
266         /* draw message */
267         draw_text (cr, priv->message,
268                    2*C_X, HEADER_HEIGHT,
269                    MESSAGE_WIDTH,
270                    MESSAGE_HEIGHT - 2*C_Y);
271
272         cairo_pattern_destroy (grad);
273         cairo_destroy (cr);
274
275         return GTK_WIDGET_CLASS (el_home_applet_parent_class)->expose_event (self, event);
276 }
277
278 static void
279 dispose (GObject *self)
280 {
281         ELHomeAppletPrivate *priv = EL_HOME_APPLET(self)->priv;
282
283         if (priv->idle_id){
284                 g_source_remove (priv->idle_id);
285                 priv->idle_id = 0;
286         }
287         if (priv->eventlogger){
288                 g_object_unref (priv->eventlogger);
289                 priv->eventlogger = NULL;
290         }
291
292         if (priv->message){
293                 g_free (priv->message);
294                 priv->message = NULL;
295         }
296
297         G_OBJECT_CLASS (el_home_applet_parent_class)->dispose (self);
298 }
299
300 static void
301 finalize (GObject *self)
302 {
303         G_OBJECT_CLASS (el_home_applet_parent_class)->finalize (self);
304 }
305
306 static gchar*
307 format_time (time_t t)
308 {
309         static const guint RESULT_SIZE = 32;
310
311         time_t now;
312         struct tm now_tm, t_tm;
313         const gchar *format = "%Y.%m.%d %T";
314         gchar *result = g_malloc0 (RESULT_SIZE);
315
316         now = time (NULL);
317         localtime_r (&now, &now_tm);
318         localtime_r (&t, &t_tm);
319
320         if ((now_tm.tm_year == t_tm.tm_year) &&
321             (now_tm.tm_mon  == t_tm.tm_mon) &&
322             (now_tm.tm_mday == t_tm.tm_mday))
323                 format = "%T";
324
325         strftime (result, RESULT_SIZE, format, &t_tm);
326
327         return result;
328 }
329
330 static void
331 show_event (ELHomeApplet *self, RTComElIter *it)
332 {
333         ELHomeAppletPrivate *priv = self->priv;
334
335         gchar *remote = NULL;
336         gchar *received = NULL;
337         const gchar *icon_name = NULL;
338
339         if (priv->message) {
340                 g_free (priv->message);
341                 priv->message = NULL;
342         }
343
344         if (it && rtcom_el_iter_first (it)){
345                 rtcom_el_iter_dup_string (it, "free-text", &priv->message);
346                 if (priv->message){
347                         const gchar *service;
348                         time_t received_t;
349
350                         rtcom_el_iter_get_int (it, "id", &priv->event_id);
351                         if (rtcom_el_iter_get_int (it, "start-time", (gint*)&received_t))
352                                 received = format_time (received_t);
353
354                         if(!rtcom_el_iter_dup_string (it, "remote-name", &remote))
355                                 rtcom_el_iter_dup_string (it, "remote-id", &remote);
356                         service = rtcom_el_iter_get_service (it);
357                         if (!g_strcmp0 (service, "RTCOM_EL_SERVICE_SMS"))
358                                 icon_name = "chat_unread_sms";
359                         else if (!g_strcmp0 (service, "RTCOM_EL_SERVICE_CHAT"))
360                                 icon_name = "chat_unread_chat";
361                 }
362         }
363         else{
364                 priv->event_id = -1;
365         }
366
367         if (priv->message)
368                 gtk_widget_hide (priv->empty);
369         else
370                 gtk_widget_show (priv->empty);
371
372         gtk_label_set_text (GTK_LABEL (priv->sender), remote);
373         gtk_label_set_text (GTK_LABEL (priv->received), received);
374
375         if (icon_name){
376                 const gchar *current_icon_name;
377                 gtk_image_get_icon_name (GTK_IMAGE (priv->icon),
378                                          &current_icon_name,
379                                          NULL);
380                 if (g_strcmp0 (current_icon_name, icon_name))
381                         gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon),
382                                                       icon_name,
383                                                       HILDON_ICON_SIZE_FINGER);
384                 gtk_widget_show (priv->icon);
385         }
386         else
387                 gtk_widget_hide (priv->icon);
388
389         g_free (remote);
390
391         gtk_widget_queue_draw (GTK_WIDGET (self));
392 }
393
394 static RTComElIter*
395 make_query (RTComEl *el, gint event_id)
396 {
397         RTComElQuery *query = NULL;
398         RTComElIter *it = NULL;
399
400         static const gchar *services[] = {"RTCOM_EL_SERVICE_SMS",
401                                           "RTCOM_EL_SERVICE_CHAT",
402                                           NULL};
403         static const gchar *event_types[] = {"RTCOM_EL_EVENTTYPE_SMS_INBOUND",
404                                              "RTCOM_EL_EVENTTYPE_CHAT_INBOUND",
405                                              NULL};
406
407         query = rtcom_el_query_new (el);
408         rtcom_el_query_set_limit (query, 1);
409         if (event_id >= 0){
410                 rtcom_el_query_prepare (query,
411                                         "is-read", FALSE, RTCOM_EL_OP_EQUAL,
412                                         "id", event_id, RTCOM_EL_OP_EQUAL,
413                                         "service", services, RTCOM_EL_OP_IN_STRV,
414                                         "event-type", event_types, RTCOM_EL_OP_IN_STRV,
415                                         NULL);
416         }
417         else{
418                 rtcom_el_query_prepare (query,
419                                         "is-read", FALSE, RTCOM_EL_OP_EQUAL,
420                                         "service", services, RTCOM_EL_OP_IN_STRV,
421                                         "event-type", event_types, RTCOM_EL_OP_IN_STRV,
422                                         NULL);
423         }
424         it = rtcom_el_get_events (el, query);
425         g_object_unref(query);
426
427         return it;
428 }
429
430 static void
431 update_unread_label (ELHomeApplet *self)
432 {
433         ELHomeAppletPrivate *priv = self->priv;
434         gchar *text;
435
436         if (priv->unread_count > 0){
437                 text = g_strdup_printf ("%d", priv->unread_count);
438                 gtk_label_set_text (GTK_LABEL (priv->unread), text);
439                 g_free (text);
440         }
441         else
442                 gtk_label_set_text (GTK_LABEL (priv->unread), NULL);
443 }
444
445 static gint
446 query_unread_events (RTComEl *el)
447 {
448         sqlite3 *db;
449         sqlite3_stmt *stmt;
450         int ret;
451         gint count = 0;
452
453         g_object_get (el, "db", &db, NULL);
454
455         if (sqlite3_prepare_v2 (db,
456                                 "SELECT SUM(total_events)-SUM(read_events) FROM GroupCache;",
457                                 -1,
458                                 &stmt,
459                                 NULL) != SQLITE_OK){
460                 g_error ("%s: can't compile SQL", G_STRFUNC);
461                 return -1;
462         }
463
464         while (SQLITE_BUSY == (ret = sqlite3_step (stmt)));
465
466         if (ret == SQLITE_ROW){
467                 count = sqlite3_column_int (stmt, 0);
468         }
469         else{
470                 g_error ("%s: error while executing SQL", G_STRFUNC);
471         }
472
473         sqlite3_finalize (stmt);
474
475         return count;
476 }
477
478 static void
479 read_event (ELHomeApplet *self)
480 {
481         ELHomeAppletPrivate *priv = self->priv;
482         RTComElIter *it = NULL;
483
484         it = make_query (priv->eventlogger, -1);
485         show_event (self, it);
486         if (it) g_object_unref (it);
487 }
488
489 static void
490 mark_as_read (ELHomeApplet *self)
491 {
492         ELHomeAppletPrivate *priv = self->priv;
493
494         if (priv->event_id >= 0){
495                 rtcom_el_set_read_event (priv->eventlogger,
496                                          priv->event_id,
497                                          TRUE,
498                                          NULL);
499                 read_event (self);
500                 priv->unread_count--;
501                 update_unread_label (self);
502         }
503 }
504
505 static gboolean
506 read_new_event (ELHomeApplet *self)
507 {
508         ELHomeAppletPrivate *priv = self->priv;
509
510         read_event (self);
511         priv->unread_count = query_unread_events (priv->eventlogger);
512         update_unread_label (self);
513
514         priv->idle_id = 0;
515
516         return FALSE;
517 }
518
519 static void
520 add_new_idle (ELHomeApplet *self)
521 {
522         ELHomeAppletPrivate *priv = self->priv;
523
524         if (priv->idle_id)
525                 g_source_remove (priv->idle_id);
526         priv->idle_id = g_idle_add ((GSourceFunc)read_new_event,
527                                     self);
528 }
529
530 static void
531 new_event_cb (RTComEl      *backend,
532               gint          event_id,
533               const gchar  *local_uid,
534               const gchar  *remote_uid,
535               const gchar  *remote_ebook_uid,
536               const gchar  *group_uid,
537               const gchar  *service,
538               ELHomeApplet *self)
539 {
540         add_new_idle (self);
541 }
542
543 static gboolean
544 button_release_event_cb (GtkWidget      *widget,
545                          GdkEventButton *event,
546                          ELHomeApplet   *self)
547 {
548         ELHomeAppletPrivate *priv = self->priv;
549
550         if (priv->active){
551                 priv->active = FALSE;
552                 gtk_widget_queue_draw (widget);
553 #ifndef DEBUG_LAYOUT
554                 mark_as_read (self);
555 #endif
556         }
557
558         return TRUE;
559 }
560
561 static gboolean
562 button_press_event_cb (GtkWidget      *widget,
563                        GdkEventButton *event,
564                        ELHomeApplet   *self)
565 {
566         ELHomeAppletPrivate *priv = self->priv;
567
568         if (priv->event_id > 0){
569                 priv->active = TRUE;
570                 gtk_widget_queue_draw (widget);
571         }
572
573         return TRUE;
574 }
575
576 static gboolean
577 leave_notify_event_cb (GtkWidget        *widget,
578                        GdkEventCrossing *event,
579                        ELHomeApplet     *self)
580 {
581         ELHomeAppletPrivate *priv = self->priv;
582
583         if (priv->active){
584                 priv->active = FALSE;
585                 gtk_widget_queue_draw (widget);
586         }
587
588         return FALSE;
589 }
590
591 static void
592 el_home_applet_init (ELHomeApplet *self)
593 {
594         ELHomeAppletPrivate *priv;
595         GtkWidget *event_box;
596         GtkWidget *hbox, *vbox, *align;
597
598         self->priv = EL_HOME_APPLET_GET_PRIVATE (self);
599         priv = self->priv;
600
601         gtk_widget_set_app_paintable (GTK_WIDGET (self), TRUE);
602
603         priv->unread = gtk_label_new ("12");
604         hildon_helper_set_logical_color (priv->unread,
605                                          GTK_RC_FG,
606                                          GTK_STATE_NORMAL,
607                                          "ActiveTextColor");
608         gtk_misc_set_alignment (GTK_MISC (priv->unread),
609                                 1.0f,
610                                 0.5f);
611         gtk_widget_set_size_request (priv->unread,
612                                      -1,
613                                      HEADER_HEIGHT);
614
615         priv->icon = gtk_image_new_from_icon_name ("chat_unread_sms",
616                                                    HILDON_ICON_SIZE_FINGER);
617         gtk_misc_set_alignment (GTK_MISC (priv->icon),
618                                 0.5f,
619                                 0.5f);
620
621         priv->sender = gtk_label_new ("asdf asdf asdf asdf asdf");
622         gtk_misc_set_alignment (GTK_MISC (priv->sender),
623                                 0.5f,
624                                 0.5f);
625         gtk_label_set_ellipsize (GTK_LABEL (priv->sender),
626                                  PANGO_ELLIPSIZE_END);
627         gtk_widget_set_name (priv->sender, "hildon-shadow-label");
628         hildon_helper_set_logical_font (priv->sender, "SystemFont");
629
630         priv->message = g_strdup ("One two three four five six seven eight nine ten"
631                                   "one two three four five six seven eight nine ten"
632                                   "one two three four five six seven eight nine ten"
633                                   "one two three four five six seven eight nine ten"
634                                   "one two three four five six seven eight nine ten"
635                                   "one two three four five six seven eight nine ten");
636
637         /* TODO: l10n */
638         priv->empty = gtk_label_new ("No new messages");
639         gtk_widget_set_name (priv->empty, "hildon-shadow-label");
640         GTK_WIDGET_SET_FLAGS (priv->empty, GTK_NO_SHOW_ALL);
641
642         priv->received = gtk_label_new ("aewf aewf aewf awef");
643         gtk_misc_set_alignment (GTK_MISC (priv->received),
644                                 1.0f,
645                                 0.5f);
646         gtk_widget_set_size_request (priv->received,
647                                      MESSAGE_WIDTH,
648                                      -1);
649         hildon_helper_set_logical_font (priv->received, "SmallSystemFont");
650         gtk_widget_set_name (priv->received, "hildon-shadow-label");
651
652         hbox = gtk_hbox_new (FALSE, 0);
653         gtk_box_pack_start (GTK_BOX (hbox), priv->unread, FALSE, FALSE, 0);
654         gtk_box_pack_start (GTK_BOX (hbox), priv->icon, FALSE, FALSE, 0);
655         gtk_box_pack_start (GTK_BOX (hbox), priv->sender, TRUE, TRUE, 0);
656
657         vbox = gtk_vbox_new (FALSE, 0);
658         gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
659         gtk_box_pack_start (GTK_BOX (vbox), priv->empty, TRUE, TRUE, 0);
660         gtk_box_pack_end (GTK_BOX (vbox), priv->received, FALSE, FALSE, 0);
661
662         align = gtk_alignment_new (0.5f, 0.0f, 1.0f, 1.0f);
663         gtk_alignment_set_padding (GTK_ALIGNMENT (align),
664                                    0, 0, HILDON_MARGIN_DEFAULT, HILDON_MARGIN_DEFAULT);
665
666         gtk_container_set_border_width (GTK_CONTAINER (vbox), HILDON_MARGIN_HALF);
667
668         event_box = gtk_event_box_new ();
669         gtk_event_box_set_visible_window (GTK_EVENT_BOX (event_box), FALSE);
670         gtk_widget_set_size_request (event_box, BOX_WIDTH, BOX_HEIGHT);
671
672         gtk_container_add (GTK_CONTAINER (align), vbox);
673         gtk_container_add (GTK_CONTAINER (event_box), align);
674         gtk_container_add (GTK_CONTAINER (self), event_box);
675
676         g_signal_connect (event_box, "button-press-event",
677                 G_CALLBACK (button_press_event_cb), self);
678         g_signal_connect (event_box, "button-release-event",
679                 G_CALLBACK (button_release_event_cb), self);
680         g_signal_connect (event_box, "leave-notify-event",
681                 G_CALLBACK (leave_notify_event_cb), self);
682
683         gtk_widget_show_all (GTK_WIDGET (event_box));
684
685 #ifndef DEBUG_LAYOUT
686         priv->eventlogger = rtcom_el_new ();
687         g_signal_connect (priv->eventlogger,
688                           "new-event",
689                           G_CALLBACK (new_event_cb),
690                           self);
691         g_signal_connect (priv->eventlogger,
692                           "event-updated",
693                           G_CALLBACK (new_event_cb),
694                           self);
695
696         read_new_event (self);
697 #endif
698 }
699
700 static void
701 el_home_applet_class_init (ELHomeAppletClass *klass)
702 {
703         GObjectClass *object_class = G_OBJECT_CLASS (klass);
704         GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
705
706         object_class->dispose = dispose;
707         object_class->finalize = finalize;
708         widget_class->expose_event = expose_event;
709         widget_class->realize = el_home_applet_realize;
710
711         g_type_class_add_private (klass, sizeof (ELHomeAppletPrivate));
712 }
713