[*]Un-Rollback to 'Merge [elm_multibuttonentry]Changed edc TEXT part to TEXTBLOCK...
[framework/uifw/elementary.git] / src / lib / elm_tickernoti.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup TickerNoti TickerNoti
6  * @ingroup Elementary
7  *
8  * This is a notification widget which can be used to display some short information.
9  */
10
11 typedef struct _Widget_Data Widget_Data;
12
13 struct _Widget_Data
14 {
15    Evas_Object *win;
16    Evas_Object *edje_obj;
17    Evas_Object *icon;
18    Evas_Object *button;
19
20    const char *label;
21
22    int noti_height;
23    int angle;
24
25    Elm_Tickernoti_Mode mode;
26    Elm_Tickernoti_Orient orient;
27 };
28
29 static const char *widtype = NULL;
30 static void _del_hook(Evas_Object *obj);
31 static void _theme_hook(Evas_Object *obj);
32 static void _sizing_eval(Evas_Object *obj);
33
34 static const char SIG_CLICKED[] = "clicked";
35 static const char SIG_HIDDEN[] = "hide";
36 static const Evas_Smart_Cb_Description _signals[] = {
37        {SIG_CLICKED, ""},
38        {SIG_HIDDEN, ""},
39        {NULL, NULL}
40 };
41 static void
42 _del_job(void *data)
43 {
44    evas_object_del(data);
45 }
46
47 static void
48 _del_hook(Evas_Object *obj)
49 {
50    Evas_Object *p;
51    Widget_Data *wd = elm_widget_data_get(obj);
52
53    if (!wd) return;
54
55    p = elm_widget_parent_get(obj);
56    if (wd->win) ecore_job_add (_del_job, p);
57
58    evas_object_del (wd->edje_obj);
59    wd->edje_obj = NULL;
60
61    free(wd);
62 }
63
64 static void
65 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
66 {
67    Widget_Data *wd = elm_widget_data_get(obj);
68
69    if (!wd) return;
70    edje_object_mirrored_set(wd->edje_obj, rtl);
71 }
72
73 static void
74 _theme_hook(Evas_Object *obj)
75 {
76    char *data_win_height = NULL;
77    Evas_Coord w;
78    Widget_Data *wd = elm_widget_data_get(obj);
79
80    if (!wd) return;
81    _elm_widget_mirrored_reload(obj);
82    _mirrored_set(obj, elm_widget_mirrored_get(obj));
83
84    _elm_theme_object_set (wd->win, wd->edje_obj, "tickernoti",
85                           "base", elm_widget_style_get(obj));
86
87    edje_object_scale_set (wd->edje_obj, elm_widget_scale_get(obj) * _elm_config->scale);
88
89    /* tickernoti detail height set */
90    data_win_height = (char *)edje_object_data_get (wd->edje_obj, "height");
91    if (data_win_height != NULL && elm_scale_get() > 0.0)
92      wd->noti_height = (int)(elm_scale_get() * atoi(data_win_height));
93
94    evas_object_geometry_get(wd->win, NULL, NULL, &w, NULL);
95    evas_object_resize (wd->win, w, wd->noti_height);
96
97    if (wd->label)
98      edje_object_part_text_set(wd->edje_obj, "elm.text", wd->label);
99    if (wd->icon)
100      edje_object_part_swallow (wd->edje_obj, "icon", wd->icon);
101    if (wd->button)
102       edje_object_part_swallow (wd->edje_obj, "button", wd->button);
103    edje_object_signal_emit (wd->edje_obj, "effect,show", "elm");
104    edje_object_message_signal_process(wd->edje_obj);
105
106    _sizing_eval(obj);
107 }
108
109 static void
110 _sizing_eval(Evas_Object *obj)
111 {
112    Widget_Data *wd = elm_widget_data_get(obj);
113    Evas_Coord minw = -1, minh = -1;
114
115    if (!wd) return;
116    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
117    edje_object_size_min_restricted_calc(wd->edje_obj, &minw, &minh, minw, minh);
118    evas_object_size_hint_min_set(obj, minw, minh);
119 }
120
121 #ifdef HAVE_ELEMENTARY_X
122 static void
123 _update_window_hints (Evas_Object *obj)
124 {
125    Ecore_X_Window xwin;
126    Ecore_X_Atom _notification_level_atom;
127    int level;
128 /* elm_win_xwindow_get() must call after elm_win_alpha_set() */
129    xwin = elm_win_xwindow_get (obj);
130
131    ecore_x_icccm_hints_set(xwin, 0, ECORE_X_WINDOW_STATE_HINT_NONE, 0, 0, 0, 0, 0);
132    ecore_x_netwm_window_type_set (xwin, ECORE_X_WINDOW_TYPE_NOTIFICATION);
133    ecore_x_netwm_opacity_set(xwin, 0);
134    /* Create atom for notification level */
135    _notification_level_atom = ecore_x_atom_get ("_E_ILLUME_NOTIFICATION_LEVEL");
136
137    /* HIGH:150, NORMAL:100, LOW:50 */
138    level = 100;
139
140    /* Set notification level of the window */
141    ecore_x_window_prop_property_set (xwin, _notification_level_atom, ECORE_X_ATOM_CARDINAL, 32, &level, 1);
142 }
143 #endif
144
145 static void _hide_cb (void *data, Evas_Object *obj __UNUSED__,
146                              const char *emission __UNUSED__,
147                              const char *source __UNUSED__)
148 {
149    Widget_Data *wd = elm_widget_data_get(data);
150
151    if (!wd) return;
152    evas_object_hide (wd->win);
153    evas_object_smart_callback_call (data, SIG_HIDDEN, NULL);
154 }
155
156 static void _clicked_cb (void *data, Evas_Object *obj __UNUSED__,
157                              const char *emission __UNUSED__,
158                              const char *source __UNUSED__)
159 {
160    Widget_Data *wd = elm_widget_data_get(data);
161
162    if (!wd) return;
163    evas_object_smart_callback_call (data, SIG_CLICKED, NULL);
164 }
165
166 static Evas_Object
167 *_create_window (Evas_Object *parent, const char *name)
168 {
169    Evas_Object *win;
170
171    win = elm_win_add (parent, name, ELM_WIN_BASIC);
172    elm_win_title_set (win, name);
173    elm_win_borderless_set (win, EINA_TRUE);
174    elm_win_autodel_set (win, EINA_TRUE);
175    elm_win_alpha_set(win, EINA_TRUE);
176
177 #ifdef HAVE_ELEMENTARY_X
178 /* set top window */
179    _update_window_hints (win);
180 #endif
181    return win;
182 }
183
184 static void
185 _create_tickernoti (Evas_Object *obj)
186 {
187 #ifdef HAVE_ELEMENTARY_X
188    Evas_Coord w;
189 #endif
190    Widget_Data *wd = elm_widget_data_get(obj);
191    char *data_win_height = NULL;
192    Evas *e;
193
194    if (!wd) return;
195
196    evas_object_move (wd->win, 0, 0);
197    e = evas_object_evas_get (wd->win);
198
199    wd->edje_obj = edje_object_add (e);
200    _elm_theme_object_set (wd->win, wd->edje_obj, "tickernoti", "base", "default");
201    elm_win_resize_object_add (wd->win, wd->edje_obj);
202
203    /* tickernoti detail height set */
204    data_win_height = (char *)edje_object_data_get (wd->edje_obj, "height");
205    if (data_win_height != NULL && elm_scale_get() > 0.0)
206      wd->noti_height = (int)(elm_scale_get() * atoi(data_win_height));
207
208 #ifdef HAVE_ELEMENTARY_X
209    ecore_x_window_size_get (ecore_x_window_root_first_get(), &w, NULL);
210    evas_object_resize (wd->win, w, wd->noti_height);
211 #endif
212
213    edje_object_signal_callback_add(wd->edje_obj, "request,hide", "", _hide_cb, obj);
214    edje_object_signal_callback_add(wd->edje_obj, "clicked", "", _clicked_cb, obj);
215    evas_object_show (wd->edje_obj);
216 }
217
218 static void
219 _disable_hook(Evas_Object *obj)
220 {
221    Widget_Data *wd = elm_widget_data_get(obj);
222
223    if (!wd) return;
224 //TODO:
225 }
226
227 static void
228 _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
229       void *event_info __UNUSED__)
230 {
231    Widget_Data *wd = elm_widget_data_get(obj);
232    if (!wd) return;
233
234 #ifdef HAVE_ELEMENTARY_X
235    _update_window_hints (wd->win);
236 #endif
237    evas_object_show (wd->win);
238    edje_object_signal_emit (wd->edje_obj, "effect,show", "elm");
239    edje_object_message_signal_process(wd->edje_obj);
240 }
241
242 static void
243 _hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
244       void *event_info __UNUSED__)
245 {
246    Widget_Data *wd = elm_widget_data_get(obj);
247
248    if (!wd) return;
249    evas_object_hide (obj);
250    evas_object_hide (wd->win);
251 }
252
253 static void _tickernoti_hide_cb (void *data, Evas_Object *obj __UNUSED__,
254                                  void *event_info __UNUSED__)
255 {
256    Widget_Data *wd = data;
257
258    if (!wd) return;
259
260    edje_object_signal_emit (wd->edje_obj, "effect,hide", "elm");
261    edje_object_message_signal_process(wd->edje_obj);
262 }
263
264 /**
265  * Add a tickernoti object to @p parent
266  *
267  * @param parent The parent object
268  *
269  * @return The tickernoti object, or NULL upon failure
270  *
271  * @ingroup TickerNoti
272  */
273 EAPI Evas_Object *
274 elm_tickernoti_add(Evas_Object *parent)
275 {
276    Evas_Object *obj;
277    Evas *e;
278    Widget_Data *wd;
279
280    wd = ELM_NEW(Widget_Data);
281    wd->win = _create_window (parent, "noti-window");
282
283    e = evas_object_evas_get(wd->win);
284    obj = elm_widget_add(e);
285    ELM_SET_WIDTYPE(widtype, "tickernoti");
286    elm_widget_type_set(obj, "tickernoti");
287    elm_widget_sub_object_add(wd->win, obj);
288    elm_widget_data_set(obj, wd);
289    elm_widget_del_hook_set(obj, _del_hook);
290    elm_widget_theme_hook_set(obj, _theme_hook);
291    elm_widget_can_focus_set(obj, 0);
292    elm_widget_disable_hook_set(obj, _disable_hook);
293
294    wd->orient = ELM_TICKERNOTI_ORIENT_TOP;
295
296    _create_tickernoti (obj);
297
298    evas_object_event_callback_add (obj, EVAS_CALLBACK_SHOW, _show, NULL);
299    evas_object_event_callback_add (obj, EVAS_CALLBACK_HIDE, _hide, NULL);
300    evas_object_smart_callbacks_descriptions_set(obj, _signals);
301    return obj;
302 }
303
304 /**
305  * Set the label on the tickernoti object
306  *
307  * @param obj The tickernoti object
308  * @param label The label will be used on the tickernoti object
309  *
310  * @ingroup TickerNoti
311  */
312 EAPI void
313 elm_tickernoti_label_set (Evas_Object *obj, const char *label)
314 {
315    ELM_CHECK_WIDTYPE(obj, widtype);
316    Widget_Data *wd = elm_widget_data_get(obj);
317
318    if (!wd) return;
319    eina_stringshare_replace(&wd->label, label);
320    edje_object_part_text_set(wd->edje_obj, "elm.text", wd->label);
321    _sizing_eval(obj);
322 }
323
324 /**
325  * Get the label used on the tickernoti object
326  *
327  * @param obj The tickernotil object
328  * @return The string inside the label
329  * @ingroup TickerNoti
330  */
331 EAPI const char *
332 elm_tickernoti_label_get (const Evas_Object *obj)
333 {
334    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
335    Widget_Data *wd = elm_widget_data_get(obj);
336    if (!wd) return NULL;
337
338    return wd->label;
339 }
340
341 /**
342  * Set the action button object used on the tickernoti object
343  *
344  * @param obj The tickernotil object
345  * @param button The button object will be used on the tickernoti object
346  * @ingroup TickerNoti
347  */
348 EAPI void
349 elm_tickernoti_button_set (Evas_Object *obj, Evas_Object *button)
350 {
351    ELM_CHECK_WIDTYPE(obj, widtype);
352    Widget_Data *wd = elm_widget_data_get(obj);
353    if (!wd) return;
354    if (!button) return;
355    edje_object_part_swallow (wd->edje_obj, "button", button);
356    wd->button = button;
357    evas_object_smart_callback_add (wd->button, "clicked", _tickernoti_hide_cb, wd);
358 }
359
360 /**
361  * Get the action button object used on the tickernoti object
362  *
363  * @param obj The tickernotil object
364  * @return The button object inside the tickernoti
365  * @ingroup TickerNoti
366  */
367 EAPI Evas_Object *
368 elm_tickernoti_button_get (const Evas_Object *obj)
369 {
370    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
371    Widget_Data *wd = elm_widget_data_get(obj);
372    if (!wd) return NULL;
373    return wd->button;
374 }
375
376 /**
377  * Set the icon object of the tickernoti object
378  *
379  * @param obj The tickernotil object
380  * @param icon The icon object will be used on the tickernoti object
381  * @ingroup TickerNoti
382  */
383 EAPI void
384 elm_tickernoti_icon_set (Evas_Object *obj, Evas_Object *icon)
385 {
386    ELM_CHECK_WIDTYPE(obj, widtype);
387    Widget_Data *wd = elm_widget_data_get(obj);
388
389    if (!wd) return;
390    if (!icon) return;
391    edje_object_part_swallow (wd->edje_obj, "icon", icon);
392    wd->icon = icon;
393 }
394
395 /**
396  * Get the icon object of the tickernoti object
397  *
398  * @param obj The tickernotil object
399  * @return The icon object inside the tickernoti
400  * @ingroup TickerNoti
401  */
402 EAPI Evas_Object *
403 elm_tickernoti_icon_get (const Evas_Object *obj)
404 {
405    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
406    Widget_Data *wd = elm_widget_data_get(obj);
407    if (!wd) return NULL;
408    return wd->icon;
409 }
410
411 /**
412  * Get the rotation of tickernoti object
413  *
414  * @param obj The tickernotil object
415  * @return The rotation angle
416  * @ingroup TickerNoti
417  */
418 EAPI int
419 elm_tickernoti_rotation_get (const Evas_Object *obj)
420 {
421    ELM_CHECK_WIDTYPE(obj, widtype) -1;
422    Widget_Data *wd = elm_widget_data_get(obj);
423    if (!wd) return -1;
424    return wd->angle;
425 }
426
427 /**
428  * Set the rotation angle for the tickernoti object
429  *
430  * @param obj The tickernoti object
431  * @param angle The rotation angle(in degree) will be used on the tickernoti object
432  * @ingroup TickerNoti
433  */
434 EAPI void
435 elm_tickernoti_rotation_set (Evas_Object *obj, int angle)
436 {
437    ELM_CHECK_WIDTYPE(obj, widtype);
438    Widget_Data *wd = elm_widget_data_get(obj);
439    Evas_Coord w, x = 0, y = 0;
440
441    if (!wd) return;
442    if (angle%90 != 0) return;
443
444    wd->angle = angle%360;
445    if (wd->angle < 0)
446      wd->angle = 360 + wd->angle;
447
448 #ifdef HAVE_ELEMENTARY_X
449    Evas_Coord root_w, root_h;
450
451    /*
452    * manual calculate win_tickernoti_indi window position & size
453    *  - win_indi is not full size window
454    */
455    ecore_x_window_size_get (ecore_x_window_root_first_get(), &root_w, &root_h);
456
457    /* rotate win */
458    switch (wd->angle)
459      {
460       case 90:
461          w = root_h;
462          if (wd->orient == ELM_TICKERNOTI_ORIENT_BOTTOM)
463            x = root_w-wd->noti_height;
464          break;
465       case 270:
466          w = root_h;
467          if (!(wd->orient == ELM_TICKERNOTI_ORIENT_BOTTOM))
468            x = root_w-wd->noti_height;
469          break;
470       case 180:
471          w = root_w;
472          if (!wd->orient == ELM_TICKERNOTI_ORIENT_BOTTOM)
473            y = root_h - wd->noti_height;
474          break;
475        case 0:
476       default:
477          w = root_w;
478          if (wd->orient == ELM_TICKERNOTI_ORIENT_BOTTOM)
479            y = root_h - wd->noti_height;
480          break;
481      }
482 #endif
483 /* detail */
484    elm_win_rotation_with_resize_set (wd->win, wd->angle);
485    evas_object_move (wd->win, x, y);
486
487    evas_object_resize (wd->win, w, wd->noti_height);
488 #ifdef HAVE_ELEMENTARY_X
489    _update_window_hints (wd->win);
490 #endif
491 }
492
493 /**
494  * Set the orientation of the tickernoti object
495  *
496  * @param obj The tickernoti object
497  * @param orient The orientation of tickernoti object
498  * @ingroup TickerNoti
499  */
500 EAPI void
501 elm_tickernoti_orientation_set (Evas_Object *obj, Elm_Tickernoti_Orient orient)
502 {
503    ELM_CHECK_WIDTYPE(obj, widtype);
504
505 #ifdef HAVE_ELEMENTARY_X
506    Evas_Coord root_w, root_h;
507 #endif
508    Widget_Data *wd = elm_widget_data_get(obj);
509
510    if (!wd) return;
511
512 #ifdef HAVE_ELEMENTARY_X
513    ecore_x_window_size_get (ecore_x_window_root_first_get(), &root_w, &root_h);
514 #endif
515
516    switch (orient) {
517       case ELM_TICKERNOTI_ORIENT_BOTTOM:
518 #ifdef HAVE_ELEMENTARY_X
519          evas_object_move (wd->win, 0, root_h - wd->noti_height);
520 #endif
521          wd->orient = ELM_TICKERNOTI_ORIENT_BOTTOM;
522          break;
523       case ELM_TICKERNOTI_ORIENT_TOP:
524       default:
525 #ifdef HAVE_ELEMENTARY_X
526          evas_object_move (wd->win, 0, 0);
527 #endif
528          wd->orient = ELM_TICKERNOTI_ORIENT_TOP;
529          break;
530    }
531 }
532
533 /**
534  * Get the orientation of the tickernoti object
535  *
536  * @param obj The tickernotil object
537  * @return The orientation of tickernotil object
538  * @ingroup TickerNoti
539  */
540 EAPI Elm_Tickernoti_Orient
541 elm_tickernoti_orientation_get (const Evas_Object *obj)
542 {
543    ELM_CHECK_WIDTYPE(obj, widtype) -1;
544    Widget_Data *wd = elm_widget_data_get(obj);
545
546    if (!wd) return -1;
547    return wd->orient;
548 }
549
550 // ################### Below APIs are going to be removed. ###########################
551 /**
552  * Set the detail label on the tickernoti object
553  *
554  * @param obj The tickernoti object
555  * @param label The label will be used on the tickernoti object
556  *
557  * @ingroup TickerNoti
558  */
559 EAPI void
560 elm_tickernoti_detailview_label_set (Evas_Object *obj, const char *label)
561 {
562    elm_tickernoti_label_set (obj, label);
563 }
564
565 /**
566  * Get the detail label used on the tickernoti object
567  *
568  * @param obj The tickernotil object
569  * @return The string inside the label
570  * @ingroup TickerNoti
571  */
572 EAPI const char *
573 elm_tickernoti_detailview_label_get (const Evas_Object *obj)
574 {
575    return elm_tickernoti_label_get (obj);
576 }
577
578 /**
579  * Set the button object used on the tickernoti object
580  *
581  * @param obj The tickernotil object
582  * @param button The button object will be used on the tickernoti object
583  * @ingroup TickerNoti
584  */
585 EAPI void
586 elm_tickernoti_detailview_button_set (Evas_Object *obj, Evas_Object *button)
587 {
588    elm_tickernoti_button_set (obj, button);
589 }
590
591
592 /**
593  * Get the button object used on the tickernoti object
594  *
595  * @param obj The tickernotil object
596  * @return The button object inside the tickernoti
597  * @ingroup TickerNoti
598  */
599 EAPI Evas_Object *
600 elm_tickernoti_detailview_button_get (const Evas_Object *obj)
601 {
602    return elm_tickernoti_button_get (obj);
603 }
604
605
606
607 /**
608  * Set the detail icon object used on the tickernoti object
609  *
610  * @param obj The tickernotil object
611  * @param icon The icon object will be used on the tickernoti object
612  * @ingroup TickerNoti
613  */
614 EAPI void
615 elm_tickernoti_detailview_icon_set (Evas_Object *obj, Evas_Object *icon)
616 {
617    elm_tickernoti_icon_set (obj, icon);
618 }
619
620 /**
621  * Get the detail icon object used on the tickernoti object
622  *
623  * @param obj The tickernotil object
624  * @return The icon object inside the tickernoti
625  * @ingroup TickerNoti
626  */
627 EAPI Evas_Object *
628 elm_tickernoti_detailview_icon_get (const Evas_Object *obj)
629 {
630    return elm_tickernoti_icon_get (obj);
631 }
632
633 /**
634  * Get the view mode on the tickernoti object
635  *
636  * @param obj The tickernotil object
637  * @return The view mode
638  * @ingroup TickerNoti
639  */
640 EAPI Elm_Tickernoti_Mode
641 elm_tickernoti_mode_get (const Evas_Object *obj)
642 {
643    ELM_CHECK_WIDTYPE(obj, widtype) -1;
644    Widget_Data *wd = elm_widget_data_get(obj);
645    if (!wd) return -1;
646    return wd->mode;
647 }
648
649 /**
650  * Set the view mode used on the tickernoti object
651  *
652  * @param obj The tickernotil object
653  * @param mode The view mode will be used on the tickernoti object
654  * @ingroup TickerNoti
655  */
656 EAPI void
657 elm_tickernoti_mode_set (Evas_Object *obj, Elm_Tickernoti_Mode mode)
658 {
659    ELM_CHECK_WIDTYPE(obj, widtype);
660    Widget_Data *wd = elm_widget_data_get(obj);
661    if (!wd) return;
662
663    switch(mode){
664       case ELM_TICKERNOTI_DEFAULT:
665       case ELM_TICKERNOTI_DETAILVIEW:
666          wd->mode = mode;
667          break;
668       default:
669          break;
670    }
671 }
672
673 /**
674  * Get the detail view window(elm_win) on the tickernoti object
675  *
676  * @param obj The tickernotil object
677  * @return detail view window(elm_win) object
678  * @ingroup TickerNoti
679  */
680 EAPI Evas_Object *
681 elm_tickernoti_win_get (const Evas_Object *obj)
682 {
683    ELM_CHECK_WIDTYPE(obj, widtype) NULL;
684    Widget_Data *wd = elm_widget_data_get(obj);
685    if (!wd) return NULL;
686    return wd->win;
687 }
688
689 /**
690  * Get the detail view window(elm_win) on the tickernoti object
691  *
692  * @param obj The tickernotil object
693  * @return detail view window(elm_win) object
694  * @ingroup TickerNoti
695  */
696 EAPI Evas_Object *
697 elm_tickernoti_detailview_get (const Evas_Object *obj)
698 {
699    return elm_tickernoti_win_get (obj);
700 }
701