7387cc956ae67df8736d0272233ad34f690bcf6b
[framework/uifw/e17.git] / src / modules / clock / e_mod_main.c
1 #include "e.h"
2 #include "e_mod_main.h"
3
4 #include <sys/time.h>
5 #include <time.h>
6
7 /* gadcon requirements */
8 static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style);
9 static void _gc_shutdown(E_Gadcon_Client *gcc);
10 static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient);
11 static char *_gc_label(E_Gadcon_Client_Class *client_class);
12 static Evas_Object *_gc_icon(E_Gadcon_Client_Class *client_class, Evas *evas);
13 static const char *_gc_id_new(E_Gadcon_Client_Class *client_class);
14
15 /* and actually define the gadcon class that this module provides (just 1) */
16 static const E_Gadcon_Client_Class _gadcon_class =
17 {
18    GADCON_CLIENT_CLASS_VERSION,
19      "clock",
20      {
21         _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL
22      },
23    E_GADCON_CLIENT_STYLE_PLAIN
24 };
25
26 /* actual module specifics */
27 typedef struct _Instance Instance;
28
29 struct _Instance
30 {
31    E_Gadcon_Client *gcc;
32    Evas_Object     *o_clock, *o_table, *o_popclock, *o_cal;
33    E_Gadcon_Popup  *popup;
34    E_Menu          *menu;
35    
36    int madj;
37    
38    char year[8];
39    char month[32];
40    const char *daynames[7];
41    unsigned char daynums[7][6];
42    Eina_Bool dayweekends[7][6];
43    Eina_Bool dayvalids[7][6];
44    Eina_Bool daytoday[7][6];
45 };
46
47 E_Module *clock_module = NULL;
48 E_Config_Dialog *clock_config = NULL;
49 Config *clock_cfg = NULL;
50
51 static E_Config_DD *clock_cfg_edd = NULL;
52 static Eina_List *clock_instances = NULL;
53 static E_Action *act = NULL;
54
55 static void
56 _clear_timestrs(Instance *inst)
57 {
58    int x;
59    
60    for (x = 0; x < 7; x++)
61      {
62         if (inst->daynames[x])
63           {
64              eina_stringshare_del(inst->daynames[x]);
65              inst->daynames[x] = NULL;
66           }
67      }
68 }
69
70 static void
71 _time_eval(Instance *inst)
72 {
73    struct timeval      timev;
74    struct tm          *tm, tms, tmm, tm2;
75    time_t              tt;
76    int                 started = 0, num, i;
77    
78    tzset();
79    gettimeofday(&timev, NULL);
80    tt = (time_t)(timev.tv_sec);
81    tm = localtime(&tt);
82    
83    _clear_timestrs(inst);
84    if (tm)
85      {
86         int day;
87         
88         // tms == current date time "saved"
89         // tm2 == date to look at adjusting for madj
90         // tm2 == month baseline @ 1st
91         memcpy(&tms, tm, sizeof(struct tm));
92         num = 0;
93         for (day = (0 - 6); day < (31 + 16); day++)
94           {
95              memcpy(&tmm, &tms, sizeof(struct tm));
96              tmm.tm_sec = 0;
97              tmm.tm_min = 0;
98              tmm.tm_hour = 10;
99              tmm.tm_mon += inst->madj;
100              tmm.tm_mday = 1; // start at the 1st of the month
101              tmm.tm_wday = 0; // ignored by mktime
102              tmm.tm_yday = 0; // ignored by mktime
103              tmm.tm_isdst = 0; // ignored by mktime
104              tt = mktime(&tmm);
105              tm = localtime(&tt);
106              memcpy(&tm2, tm, sizeof(struct tm));
107              
108              tt = mktime(&tmm);
109              tt += (day * 60 * 60 * 24);
110              tm = localtime(&tt);
111              memcpy(&tmm, tm, sizeof(struct tm));
112              if (!started)
113                {
114                   if (tm->tm_wday == clock_cfg->week.start) started = 1;
115                }
116              if (started)
117                {
118                   int y = num / 7;
119                   int x = num % 7;
120                   
121                   if (y < 6)
122                     {
123                        inst->daynums[x][y] = tmm.tm_mday;
124                        
125                        inst->dayvalids[x][y] = 0;
126                        if (tmm.tm_mon == tm2.tm_mon) inst->dayvalids[x][y] = 1;
127                        
128                        inst->daytoday[x][y] = 0;
129                        if ((tmm.tm_mon == tms.tm_mon) &&
130                            (tmm.tm_year == tms.tm_year) &&
131                            (tmm.tm_mday == tms.tm_mday))
132                           inst->daytoday[x][y] = 1;
133                        
134                        inst->dayweekends[x][y] = 0;
135                        for (i = clock_cfg->weekend.start; 
136                             i < (clock_cfg->weekend.start + clock_cfg->weekend.len);
137                             i++)
138                          {
139                             if (tmm.tm_wday == (i % 7))
140                               {
141                                  inst->dayweekends[x][y] = 1;
142                                  break;
143                               }
144                          }
145                        if (!inst->daynames[x])
146                          {
147                             char buf[32];
148                             
149                             buf[sizeof(buf) - 1] = 0;
150                             strftime(buf, sizeof(buf) - 1, "%a", (const struct tm *)&tmm); // %A full weekeday
151                             inst->daynames[x] = eina_stringshare_add(buf);
152                          }
153                     }
154                   num++;
155                }
156           }
157         
158         memcpy(&tmm, &tms, sizeof(struct tm));
159         tmm.tm_sec = 0;
160         tmm.tm_min = 0;
161         tmm.tm_hour = 10;
162         tmm.tm_mon += inst->madj;
163         tmm.tm_mday = 1; // start at the 1st of the month
164         tmm.tm_wday = 0; // ignored by mktime
165         tmm.tm_yday = 0; // ignored by mktime
166         tmm.tm_isdst = 0; // ignored by mktime
167         tt = mktime(&tmm);
168         tm = localtime(&tt);
169         memcpy(&tm2, tm, sizeof(struct tm));
170         inst->year[sizeof(inst->year) - 1] = 0;
171         strftime(inst->year, sizeof(inst->year) - 1, "%Y", (const struct tm *)&tm2);
172         inst->month[sizeof(inst->month) - 1] = 0;
173         strftime(inst->month, sizeof(inst->month) - 1, "%B", (const struct tm *)&tm2); // %b for short month
174      }
175 }
176
177 static void
178 _clock_month_update(Instance *inst)
179 {
180    Evas_Object *od, *oi;
181    int x, y;
182
183    oi = inst->o_cal;
184    edje_object_part_text_set(oi, "e.text.month", inst->month);
185    edje_object_part_text_set(oi, "e.text.year", inst->year);
186    for (x = 0; x < 7; x++)
187      {
188         od = edje_object_part_table_child_get(oi, "e.table.daynames", x, 0);
189         edje_object_part_text_set(od, "e.text.label", inst->daynames[x]);
190      }
191    
192    for (y = 0; y < 6; y++)
193      {
194         for (x = 0; x < 7; x++)
195           {
196              char buf[32];
197              
198              od = edje_object_part_table_child_get(oi, "e.table.days", x, y);
199              snprintf(buf, sizeof(buf), "%i", (int)inst->daynums[x][y]);
200              edje_object_part_text_set(od, "e.text.label", buf);
201              if (inst->dayweekends[x][y])
202                 edje_object_signal_emit(od, "e,state,weekend", "e");
203              else
204                 edje_object_signal_emit(od, "e,state,weekday", "e");
205              if (inst->dayvalids[x][y])
206                 edje_object_signal_emit(od, "e,state,visible", "e");
207              else
208                 edje_object_signal_emit(od, "e,state,hidden", "e");
209              if (inst->daytoday[x][y])
210                 edje_object_signal_emit(od, "e,state,today", "e");
211              else
212                 edje_object_signal_emit(od, "e,state,someday", "e");
213           }
214      }
215 }
216
217 static void
218 _clock_month_prev_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
219 {
220    Instance *inst = data;
221    inst->madj--;
222    _time_eval(inst);
223    _clock_month_update(inst);
224 }
225
226 static void
227 _clock_month_next_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
228 {
229    Instance *inst = data;
230    inst->madj++;
231    _time_eval(inst);
232    _clock_month_update(inst);
233 }
234
235 static void
236 _clock_settings_cb(void *d1, void *d2 __UNUSED__)
237 {
238    Instance *inst = d1;
239    e_int_config_clock_module(inst->popup->win->zone->container, NULL);
240    e_object_del(E_OBJECT(inst->popup));
241    inst->popup = NULL;
242 }
243    
244 static void
245 _clock_popup_new(Instance *inst)
246 {
247    Evas *evas;
248    Evas_Object *o, *oi;
249    Evas_Coord mw = 128, mh = 128;
250    
251    if (inst->popup) return;
252
253    inst->madj = 0;
254    
255    _time_eval(inst);
256    
257    inst->popup = e_gadcon_popup_new(inst->gcc);
258    evas = inst->popup->win->evas;
259    
260    inst->o_table = e_widget_table_add(evas, 0);
261
262    oi = edje_object_add(evas);
263    inst->o_popclock = oi;
264    if (clock_cfg->digital_clock)
265       e_theme_edje_object_set(oi, "base/theme/modules/clock",
266                               "e/modules/clock/digital");
267    else
268       e_theme_edje_object_set(oi, "base/theme/modules/clock",
269                               "e/modules/clock/main");
270    if (clock_cfg->digital_24h)
271       edje_object_signal_emit(oi, "e,state,24h,on", "e");
272    else
273       edje_object_signal_emit(oi, "e,state,24h,off", "e");
274    if (clock_cfg->show_seconds)
275       edje_object_signal_emit(oi, "e,state,seconds,on", "e");
276    else
277       edje_object_signal_emit(oi, "e,state,seconds,off", "e");
278    o = e_widget_image_add_from_object(evas, oi, 128, 128);
279    evas_object_show(oi);
280    e_widget_table_object_align_append(inst->o_table, o, 
281                                       0, 0, 1, 1, 0, 0, 0, 0, 0.5, 0.5);
282
283    o = e_widget_button_add(evas, _("Settings"), "preferences-system",
284                            _clock_settings_cb, inst, NULL);
285    e_widget_table_object_align_append(inst->o_table, o, 
286                                       0, 1, 1, 1, 0, 0, 0, 0, 0.5, 1.0);
287    
288    oi = edje_object_add(evas);
289    inst->o_cal = oi;
290    e_theme_edje_object_set(oi, "base/theme/modules/clock",
291                            "e/modules/clock/calendar");
292    _clock_month_update(inst);
293    
294    edje_object_signal_callback_add(oi, "e,action,prev", "*", 
295                                    _clock_month_prev_cb, inst);
296    edje_object_signal_callback_add(oi, "e,action,next", "*", 
297                                    _clock_month_next_cb, inst);
298    evas_object_resize(oi, 500, 500);
299    edje_object_size_min_restricted_calc(oi, &mw, &mh, 128, 128);
300    
301    o = e_widget_image_add_from_object(evas, oi, mw, mh);
302    evas_object_show(oi);
303    e_widget_table_object_align_append(inst->o_table, o, 
304                                       1, 0, 1, 2, 0, 0, 0, 0, 0.5, 0.5);
305    
306    e_gadcon_popup_content_set(inst->popup, inst->o_table);
307    e_gadcon_popup_show(inst->popup);
308 }
309
310 void
311 e_int_clock_instances_redo(void)
312 {
313    Eina_List *l;
314    Instance *inst;
315    
316    EINA_LIST_FOREACH(clock_instances, l, inst)
317      {
318         Evas_Object *o = inst->o_clock;
319         Evas_Coord mw, mh;
320
321         if (clock_cfg->digital_clock)
322            e_theme_edje_object_set(o, "base/theme/modules/clock",
323                                    "e/modules/clock/digital");
324         else
325            e_theme_edje_object_set(o, "base/theme/modules/clock",
326                                    "e/modules/clock/main");
327         if (clock_cfg->digital_24h)
328            edje_object_signal_emit(o, "e,state,24h,on", "e");
329         else
330            edje_object_signal_emit(o, "e,state,24h,off", "e");
331         if (clock_cfg->show_seconds)
332            edje_object_signal_emit(o, "e,state,seconds,on", "e");
333         else
334            edje_object_signal_emit(o, "e,state,seconds,off", "e");
335         edje_object_message_signal_process(o);
336         mw = 0, mh = 0;
337         edje_object_size_min_get(o, &mw, &mh);
338         if ((mw < 1) || (mh < 1))
339            edje_object_size_min_calc(o, &mw, &mh);
340         if (mw < 4) mw = 4;
341         if (mh < 4) mh = 4;
342         e_gadcon_client_aspect_set(inst->gcc, mw, mh);
343         e_gadcon_client_min_size_set(inst->gcc, mw, mh);
344      }
345 }
346
347 static void
348 _clock_popup_free(Instance *inst)
349 {
350    if (!inst->popup) return;
351    if (inst->popup) e_object_del(E_OBJECT(inst->popup));
352    inst->popup = NULL;
353 }
354
355 static void
356 _clock_menu_cb_post(void *data, E_Menu *menu __UNUSED__)
357 {
358    Instance *inst = data;
359    if ((!inst) || (!inst->menu))
360       return;
361    if (inst->menu)
362      {
363         e_object_del(E_OBJECT(inst->menu));
364         inst->menu = NULL;
365      }
366 }
367
368 static void
369 _clock_menu_cb_cfg(void *data, E_Menu *menu __UNUSED__, E_Menu_Item *mi __UNUSED__)
370 {
371    Instance *inst = data;
372    E_Container *con;
373    
374    if (inst->popup)
375      {
376         e_object_del(E_OBJECT(inst->popup));
377         inst->popup = NULL;
378      }
379    con = e_container_current_get(e_manager_current_get());
380    e_int_config_clock_module(con, NULL);
381 }
382
383 static void
384 _clock_cb_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event)
385 {
386    Instance *inst = data;
387    Evas_Event_Mouse_Down *ev = event;
388    
389    if (ev->button == 1)
390      {
391         if (inst->popup) _clock_popup_free(inst);
392         else _clock_popup_new(inst);
393      }
394    else if ((ev->button == 3) && (!inst->menu))
395      {
396         E_Zone *zone;
397         E_Menu *m;
398         E_Menu_Item *mi;
399         int x, y;
400         
401         zone = e_util_zone_current_get(e_manager_current_get());
402         
403         m = e_menu_new();
404         
405         mi = e_menu_item_new(m);
406         e_menu_item_label_set(mi, _("Settings"));
407         e_util_menu_item_theme_icon_set(mi, "configure");
408         e_menu_item_callback_set(mi, _clock_menu_cb_cfg, inst);
409         
410         m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
411         e_menu_post_deactivate_callback_set(m, _clock_menu_cb_post, inst);
412         inst->menu = m;
413         
414         e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
415         e_menu_activate_mouse(m, zone, x + ev->output.x, y + ev->output.y,
416                               1, 1, E_MENU_POP_DIRECTION_AUTO, ev->timestamp);
417         evas_event_feed_mouse_up(inst->gcc->gadcon->evas, ev->button,
418                                  EVAS_BUTTON_NONE, ev->timestamp, NULL);
419      }
420 }
421 static void
422 _clock_sizing_changed_cb(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
423 {
424    Instance *inst = data;
425    Evas_Coord mw, mh;
426    
427    mw = 0, mh = 0;
428    edje_object_size_min_get(inst->o_clock, &mw, &mh);
429    if ((mw < 1) || (mh < 1))
430      edje_object_size_min_calc(inst->o_clock, &mw, &mh);
431    if (mw < 4) mw = 4;
432    if (mh < 4) mh = 4;
433    e_gadcon_client_aspect_set(inst->gcc, mw, mh);
434    e_gadcon_client_min_size_set(inst->gcc, mw, mh);
435 }
436
437 static E_Gadcon_Client *
438 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
439 {
440    Evas_Object *o;
441    E_Gadcon_Client *gcc;
442    Instance *inst;
443    
444    inst = E_NEW(Instance, 1);
445    
446    o = edje_object_add(gc->evas);
447    edje_object_signal_callback_add(o, "e,state,sizing,changed", "*", 
448                                    _clock_sizing_changed_cb, inst);
449    if (clock_cfg->digital_clock)
450       e_theme_edje_object_set(o, "base/theme/modules/clock",
451                               "e/modules/clock/digital");
452    else
453       e_theme_edje_object_set(o, "base/theme/modules/clock",
454                               "e/modules/clock/main");
455    if (clock_cfg->digital_24h)
456       edje_object_signal_emit(o, "e,state,24h,on", "e");
457    else
458       edje_object_signal_emit(o, "e,state,24h,off", "e");
459    if (clock_cfg->show_seconds)
460       edje_object_signal_emit(o, "e,state,seconds,on", "e");
461    else
462       edje_object_signal_emit(o, "e,state,seconds,off", "e");
463    evas_object_show(o);
464    
465    gcc = e_gadcon_client_new(gc, name, id, style, o);
466    gcc->data = inst;
467    
468    inst->gcc = gcc;
469    inst->o_clock = o;
470    
471    evas_object_event_callback_add(inst->o_clock, 
472                                   EVAS_CALLBACK_MOUSE_DOWN,
473                                   _clock_cb_mouse_down,
474                                   inst);
475    
476    e_gadcon_client_util_menu_attach(gcc);
477
478    clock_instances = eina_list_append(clock_instances, inst);
479    return gcc;
480 }
481
482 static void
483 _gc_shutdown(E_Gadcon_Client *gcc)
484 {
485    Instance *inst;
486    
487    inst = gcc->data;
488    if (inst->menu)
489      {
490         e_object_del(E_OBJECT(inst->menu));
491         inst->menu = NULL;
492      }
493    clock_instances = eina_list_remove(clock_instances, inst);
494    evas_object_del(inst->o_clock);
495    _clock_popup_free(inst);
496    _clear_timestrs(inst);
497    free(inst);
498 }
499
500 static void
501 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient __UNUSED__)
502 {
503    Instance *inst;
504    Evas_Coord mw, mh;
505    
506    inst = gcc->data;
507    mw = 0, mh = 0;
508    edje_object_size_min_get(inst->o_clock, &mw, &mh);
509    if ((mw < 1) || (mh < 1))
510      edje_object_size_min_calc(inst->o_clock, &mw, &mh);
511    if (mw < 4) mw = 4;
512    if (mh < 4) mh = 4;
513    e_gadcon_client_aspect_set(gcc, mw, mh);
514    e_gadcon_client_min_size_set(gcc, mw, mh);
515 }
516
517 static char *
518 _gc_label(E_Gadcon_Client_Class *client_class __UNUSED__)
519 {
520    return _("Clock");
521 }
522
523 static Evas_Object *
524 _gc_icon(E_Gadcon_Client_Class *client_class __UNUSED__, Evas *evas)
525 {
526    Evas_Object *o;
527    char buf[4096];
528    
529    o = edje_object_add(evas);
530    snprintf(buf, sizeof(buf), "%s/e-module-clock.edj",
531             e_module_dir_get(clock_module));
532    edje_object_file_set(o, buf, "icon");
533    return o;
534 }
535
536 static const char *
537 _gc_id_new(E_Gadcon_Client_Class *client_class __UNUSED__)
538 {
539    return _gadcon_class.name;
540 }
541
542 static void
543 _e_mod_action(const char *params)
544 {
545    Eina_List *l;
546    Instance *inst;
547
548    if (!params) return ;
549    if (strcmp(params, "show_calendar")) return ;
550
551    EINA_LIST_FOREACH(clock_instances, l, inst)
552      if (inst->popup)
553        _clock_popup_free(inst);
554      else
555        _clock_popup_new(inst);
556 }
557
558 static void
559 _e_mod_action_cb_edge(E_Object *obj,
560                       const char *params,
561                       E_Event_Zone_Edge *ev)
562 {
563    _e_mod_action(params);
564 }
565
566 static void
567 _e_mod_action_cb(E_Object *obj, const char *params)
568 {
569    _e_mod_action(params);
570 }
571
572 static void
573 _e_mod_action_cb_key(E_Object *obj,
574                      const char *params,
575                      Ecore_Event_Key *ev)
576 {
577    _e_mod_action(params);
578 }
579
580 static void
581 _e_mod_action_cb_mouse(E_Object *obj,
582                        const char *params,
583                        Ecore_Event_Mouse_Button *ev)
584 {
585    _e_mod_action(params);
586 }
587
588 /* module setup */
589 EAPI E_Module_Api e_modapi =
590 {
591    E_MODULE_API_VERSION,
592      "Clock"
593 };
594
595 EAPI void *
596 e_modapi_init(E_Module *m)
597 {
598    clock_cfg_edd = E_CONFIG_DD_NEW("Config", Config);
599 #undef T
600 #undef D
601 #define T Config
602 #define D clock_cfg_edd
603    E_CONFIG_VAL(D, T, weekend.start, INT);
604    E_CONFIG_VAL(D, T, weekend.len, INT);
605    E_CONFIG_VAL(D, T, week.start, INT);
606    E_CONFIG_VAL(D, T, digital_clock, INT);
607    E_CONFIG_VAL(D, T, digital_24h, INT);
608    E_CONFIG_VAL(D, T, show_seconds, INT);
609
610    clock_cfg = e_config_domain_load("module.clock", clock_cfg_edd);
611    if (!clock_cfg)
612      {
613         clock_cfg = E_NEW(Config, 1);
614         clock_cfg->weekend.start = 6;
615         clock_cfg->weekend.len = 2;
616         clock_cfg->week.start = 1;
617         clock_cfg->digital_clock = 0;
618         clock_cfg->digital_24h = 0;
619         clock_cfg->show_seconds = 1;
620         e_config_save_queue();
621      }
622
623    act = e_action_add("clock");
624    if (act)
625      {
626        act->func.go = _e_mod_action_cb;
627        act->func.go_key = _e_mod_action_cb_key;
628        act->func.go_mouse = _e_mod_action_cb_mouse;
629        act->func.go_edge = _e_mod_action_cb_edge;
630
631        e_action_predef_name_set(_("Clock"), _("Show calendar"), "clock", "show_calendar", NULL, 0);
632      }
633
634    clock_module = m;
635    e_gadcon_provider_register(&_gadcon_class);
636    return m;
637 }
638
639 EAPI int
640 e_modapi_shutdown(E_Module *m __UNUSED__)
641 {
642    if (clock_config)
643      {
644         e_object_del(E_OBJECT(clock_config));
645         clock_config = NULL;
646      }
647    if (clock_cfg)
648      {
649         free(clock_cfg);
650         clock_cfg = NULL;
651      }
652    E_CONFIG_DD_FREE(clock_cfg_edd);
653    clock_cfg_edd = NULL;
654    clock_module = NULL;
655    e_gadcon_provider_unregister(&_gadcon_class);
656    return 1;
657 }
658
659 EAPI int
660 e_modapi_save(E_Module *m __UNUSED__)
661 {
662    e_config_domain_save("module.clock", clock_cfg_edd, clock_cfg);
663    return 1;
664 }