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