1 #include <Elementary.h>
6 * @defgroup Notify notify
8 * Display a window in a particular region of the application (top,
9 * bottom, etc. A timeout can be set to automatically close the
10 * window. This is so that, after an evas_object_show() on a notify
11 * object, if a timeout was set on it, it will <b>automatically</b>
12 * get hidden after that time.
16 typedef struct _Widget_Data Widget_Data;
20 Evas_Object *notify, *content, *parent;
22 Elm_Notify_Orient orient;
23 Eina_Bool repeat_events;
24 Evas_Object *block_events;
30 static const char *widtype = NULL;
31 static void _del_hook(Evas_Object *obj);
32 static void _theme_hook(Evas_Object *obj);
33 static void _sizing_eval(Evas_Object *obj);
34 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
35 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
36 static void _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
37 static void _calc(Evas_Object *obj);
38 static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
39 static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
40 static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
41 static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
43 static const char SIG_BLOCK_CLICKED[] = "block,clicked";
44 static const char SIG_TIMEOUT[] = "timeout";
45 static const Evas_Smart_Cb_Description _signals[] = {
46 {SIG_BLOCK_CLICKED, ""},
52 _del_pre_hook(Evas_Object *obj)
54 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
55 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
56 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
57 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
61 _del_hook(Evas_Object *obj)
63 Widget_Data *wd = elm_widget_data_get(obj);
65 elm_notify_parent_set(obj, NULL);
66 elm_notify_repeat_events_set(obj, EINA_TRUE);
69 ecore_timer_del(wd->timer);
76 _notify_theme_apply(Evas_Object *obj)
78 Widget_Data *wd = elm_widget_data_get(obj);
79 const char *style = elm_widget_style_get(obj);
83 case ELM_NOTIFY_ORIENT_TOP:
84 _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
86 case ELM_NOTIFY_ORIENT_CENTER:
87 _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
89 case ELM_NOTIFY_ORIENT_BOTTOM:
90 _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
92 case ELM_NOTIFY_ORIENT_LEFT:
93 _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
95 case ELM_NOTIFY_ORIENT_RIGHT:
96 _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
98 case ELM_NOTIFY_ORIENT_TOP_LEFT:
99 _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
101 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
102 _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
104 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
105 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
107 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
108 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
110 case ELM_NOTIFY_ORIENT_LAST:
116 _block_events_theme_apply(Evas_Object *obj)
118 Widget_Data *wd = elm_widget_data_get(obj);
119 const char *style = elm_widget_style_get(obj);
120 _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
124 _theme_hook(Evas_Object *obj)
126 Widget_Data *wd = elm_widget_data_get(obj);
128 _notify_theme_apply(obj);
129 if (wd->block_events) _block_events_theme_apply(obj);
130 edje_object_scale_set(wd->notify, elm_widget_scale_get(obj) *
136 _sizing_eval(Evas_Object *obj)
138 Widget_Data *wd = elm_widget_data_get(obj);
141 if (!wd->parent) return;
142 evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
143 evas_object_move(obj, x, y);
144 evas_object_resize(obj, w, h);
148 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
154 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
156 Widget_Data *wd = elm_widget_data_get(obj);
157 Evas_Object *sub = event_info;
160 if (sub == wd->content)
162 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
163 _changed_size_hints, obj);
164 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
165 _content_resize, obj);
171 _signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
173 Widget_Data *wd = elm_widget_data_get(data);
175 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
179 _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
185 _content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
191 _calc(Evas_Object *obj)
193 Widget_Data *wd = elm_widget_data_get(obj);
194 Evas_Coord minw = -1, minh = -1;
195 Evas_Coord x, y, w, h;
198 evas_object_geometry_get(obj, &x, &y, &w, &h);
199 edje_object_size_min_get(wd->notify, &minw, &minh);
200 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
204 int offx = (w - minw) / 2;
205 int offy = (h - minh) / 2;
209 case ELM_NOTIFY_ORIENT_TOP:
210 evas_object_move(wd->notify, x + offx, y);
212 case ELM_NOTIFY_ORIENT_CENTER:
213 evas_object_move(wd->notify, x + offx, y + offy);
215 case ELM_NOTIFY_ORIENT_BOTTOM:
216 evas_object_move(wd->notify, x + offx, y + h - minh);
218 case ELM_NOTIFY_ORIENT_LEFT:
219 evas_object_move(wd->notify, x, y + offy);
221 case ELM_NOTIFY_ORIENT_RIGHT:
222 evas_object_move(wd->notify, x + w - minw, y + offy);
224 case ELM_NOTIFY_ORIENT_TOP_LEFT:
225 evas_object_move(wd->notify, x, y);
227 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
228 evas_object_move(wd->notify, x + w - minw, y);
230 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
231 evas_object_move(wd->notify, x, y + h - minh);
233 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
234 evas_object_move(wd->notify, x + w - minw, y + h - minh);
236 case ELM_NOTIFY_ORIENT_LAST:
239 evas_object_resize(wd->notify, minw, minh);
245 _timer_cb(void *data)
247 Evas_Object *obj = data;
248 Widget_Data *wd = elm_widget_data_get(obj);
249 if (!wd) return ECORE_CALLBACK_CANCEL;
251 evas_object_hide(obj);
252 evas_object_smart_callback_call(obj, SIG_TIMEOUT, NULL);
253 return ECORE_CALLBACK_CANCEL;
257 _timer_init(Evas_Object *obj, Widget_Data *wd)
261 ecore_timer_del(wd->timer);
264 if ((evas_object_visible_get(obj)) && (wd->timeout > 0.0))
265 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
269 _show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
271 Widget_Data *wd = elm_widget_data_get(obj);
273 evas_object_show(wd->notify);
274 if (!wd->repeat_events)
275 evas_object_show(wd->block_events);
276 _timer_init(obj, wd);
280 _hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
282 Widget_Data *wd = elm_widget_data_get(obj);
284 evas_object_hide(wd->notify);
285 if (!wd->repeat_events)
286 evas_object_hide(wd->block_events);
289 ecore_timer_del(wd->timer);
295 _parent_del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
297 Widget_Data *wd = elm_widget_data_get(obj);
300 evas_object_hide(obj);
304 _parent_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
306 Widget_Data *wd = elm_widget_data_get(obj);
309 evas_object_hide(obj);
313 * Add a new notify to the parent
315 * @param parent The parent object
316 * @return The new object or NULL if it cannot be created
321 elm_notify_add(Evas_Object *parent)
327 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
329 wd = ELM_NEW(Widget_Data);
330 e = evas_object_evas_get(parent);
332 obj = elm_widget_add(e);
333 ELM_SET_WIDTYPE(widtype, "notify");
334 elm_widget_type_set(obj, "notify");
335 elm_widget_sub_object_add(parent, obj);
336 elm_widget_data_set(obj, wd);
337 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
338 elm_widget_del_hook_set(obj, _del_hook);
339 elm_widget_theme_hook_set(obj, _theme_hook);
340 elm_widget_can_focus_set(obj, EINA_FALSE);
342 wd->repeat_events = EINA_TRUE;
344 wd->notify = edje_object_add(e);
346 elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
348 elm_notify_parent_set(obj, parent);
350 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
351 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
352 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
353 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
354 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
358 evas_object_smart_callbacks_descriptions_set(obj, _signals);
363 * Set the content of the notify widget
365 * Once the content object is set, a previously set one will be deleted.
366 * If you want to keep that old content object, use the
367 * elm_notify_content_unset() function.
369 * @param obj The notify object
370 * @param content The content will be filled in this notify object
375 elm_notify_content_set(Evas_Object *obj, Evas_Object *content)
377 ELM_CHECK_WIDTYPE(obj, widtype);
378 Widget_Data *wd = elm_widget_data_get(obj);
380 if (wd->content == content) return;
381 if (wd->content) evas_object_del(wd->content);
382 wd->content = content;
386 elm_widget_sub_object_add(obj, content);
387 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
388 _changed_size_hints, obj);
389 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
390 _content_resize, obj);
391 edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
398 * Unset the content of the notify widget
400 * Unparent and return the content object which was set for this widget
402 * @param obj The notify object
403 * @return The content that was being used
408 elm_notify_content_unset(Evas_Object *obj)
410 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
411 Widget_Data *wd = elm_widget_data_get(obj);
412 Evas_Object *content;
413 if (!wd) return NULL;
414 if (!wd->content) return NULL;
415 content = wd->content;
416 elm_widget_sub_object_del(obj, wd->content);
417 edje_object_part_unswallow(wd->notify, wd->content);
423 * Return the content of the notify widget
425 * @param obj The notify object
426 * @return The content that is being used
431 elm_notify_content_get(const Evas_Object *obj)
433 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
434 Widget_Data *wd = elm_widget_data_get(obj);
436 if (!wd) return NULL;
441 * Set the notify parent
443 * Once the parent object is set, a previously set one will be desconected
446 * @param obj The notify object
447 * @param content The new parent
452 elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
454 ELM_CHECK_WIDTYPE(obj, widtype);
455 Widget_Data *wd = elm_widget_data_get(obj);
459 evas_object_event_callback_del_full(wd->parent,
460 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
461 _changed_size_hints, obj);
462 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
463 _changed_size_hints, obj);
464 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
465 _changed_size_hints, obj);
466 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
468 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
476 evas_object_event_callback_add(parent,
477 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
478 _changed_size_hints, obj);
479 evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
480 _changed_size_hints, obj);
481 evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
482 _changed_size_hints, obj);
483 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
485 evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
487 edje_object_part_swallow(wd->notify, "elm.swallow.parent", parent);
494 * Get the notify parent
496 * @param obj The notify object
502 elm_notify_parent_get(const Evas_Object *obj)
504 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
505 Widget_Data *wd = elm_widget_data_get(obj);
506 if (!wd) return NULL;
511 * Set the orientation
513 * @param obj The notify object
514 * @param orient The new orientation
519 elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
521 ELM_CHECK_WIDTYPE(obj, widtype);
522 Widget_Data *wd = elm_widget_data_get(obj);
524 if (wd->orient == orient) return;
526 _notify_theme_apply(obj);
527 _resize(obj, NULL, obj, NULL);
531 * Return the orientation
532 * @param obj the notify objects
534 EAPI Elm_Notify_Orient
535 elm_notify_orient_get(const Evas_Object *obj)
537 ELM_CHECK_WIDTYPE(obj, widtype) -1;
538 Widget_Data *wd = elm_widget_data_get(obj);
544 * Set the time interval after which the notify window is going to be
547 * @param obj The notify object
548 * @param time The new timeout
550 * As said previously, an evas_object_show() on a notify object which
551 * had a timeout set by this function will trigger a timer to
552 * automatically hide it again. So, any order one calls
553 * elm_notify_timeout_set() and evas_object_show() on the same object
554 * (at hidden state) will behave the same.
556 * @note Set a value <= 0.0 to disable a running timer.
558 * @note If the value > 0.0 and the notify is previously visible, the
559 * timer will be started with this value, canceling any running timer.
563 elm_notify_timeout_set(Evas_Object *obj, double timeout)
565 ELM_CHECK_WIDTYPE(obj, widtype);
566 Widget_Data *wd = elm_widget_data_get(obj);
568 wd->timeout = timeout;
569 _timer_init(obj, wd);
573 * Return the timeout value (in seconds)
574 * @param obj the notify object
577 elm_notify_timeout_get(const Evas_Object *obj)
579 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
580 Widget_Data *wd = elm_widget_data_get(obj);
586 * When true if the user clicks outside the window the events will be
587 * catch by the others widgets, else the events are block and the signal
588 * dismiss will be sent when the user click outside the window.
590 * @note The default value is EINA_TRUE.
592 * @param obj The notify object
593 * @param repeats EINA_TRUE Events are repeats, else no
596 elm_notify_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
598 ELM_CHECK_WIDTYPE(obj, widtype);
599 Widget_Data *wd = elm_widget_data_get(obj);
601 if (repeat == wd->repeat_events) return;
602 wd->repeat_events = repeat;
605 wd->block_events = edje_object_add(evas_object_evas_get(obj));
606 _block_events_theme_apply(obj);
607 elm_widget_resize_object_set(obj, wd->block_events);
608 edje_object_signal_callback_add(wd->block_events, "elm,action,clicked",
609 "elm", _signal_block_clicked, obj);
612 evas_object_del(wd->block_events);
616 * Return true if events are repeat below the notify object
617 * @param obj the notify object
620 elm_notify_repeat_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->repeat_events;