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 allow_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_allow_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->allow_events) evas_object_show(wd->block_events);
364 _timer_init(obj, wd);
365 elm_object_focus_set(obj, EINA_TRUE);
369 _hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
371 Widget_Data *wd = elm_widget_data_get(obj);
373 evas_object_hide(wd->notify);
374 if (!wd->allow_events) evas_object_hide(wd->block_events);
377 ecore_timer_del(wd->timer);
383 _parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
385 Widget_Data *wd = elm_widget_data_get(data);
388 evas_object_hide(data);
392 _parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
394 Widget_Data *wd = elm_widget_data_get(data);
396 evas_object_hide(data);
400 _elm_notify_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
402 Widget_Data *wd = elm_widget_data_get(obj);
405 if ((!wd) || (!wd->content))
410 /* Try Focus cycle in subitem */
411 return elm_widget_focus_next_get(cur, dir, next);
415 _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
417 ELM_CHECK_WIDTYPE(obj, widtype);
419 if (part && strcmp(part ,"default")) return;
420 wd = elm_widget_data_get(obj);
422 if (wd->content == content) return;
423 if (wd->content) evas_object_del(wd->content);
424 wd->content = content;
428 elm_widget_sub_object_add(obj, content);
429 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
430 _changed_size_hints, obj);
431 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
432 _content_resize, obj);
433 edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
440 _content_get_hook(const Evas_Object *obj, const char *part)
442 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
444 if (part && strcmp(part ,"default")) return NULL;
445 wd = elm_widget_data_get(obj);
446 if (!wd) return NULL;
451 _content_unset_hook(Evas_Object *obj, const char *part)
453 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
455 Evas_Object *content;
456 if (part && strcmp(part ,"default")) return NULL;
457 wd = elm_widget_data_get(obj);
458 if (!wd) return NULL;
459 if (!wd->content) return NULL;
460 content = wd->content;
461 elm_widget_sub_object_del(obj, wd->content);
462 edje_object_part_unswallow(wd->notify, content);
467 elm_notify_add(Evas_Object *parent)
473 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
475 ELM_SET_WIDTYPE(widtype, "notify");
476 elm_widget_type_set(obj, "notify");
477 elm_widget_sub_object_add(parent, obj);
478 elm_widget_data_set(obj, wd);
479 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
480 elm_widget_del_hook_set(obj, _del_hook);
481 elm_widget_theme_hook_set(obj, _theme_hook);
482 elm_widget_can_focus_set(obj, EINA_FALSE);
483 elm_widget_focus_next_hook_set(obj, _elm_notify_focus_next_hook);
484 elm_widget_content_set_hook_set(obj, _content_set_hook);
485 elm_widget_content_get_hook_set(obj, _content_get_hook);
486 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
488 wd->allow_events = EINA_TRUE;
490 wd->notify = edje_object_add(e);
492 elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
494 elm_notify_parent_set(obj, parent);
496 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
497 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
498 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
499 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
500 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
501 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
502 _mirrored_set(obj, elm_widget_mirrored_get(obj));
505 evas_object_smart_callbacks_descriptions_set(obj, _signals);
510 elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
512 ELM_CHECK_WIDTYPE(obj, widtype);
513 Widget_Data *wd = elm_widget_data_get(obj);
517 evas_object_event_callback_del_full(wd->parent,
518 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
519 _changed_size_hints, obj);
520 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
521 _changed_size_hints, obj);
522 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
523 _changed_size_hints, obj);
524 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
526 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
534 evas_object_event_callback_add(parent,
535 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
536 _changed_size_hints, obj);
537 evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
538 _changed_size_hints, obj);
539 evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
540 _changed_size_hints, obj);
541 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
543 evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
551 elm_notify_parent_get(const Evas_Object *obj)
553 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
554 Widget_Data *wd = elm_widget_data_get(obj);
555 if (!wd) return NULL;
560 elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
562 ELM_CHECK_WIDTYPE(obj, widtype);
563 Widget_Data *wd = elm_widget_data_get(obj);
565 if (wd->orient == orient) return;
567 _notify_theme_apply(obj);
568 _resize(obj, NULL, obj, NULL);
571 EAPI Elm_Notify_Orient
572 elm_notify_orient_get(const Evas_Object *obj)
574 ELM_CHECK_WIDTYPE(obj, widtype) -1;
575 Widget_Data *wd = elm_widget_data_get(obj);
581 elm_notify_timeout_set(Evas_Object *obj, double timeout)
583 ELM_CHECK_WIDTYPE(obj, widtype);
584 Widget_Data *wd = elm_widget_data_get(obj);
586 wd->timeout = timeout;
587 _timer_init(obj, wd);
591 elm_notify_timeout_get(const Evas_Object *obj)
593 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
594 Widget_Data *wd = elm_widget_data_get(obj);
600 elm_notify_allow_events_set(Evas_Object *obj, Eina_Bool allow)
602 ELM_CHECK_WIDTYPE(obj, widtype);
603 Widget_Data *wd = elm_widget_data_get(obj);
605 if (allow == wd->allow_events) return;
606 wd->allow_events = allow;
609 wd->block_events = edje_object_add(evas_object_evas_get(obj));
610 _block_events_theme_apply(obj);
611 elm_widget_resize_object_set(obj, wd->block_events);
612 edje_object_signal_callback_add(wd->block_events, "elm,action,click",
613 "elm", _signal_block_clicked, obj);
616 evas_object_del(wd->block_events);
620 elm_notify_allow_events_get(const Evas_Object *obj)
622 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
623 Widget_Data *wd = elm_widget_data_get(obj);
624 if (!wd) return EINA_FALSE;
625 return wd->allow_events;