1 #include <Elementary.h>
5 * @defgroup Notify Notify
7 * Display a window in a particular region of the application (top,
8 * bottom, etc. A timeout can be set to automatically close the
9 * window. This is so that, after an evas_object_show() on a notify
10 * object, if a timeout was set on it, it will <b>automatically</b>
11 * get hidden after that time.
13 * Signals that you can add callbacks for are:
15 * "timeout" - when timeout happens on notify and it's hidden
16 * "block,clicked" - when it's hidden by a click outside of the notify's view
19 typedef struct _Widget_Data Widget_Data;
23 Evas_Object *notify, *content, *parent;
25 Elm_Notify_Orient orient;
26 Eina_Bool repeat_events;
27 Evas_Object *block_events;
33 static const char *widtype = NULL;
34 static void _del_hook(Evas_Object *obj);
35 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
36 static void _theme_hook(Evas_Object *obj);
37 static void _sizing_eval(Evas_Object *obj);
38 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
39 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
40 static void _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
41 static void _calc(Evas_Object *obj);
42 static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
43 static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
44 static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
45 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
47 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
48 static const char SIG_TIMEOUT[] = "timeout";
49 static const Evas_Smart_Cb_Description _signals[] = {
50 {SIG_BLOCK_CLICKED, ""},
56 _del_pre_hook(Evas_Object *obj)
58 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
59 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
60 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
61 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
65 _del_hook(Evas_Object *obj)
67 Widget_Data *wd = elm_widget_data_get(obj);
69 elm_notify_parent_set(obj, NULL);
70 elm_notify_repeat_events_set(obj, EINA_TRUE);
73 ecore_timer_del(wd->timer);
80 * Return Notification orientation with RTL
82 * This function switches-sides of notification area when in RTL mode.
84 * @param obj notification object.
86 * @param orient Original notification orientation.
88 * @return notification orientation with respect to the object RTL mode.
92 static Elm_Notify_Orient
93 _notify_orientation_with_rtl(Evas_Object *obj, Elm_Notify_Orient orient)
95 if (elm_widget_mirrored_get(obj))
99 case ELM_NOTIFY_ORIENT_LEFT:
100 orient = ELM_NOTIFY_ORIENT_RIGHT;
102 case ELM_NOTIFY_ORIENT_RIGHT:
103 orient = ELM_NOTIFY_ORIENT_LEFT;
105 case ELM_NOTIFY_ORIENT_TOP_LEFT:
106 orient = ELM_NOTIFY_ORIENT_TOP_RIGHT;
108 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
109 orient = ELM_NOTIFY_ORIENT_TOP_LEFT;
111 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
112 orient = ELM_NOTIFY_ORIENT_BOTTOM_RIGHT;
114 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
115 orient = ELM_NOTIFY_ORIENT_BOTTOM_LEFT;
126 _notify_theme_apply(Evas_Object *obj)
128 Widget_Data *wd = elm_widget_data_get(obj);
129 const char *style = elm_widget_style_get(obj);
133 case ELM_NOTIFY_ORIENT_TOP:
134 _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
136 case ELM_NOTIFY_ORIENT_CENTER:
137 _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
139 case ELM_NOTIFY_ORIENT_BOTTOM:
140 _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
142 case ELM_NOTIFY_ORIENT_LEFT:
143 _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
145 case ELM_NOTIFY_ORIENT_RIGHT:
146 _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
148 case ELM_NOTIFY_ORIENT_TOP_LEFT:
149 _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
151 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
152 _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
154 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
155 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
157 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
158 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
160 case ELM_NOTIFY_ORIENT_LAST:
166 * Moves notification to orientation.
168 * This fucntion moves notification to orientation
169 * according to object RTL orientation.
171 * @param obj notification object.
173 * @param orient notification orientation.
178 _notify_move_to_orientation(Evas_Object *obj)
180 Widget_Data *wd = elm_widget_data_get(obj);
183 Evas_Coord minw = -1, minh = -1;
184 Evas_Coord x, y, w, h;
187 evas_object_geometry_get(obj, &x, &y, &w, &h);
188 edje_object_size_min_get(wd->notify, &minw, &minh);
189 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
190 offx = (w - minw) / 2;
191 offy = (h - minh) / 2;
193 switch (_notify_orientation_with_rtl(obj, wd->orient))
195 case ELM_NOTIFY_ORIENT_TOP:
196 evas_object_move(wd->notify, x + offx, y);
198 case ELM_NOTIFY_ORIENT_CENTER:
199 evas_object_move(wd->notify, x + offx, y + offy);
201 case ELM_NOTIFY_ORIENT_BOTTOM:
202 evas_object_move(wd->notify, x + offx, y + h - minh);
204 case ELM_NOTIFY_ORIENT_LEFT:
205 evas_object_move(wd->notify, x, y + offy);
207 case ELM_NOTIFY_ORIENT_RIGHT:
208 evas_object_move(wd->notify, x + w - minw, y + offy);
210 case ELM_NOTIFY_ORIENT_TOP_LEFT:
211 evas_object_move(wd->notify, x, y);
213 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
214 evas_object_move(wd->notify, x + w - minw, y);
216 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
217 evas_object_move(wd->notify, x, y + h - minh);
219 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
220 evas_object_move(wd->notify, x + w - minw, y + h - minh);
222 case ELM_NOTIFY_ORIENT_LAST:
228 _block_events_theme_apply(Evas_Object *obj)
230 Widget_Data *wd = elm_widget_data_get(obj);
231 const char *style = elm_widget_style_get(obj);
232 _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
236 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
238 Widget_Data *wd = elm_widget_data_get(obj);
240 edje_object_mirrored_set(wd->notify, rtl);
241 _notify_move_to_orientation(obj);
245 _theme_hook(Evas_Object *obj)
247 Widget_Data *wd = elm_widget_data_get(obj);
249 _elm_widget_mirrored_reload(obj);
250 _mirrored_set(obj, elm_widget_mirrored_get(obj));
251 _notify_theme_apply(obj);
252 if (wd->block_events) _block_events_theme_apply(obj);
253 edje_object_scale_set(wd->notify, elm_widget_scale_get(obj) *
259 _sizing_eval(Evas_Object *obj)
261 Widget_Data *wd = elm_widget_data_get(obj);
264 if (!wd->parent) return;
265 evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
266 evas_object_move(obj, x, y);
267 evas_object_resize(obj, w, h);
271 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
277 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
279 Widget_Data *wd = elm_widget_data_get(obj);
280 Evas_Object *sub = event_info;
283 if (sub == wd->content)
285 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
286 _changed_size_hints, obj);
287 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
288 _content_resize, obj);
294 _signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
296 Widget_Data *wd = elm_widget_data_get(data);
298 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
302 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
308 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
314 _calc(Evas_Object *obj)
316 Widget_Data *wd = elm_widget_data_get(obj);
317 Evas_Coord minw = -1, minh = -1;
318 Evas_Coord x, y, w, h;
321 evas_object_geometry_get(obj, &x, &y, &w, &h);
322 edje_object_size_min_get(wd->notify, &minw, &minh);
323 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
327 _notify_move_to_orientation(obj);
328 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(obj);
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 __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
387 Widget_Data *wd = elm_widget_data_get(obj);
390 evas_object_hide(obj);
394 _parent_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
396 Widget_Data *wd = elm_widget_data_get(obj);
398 evas_object_hide(obj);
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 * Add a new notify to the parent
419 * @param parent The parent object
420 * @return The new object or NULL if it cannot be created
425 elm_notify_add(Evas_Object *parent)
431 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
433 ELM_SET_WIDTYPE(widtype, "notify");
434 elm_widget_type_set(obj, "notify");
435 elm_widget_sub_object_add(parent, obj);
436 elm_widget_data_set(obj, wd);
437 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
438 elm_widget_del_hook_set(obj, _del_hook);
439 elm_widget_theme_hook_set(obj, _theme_hook);
440 elm_widget_can_focus_set(obj, EINA_FALSE);
441 elm_widget_focus_next_hook_set(obj, _elm_notify_focus_next_hook);
443 wd->repeat_events = EINA_TRUE;
445 wd->notify = edje_object_add(e);
447 elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
449 elm_notify_parent_set(obj, parent);
451 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
452 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
453 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
454 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
455 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
457 _mirrored_set(obj, elm_widget_mirrored_get(obj));
460 evas_object_smart_callbacks_descriptions_set(obj, _signals);
465 * Set the content of the notify widget
467 * Once the content object is set, a previously set one will be deleted.
468 * If you want to keep that old content object, use the
469 * elm_notify_content_unset() function.
471 * @param obj The notify object
472 * @param content The content will be filled in this notify object
477 elm_notify_content_set(Evas_Object *obj, Evas_Object *content)
479 ELM_CHECK_WIDTYPE(obj, widtype);
480 Widget_Data *wd = elm_widget_data_get(obj);
482 if (wd->content == content) return;
483 if (wd->content) evas_object_del(wd->content);
484 wd->content = content;
488 elm_widget_sub_object_add(obj, content);
489 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
490 _changed_size_hints, obj);
491 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
492 _content_resize, obj);
493 edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
500 * Unset the content of the notify widget
502 * Unparent and return the content object which was set for this widget
504 * @param obj The notify object
505 * @return The content that was being used
510 elm_notify_content_unset(Evas_Object *obj)
512 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
513 Widget_Data *wd = elm_widget_data_get(obj);
514 Evas_Object *content;
515 if (!wd) return NULL;
516 if (!wd->content) return NULL;
517 content = wd->content;
518 elm_widget_sub_object_del(obj, wd->content);
519 edje_object_part_unswallow(wd->notify, wd->content);
525 * Return the content of the notify widget
527 * @param obj The notify object
528 * @return The content that is being used
533 elm_notify_content_get(const Evas_Object *obj)
535 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
536 Widget_Data *wd = elm_widget_data_get(obj);
538 if (!wd) return NULL;
543 * Set the notify parent
545 * Once the parent object is set, a previously set one will be disconnected
548 * @param obj The notify object
549 * @param content The new parent
554 elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
556 ELM_CHECK_WIDTYPE(obj, widtype);
557 Widget_Data *wd = elm_widget_data_get(obj);
561 evas_object_event_callback_del_full(wd->parent,
562 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
563 _changed_size_hints, obj);
564 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
565 _changed_size_hints, obj);
566 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
567 _changed_size_hints, obj);
568 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
570 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
578 evas_object_event_callback_add(parent,
579 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
580 _changed_size_hints, obj);
581 evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
582 _changed_size_hints, obj);
583 evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
584 _changed_size_hints, obj);
585 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
587 evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
589 edje_object_part_swallow(wd->notify, "elm.swallow.parent", parent);
596 * Get the notify parent
598 * @param obj The notify object
604 elm_notify_parent_get(const Evas_Object *obj)
606 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
607 Widget_Data *wd = elm_widget_data_get(obj);
608 if (!wd) return NULL;
613 * Set the orientation
615 * @param obj The notify object
616 * @param orient The new orientation
621 elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
623 ELM_CHECK_WIDTYPE(obj, widtype);
624 Widget_Data *wd = elm_widget_data_get(obj);
626 if (wd->orient == orient) return;
628 _notify_theme_apply(obj);
629 _resize(obj, NULL, obj, NULL);
633 * Return the orientation
634 * @param obj the notify objects
636 EAPI Elm_Notify_Orient
637 elm_notify_orient_get(const Evas_Object *obj)
639 ELM_CHECK_WIDTYPE(obj, widtype) -1;
640 Widget_Data *wd = elm_widget_data_get(obj);
646 * Set the time interval after which the notify window is going to be
649 * @param obj The notify object
650 * @param time The new timeout
652 * As said previously, an evas_object_show() on a notify object which
653 * had a timeout set by this function will trigger a timer to
654 * automatically hide it again. So, any order one calls
655 * elm_notify_timeout_set() and evas_object_show() on the same object
656 * (at hidden state) will behave the same.
658 * @note Set a value <= 0.0 to disable a running timer.
660 * @note If the value > 0.0 and the notify is previously visible, the
661 * timer will be started with this value, canceling any running timer.
665 elm_notify_timeout_set(Evas_Object *obj, double timeout)
667 ELM_CHECK_WIDTYPE(obj, widtype);
668 Widget_Data *wd = elm_widget_data_get(obj);
670 wd->timeout = timeout;
671 _timer_init(obj, wd);
675 * Return the timeout value (in seconds)
676 * @param obj the notify object
679 elm_notify_timeout_get(const Evas_Object *obj)
681 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
682 Widget_Data *wd = elm_widget_data_get(obj);
688 * When true if the user clicks outside the window the events will be
689 * catch by the others widgets, else the events are block and the signal
690 * dismiss will be sent when the user click outside the window.
692 * @note The default value is EINA_TRUE.
694 * @param obj The notify object
695 * @param repeats EINA_TRUE Events are repeats, else no
698 elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
700 ELM_CHECK_WIDTYPE(obj, widtype);
701 Widget_Data *wd = elm_widget_data_get(obj);
703 if (repeat == wd->repeat_events) return;
704 wd->repeat_events = repeat;
707 wd->block_events = edje_object_add(evas_object_evas_get(obj));
708 _block_events_theme_apply(obj);
709 elm_widget_resize_object_set(obj, wd->block_events);
710 edje_object_signal_callback_add(wd->block_events, "elm,action,clicked",
711 "elm", _signal_block_clicked, obj);
714 evas_object_del(wd->block_events);
718 * Return true if events are repeat below the notify object
719 * @param obj the notify object
722 elm_notify_repeat_events_get(const Evas_Object *obj)
724 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
725 Widget_Data *wd = elm_widget_data_get(obj);
726 if (!wd) return EINA_FALSE;
727 return wd->repeat_events;