1 #include <Elementary.h>
4 typedef struct _Widget_Data Widget_Data;
8 Evas_Object *notify, *content, *parent;
10 Elm_Notify_Orient orient;
11 Eina_Bool repeat_events;
12 Evas_Object *block_events;
18 static const char *widtype = NULL;
19 static void _del_hook(Evas_Object *obj);
20 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
21 static void _theme_hook(Evas_Object *obj);
22 static void _sizing_eval(Evas_Object *obj);
23 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
24 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
25 static void _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
26 static void _calc(Evas_Object *obj);
27 static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
28 static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
29 static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
30 static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
31 static void _parent_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
33 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
34 static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
36 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
37 static const char SIG_TIMEOUT[] = "timeout";
38 static const Evas_Smart_Cb_Description _signals[] = {
39 {SIG_BLOCK_CLICKED, ""},
45 _del_pre_hook(Evas_Object *obj)
47 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
48 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
49 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
50 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
51 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
55 _del_hook(Evas_Object *obj)
57 Widget_Data *wd = elm_widget_data_get(obj);
59 elm_notify_parent_set(obj, NULL);
60 elm_notify_repeat_events_set(obj, EINA_TRUE);
63 ecore_timer_del(wd->timer);
70 * Return Notification orientation with RTL
72 * This function switches-sides of notification area when in RTL mode.
74 * @param obj notification object.
76 * @param orient Original notification orientation.
78 * @return notification orientation with respect to the object RTL mode.
82 static Elm_Notify_Orient
83 _notify_orientation_with_rtl(Evas_Object *obj, Elm_Notify_Orient orient)
85 if (elm_widget_mirrored_get(obj))
89 case ELM_NOTIFY_ORIENT_LEFT:
90 orient = ELM_NOTIFY_ORIENT_RIGHT;
92 case ELM_NOTIFY_ORIENT_RIGHT:
93 orient = ELM_NOTIFY_ORIENT_LEFT;
95 case ELM_NOTIFY_ORIENT_TOP_LEFT:
96 orient = ELM_NOTIFY_ORIENT_TOP_RIGHT;
98 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
99 orient = ELM_NOTIFY_ORIENT_TOP_LEFT;
101 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
102 orient = ELM_NOTIFY_ORIENT_BOTTOM_RIGHT;
104 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
105 orient = ELM_NOTIFY_ORIENT_BOTTOM_LEFT;
116 _notify_theme_apply(Evas_Object *obj)
118 Widget_Data *wd = elm_widget_data_get(obj);
119 const char *style = elm_widget_style_get(obj);
123 case ELM_NOTIFY_ORIENT_TOP:
124 _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
126 case ELM_NOTIFY_ORIENT_CENTER:
127 _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
129 case ELM_NOTIFY_ORIENT_BOTTOM:
130 _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
132 case ELM_NOTIFY_ORIENT_LEFT:
133 _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
135 case ELM_NOTIFY_ORIENT_RIGHT:
136 _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
138 case ELM_NOTIFY_ORIENT_TOP_LEFT:
139 _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
141 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
142 _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
144 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
145 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
147 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
148 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
150 case ELM_NOTIFY_ORIENT_LAST:
156 * Moves notification to orientation.
158 * This fucntion moves notification to orientation
159 * according to object RTL orientation.
161 * @param obj notification object.
163 * @param orient notification orientation.
168 _notify_move_to_orientation(Evas_Object *obj)
170 Widget_Data *wd = elm_widget_data_get(obj);
173 Evas_Coord minw = -1, minh = -1;
174 Evas_Coord x, y, w, h;
177 evas_object_geometry_get(obj, &x, &y, &w, &h);
178 edje_object_size_min_get(wd->notify, &minw, &minh);
179 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
180 offx = (w - minw) / 2;
181 offy = (h - minh) / 2;
183 switch (_notify_orientation_with_rtl(obj, wd->orient))
185 case ELM_NOTIFY_ORIENT_TOP:
186 evas_object_move(wd->notify, x + offx, y);
188 case ELM_NOTIFY_ORIENT_CENTER:
189 evas_object_move(wd->notify, x + offx, y + offy);
191 case ELM_NOTIFY_ORIENT_BOTTOM:
192 evas_object_move(wd->notify, x + offx, y + h - minh);
194 case ELM_NOTIFY_ORIENT_LEFT:
195 evas_object_move(wd->notify, x, y + offy);
197 case ELM_NOTIFY_ORIENT_RIGHT:
198 evas_object_move(wd->notify, x + w - minw, y + offy);
200 case ELM_NOTIFY_ORIENT_TOP_LEFT:
201 evas_object_move(wd->notify, x, y);
203 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
204 evas_object_move(wd->notify, x + w - minw, y);
206 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
207 evas_object_move(wd->notify, x, y + h - minh);
209 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
210 evas_object_move(wd->notify, x + w - minw, y + h - minh);
212 case ELM_NOTIFY_ORIENT_LAST:
218 _block_events_theme_apply(Evas_Object *obj)
220 Widget_Data *wd = elm_widget_data_get(obj);
221 const char *style = elm_widget_style_get(obj);
222 _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
226 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
228 Widget_Data *wd = elm_widget_data_get(obj);
230 edje_object_mirrored_set(wd->notify, rtl);
231 _notify_move_to_orientation(obj);
235 _theme_hook(Evas_Object *obj)
237 Widget_Data *wd = elm_widget_data_get(obj);
239 _elm_widget_mirrored_reload(obj);
240 _mirrored_set(obj, elm_widget_mirrored_get(obj));
241 _notify_theme_apply(obj);
242 if (wd->block_events) _block_events_theme_apply(obj);
243 edje_object_scale_set(wd->notify, elm_widget_scale_get(obj) *
249 _sizing_eval(Evas_Object *obj)
251 Widget_Data *wd = elm_widget_data_get(obj);
254 if (!wd->parent) return;
255 evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
256 evas_object_move(obj, x, y);
257 evas_object_resize(obj, w, h);
261 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
267 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
269 Widget_Data *wd = elm_widget_data_get(obj);
270 Evas_Object *sub = event_info;
273 if (sub == wd->content)
275 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
276 _changed_size_hints, obj);
277 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
278 _content_resize, obj);
284 _signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
286 Widget_Data *wd = elm_widget_data_get(data);
288 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
292 _restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
294 Widget_Data *wd = elm_widget_data_get(obj);
296 evas_object_layer_set(wd->notify,
297 evas_object_layer_get(obj));
301 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
307 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
313 _calc(Evas_Object *obj)
315 Widget_Data *wd = elm_widget_data_get(obj);
316 Evas_Coord minw = -1, minh = -1;
317 Evas_Coord x, y, w, h;
322 evas_object_geometry_get(obj, &x, &y, &w, &h);
323 edje_object_size_min_get(wd->notify, &minw, &minh);
324 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
328 _notify_move_to_orientation(obj);
329 evas_object_resize(wd->notify, minw, minh);
334 _timer_cb(void *data)
336 Evas_Object *obj = data;
337 Widget_Data *wd = elm_widget_data_get(obj);
338 if (!wd) return ECORE_CALLBACK_CANCEL;
340 evas_object_hide(obj);
341 evas_object_smart_callback_call(obj, SIG_TIMEOUT, NULL);
342 return ECORE_CALLBACK_CANCEL;
346 _timer_init(Evas_Object *obj, Widget_Data *wd)
350 ecore_timer_del(wd->timer);
353 if ((evas_object_visible_get(obj)) && (wd->timeout > 0.0))
354 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
358 _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
360 Widget_Data *wd = elm_widget_data_get(obj);
362 evas_object_show(wd->notify);
363 if (!wd->repeat_events)
364 evas_object_show(wd->block_events);
365 _timer_init(obj, wd);
366 elm_object_focus_set(obj, EINA_TRUE);
370 _hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
372 Widget_Data *wd = elm_widget_data_get(obj);
374 evas_object_hide(wd->notify);
375 if (!wd->repeat_events)
376 evas_object_hide(wd->block_events);
379 ecore_timer_del(wd->timer);
385 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
387 Widget_Data *wd = elm_widget_data_get(data);
390 evas_object_hide(data);
394 _parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
396 Widget_Data *wd = elm_widget_data_get(data);
398 evas_object_hide(data);
402 _elm_notify_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
404 Widget_Data *wd = elm_widget_data_get(obj);
407 if ((!wd) || (!wd->content))
412 /* Try Focus cycle in subitem */
413 return elm_widget_focus_next_get(cur, dir, next);
417 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
419 ELM_CHECK_WIDTYPE(obj, widtype);
421 if (part && strcmp(part ,"default")) return;
422 wd = elm_widget_data_get(obj);
424 if (wd->content == content) return;
425 if (wd->content) evas_object_del(wd->content);
426 wd->content = content;
430 elm_widget_sub_object_add(obj, content);
431 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
432 _changed_size_hints, obj);
433 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
434 _content_resize, obj);
435 edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
442 _content_get_hook(const Evas_Object *obj, const char *part)
444 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
446 if (part && strcmp(part ,"default")) return NULL;
447 wd = elm_widget_data_get(obj);
448 if (!wd) return NULL;
453 _content_unset_hook(Evas_Object *obj, const char *part)
455 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
457 Evas_Object *content;
458 if (part && strcmp(part ,"default")) return NULL;
459 wd = elm_widget_data_get(obj);
460 if (!wd) return NULL;
461 if (!wd->content) return NULL;
462 content = wd->content;
463 elm_widget_sub_object_del(obj, wd->content);
464 evas_object_event_callback_del_full(wd->content,
465 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
466 _changed_size_hints, obj);
467 evas_object_event_callback_del_full(wd->content, EVAS_CALLBACK_RESIZE,
468 _content_resize, obj);
469 edje_object_part_unswallow(wd->notify, wd->content);
475 elm_notify_add(Evas_Object *parent)
481 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
483 ELM_SET_WIDTYPE(widtype, "notify");
484 elm_widget_type_set(obj, "notify");
485 elm_widget_sub_object_add(parent, obj);
486 elm_widget_data_set(obj, wd);
487 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
488 elm_widget_del_hook_set(obj, _del_hook);
489 elm_widget_theme_hook_set(obj, _theme_hook);
490 elm_widget_can_focus_set(obj, EINA_FALSE);
491 elm_widget_focus_next_hook_set(obj, _elm_notify_focus_next_hook);
492 elm_widget_content_set_hook_set(obj, _content_set_hook);
493 elm_widget_content_get_hook_set(obj, _content_get_hook);
494 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
496 wd->repeat_events = EINA_TRUE;
498 wd->notify = edje_object_add(e);
500 elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
502 elm_notify_parent_set(obj, parent);
504 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
505 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
506 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
507 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
508 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
509 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
510 _mirrored_set(obj, elm_widget_mirrored_get(obj));
513 evas_object_smart_callbacks_descriptions_set(obj, _signals);
518 elm_notify_content_set(Evas_Object *obj, Evas_Object *content)
520 _content_set_hook(obj, NULL, content);
524 elm_notify_content_unset(Evas_Object *obj)
526 return _content_unset_hook(obj, NULL);
530 elm_notify_content_get(const Evas_Object *obj)
532 return _content_get_hook(obj, NULL);
536 elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
538 ELM_CHECK_WIDTYPE(obj, widtype);
539 Widget_Data *wd = elm_widget_data_get(obj);
543 evas_object_event_callback_del_full(wd->parent,
544 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
545 _changed_size_hints, obj);
546 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
547 _changed_size_hints, obj);
548 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
549 _changed_size_hints, obj);
550 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
552 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
560 evas_object_event_callback_add(parent,
561 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
562 _changed_size_hints, obj);
563 evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
564 _changed_size_hints, obj);
565 evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
566 _changed_size_hints, obj);
567 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
569 evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
577 elm_notify_parent_get(const Evas_Object *obj)
579 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
580 Widget_Data *wd = elm_widget_data_get(obj);
581 if (!wd) return NULL;
586 elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
588 ELM_CHECK_WIDTYPE(obj, widtype);
589 Widget_Data *wd = elm_widget_data_get(obj);
591 if (wd->orient == orient) return;
593 _notify_theme_apply(obj);
594 _resize(obj, NULL, obj, NULL);
597 EAPI Elm_Notify_Orient
598 elm_notify_orient_get(const Evas_Object *obj)
600 ELM_CHECK_WIDTYPE(obj, widtype) -1;
601 Widget_Data *wd = elm_widget_data_get(obj);
607 elm_notify_timeout_set(Evas_Object *obj, double timeout)
609 ELM_CHECK_WIDTYPE(obj, widtype);
610 Widget_Data *wd = elm_widget_data_get(obj);
612 wd->timeout = timeout;
613 _timer_init(obj, wd);
617 elm_notify_timeout_get(const Evas_Object *obj)
619 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
620 Widget_Data *wd = elm_widget_data_get(obj);
626 elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
628 ELM_CHECK_WIDTYPE(obj, widtype);
629 Widget_Data *wd = elm_widget_data_get(obj);
631 if (repeat == wd->repeat_events) return;
632 wd->repeat_events = repeat;
635 wd->block_events = edje_object_add(evas_object_evas_get(obj));
636 _block_events_theme_apply(obj);
637 elm_widget_resize_object_set(obj, wd->block_events);
638 edje_object_signal_callback_add(wd->block_events, "elm,action,click",
639 "elm", _signal_block_clicked, obj);
642 evas_object_del(wd->block_events);
646 elm_notify_repeat_events_get(const Evas_Object *obj)
648 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
649 Widget_Data *wd = elm_widget_data_get(obj);
650 if (!wd) return EINA_FALSE;
651 return wd->repeat_events;