2 # include "elementary_config.h"
5 #define ELM_INTERFACE_ATSPI_IMAGE_PROTECTED
6 #define ELM_INTERFACE_ATSPI_ACCESSIBLE_PROTECTED
7 #define ELM_INTERFACE_ATSPI_WIDGET_ACTION_PROTECTED
9 #include <Elementary.h>
12 #include "elm_widget_image.h"
14 #define FMT_SIZE_T "%zu"
16 #define MY_CLASS ELM_IMAGE_CLASS
17 #define MY_CLASS_NAME "Elm_Image"
18 #define MY_CLASS_NAME_LEGACY "elm_image"
20 static const char SIG_DND[] = "drop";
21 static const char SIG_CLICKED[] = "clicked";
22 static const char SIG_DOWNLOAD_START[] = "download,start";
23 static const char SIG_DOWNLOAD_PROGRESS[] = "download,progress";
24 static const char SIG_DOWNLOAD_DONE[] = "download,done";
25 static const char SIG_DOWNLOAD_ERROR[] = "download,error";
26 static const char SIG_LOAD_OPEN[] = "load,open";
27 static const char SIG_LOAD_READY[] = "load,ready";
28 static const char SIG_LOAD_ERROR[] = "load,error";
29 static const char SIG_LOAD_CANCEL[] = "load,cancel";
30 static const Evas_Smart_Cb_Description _smart_callbacks[] = {
33 {SIG_DOWNLOAD_START, ""},
34 {SIG_DOWNLOAD_PROGRESS, ""},
35 {SIG_DOWNLOAD_DONE, ""},
36 {SIG_DOWNLOAD_ERROR, ""},
37 {SIG_LOAD_OPEN, "Triggered when the file has been opened (image size is known)"},
38 {SIG_LOAD_READY, "Triggered when the image file is ready for display"},
39 {SIG_LOAD_ERROR, "Triggered whenener an I/O or decoding error occured"},
40 {SIG_LOAD_CANCEL, "Triggered whenener async I/O was cancelled"},
44 static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
45 static Eina_Bool _elm_image_smart_internal_file_set(Eo *obj, Elm_Image_Data *sd, const char *file, const Eina_File *f, const char *key);
47 static const Elm_Action key_actions[] = {
48 {"activate", _key_action_activate},
52 typedef struct _Async_Open_Data Async_Open_Data;
54 struct _Async_Open_Data {
56 Eina_Stringshare *file, *key;
57 Eina_File *f_set, *f_open;
62 _prev_img_del(Elm_Image_Data *sd)
64 elm_widget_sub_object_del(sd->self, sd->prev_img);
65 evas_object_smart_member_del(sd->prev_img);
66 evas_object_del(sd->prev_img);
71 _on_image_preloaded(void *data,
74 void *event EINA_UNUSED)
76 Elm_Image_Data *sd = data;
79 sd->preload_status = ELM_IMAGE_PRELOADED;
80 if (sd->show) evas_object_show(obj);
82 err = evas_object_image_load_error_get(obj);
83 if (!err) evas_object_smart_callback_call(sd->self, SIG_LOAD_READY, NULL);
84 else evas_object_smart_callback_call(sd->self, SIG_LOAD_ERROR, NULL);
88 _on_mouse_up(void *data,
90 Evas_Object *obj EINA_UNUSED,
93 ELM_WIDGET_DATA_GET_OR_RETURN(data, wd);
95 Evas_Event_Mouse_Up *ev = event_info;
97 if (ev->button != 1) return;
98 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
99 if (!wd->still_in) return;
101 eo_do(data, eo_event_callback_call(EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED, NULL));
105 _elm_image_animate_cb(void *data)
107 ELM_IMAGE_DATA_GET(data, sd);
109 if (!sd->anim) return ECORE_CALLBACK_CANCEL;
112 if ((sd->frame_count > 0) && (sd->cur_frame > sd->frame_count))
113 sd->cur_frame = sd->cur_frame % sd->frame_count;
115 evas_object_image_animated_frame_set(sd->img, sd->cur_frame);
117 sd->frame_duration = evas_object_image_animated_frame_duration_get
118 (sd->img, sd->cur_frame, 0);
120 if (sd->frame_duration > 0)
121 ecore_timer_interval_set(sd->anim_timer, sd->frame_duration);
123 return ECORE_CALLBACK_RENEW;
127 _img_new(Evas_Object *obj)
131 ELM_IMAGE_DATA_GET(obj, sd);
133 img = evas_object_image_add(evas_object_evas_get(obj));
134 evas_object_image_scale_hint_set(img, EVAS_IMAGE_SCALE_HINT_STATIC);
135 // TIZEN_ONLY(20161111): Preserve backward compatibility with Tizen 2.4.
136 evas_object_repeat_events_set(img, EINA_TRUE);
138 evas_object_event_callback_add
139 (img, EVAS_CALLBACK_IMAGE_PRELOADED, _on_image_preloaded, sd);
141 evas_object_smart_member_add(img, obj);
142 elm_widget_sub_object_add(obj, img);
148 _elm_image_internal_sizing_eval(Evas_Object *obj, Elm_Image_Data *sd)
150 Evas_Coord x, y, w, h;
152 if (!sd->img) return;
157 if (eo_isa(sd->img, EDJE_OBJECT_CLASS))
161 evas_object_move(sd->img, x, y);
162 evas_object_resize(sd->img, w, h);
166 double alignh = 0.5, alignv = 0.5;
167 int iw = 0, ih = 0, offset_w = 0, offset_h = 0;
168 evas_object_image_size_get(sd->img, &iw, &ih);
170 iw = ((double)iw) * sd->scale;
171 ih = ((double)ih) * sd->scale;
176 if (sd->aspect_fixed)
178 h = ((double)ih * w) / (double)iw;
184 w = ((double)iw * h) / (double)ih;
192 w = ((double)iw * h) / (double)ih;
201 if (!sd->resize_down)
207 evas_object_size_hint_align_get
208 (obj, &alignh, &alignv);
210 if (alignh == EVAS_HINT_FILL) alignh = 0.5;
211 if (alignv == EVAS_HINT_FILL) alignv = 0.5;
213 offset_w = ((sd->img_w - w) * alignh);
214 offset_h = ((sd->img_h - h) * alignv);
216 if (sd->aspect_fixed && !sd->fill_inside)
218 evas_object_image_fill_set(sd->img, offset_w, offset_h, w, h);
227 evas_object_image_fill_set(sd->img, 0, 0, w, h);
229 x = sd->img_x + offset_w;
230 y = sd->img_y + offset_h;
233 evas_object_move(sd->img, x, y);
234 evas_object_resize(sd->img, w, h);
236 evas_object_move(sd->hit_rect, x, y);
237 evas_object_resize(sd->hit_rect, w, h);
241 _async_open_data_free(Async_Open_Data *data)
244 eina_stringshare_del(data->file);
245 eina_stringshare_del(data->key);
246 if (data->map) eina_file_map_free(data->f_open, data->map);
247 if (data->f_open) eina_file_close(data->f_open);
248 if (data->f_set) eina_file_close(data->f_set);
253 _elm_image_async_open_do(void *data, Ecore_Thread *thread)
255 Async_Open_Data *todo = data;
260 if (ecore_thread_check(thread)) return;
262 if (todo->f_set) f = eina_file_dup(todo->f_set);
266 f = eina_file_open(todo->file, EINA_FALSE);
271 CRI("Async open has no input file!");
274 if (ecore_thread_check(thread))
276 if (!todo->f_set) eina_file_close(f);
280 // Read just enough data for map to actually do something.
281 size = eina_file_size_get(f);
282 // Read and ensure all pages are in memory for sure first just
283 // 1 byte per page will do. also keep a limit on how much we will
284 // blindly load in here to let's say 32KB (Should be enough to get
285 // image headers without getting to much data from the hard drive).
286 size = size > 32 * 1024 ? 32 * 1024 : size;
287 map = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
288 eina_file_map_populate(f, EINA_FILE_POPULATE, map, 0, size);
290 if (ecore_thread_check(thread))
292 if (map) eina_file_map_free(f, map);
293 if (!todo->f_set) eina_file_close(f);
301 _async_clear(Elm_Image_Data *sd)
304 sd->async.todo = NULL;
305 eina_stringshare_del(sd->async.file);
306 eina_stringshare_del(sd->async.key);
307 sd->async.file = NULL;
308 sd->async.key = NULL;
312 _async_cancel(Elm_Image_Data *sd)
316 ecore_thread_cancel(sd->async.th);
317 ((Async_Open_Data *)(sd->async.todo))->obj = NULL;
323 _elm_image_async_open_cancel(void *data, Ecore_Thread *thread)
325 Async_Open_Data *todo = data;
327 DBG("Async open thread was canceled");
330 ELM_IMAGE_DATA_GET(todo->obj, sd);
333 evas_object_smart_callback_call(todo->obj, SIG_LOAD_CANCEL, NULL);
334 if (thread == sd->async.th) _async_clear(sd);
337 _async_open_data_free(todo);
341 _elm_image_async_open_done(void *data, Ecore_Thread *thread)
343 Async_Open_Data *todo = data;
344 Eina_Stringshare *file, *key;
351 ELM_IMAGE_DATA_GET(todo->obj, sd);
354 if (thread == sd->async.th)
356 DBG("Async open succeeded");
362 if (todo->file) file = todo->file;
363 else file = f ? eina_file_filename_get(f) : NULL;
370 ok = edje_object_mmap_set(sd->img, f, key);
373 ok = _elm_image_smart_internal_file_set
374 (sd->self, sd, file, f, key);
376 if (ok) evas_object_smart_callback_call(sd->self, SIG_LOAD_OPEN, NULL);
377 else evas_object_smart_callback_call(sd->self, SIG_LOAD_ERROR, NULL);
381 // close f, map and free strings
382 _async_open_data_free(todo);
386 _elm_image_async_file_set(Eo *obj, Elm_Image_Data *sd, const char *file,
387 const Eina_File *f, const char *key)
389 Async_Open_Data *todo;
392 ((file == sd->async.file) ||
393 (file && sd->async.file && !strcmp(file, sd->async.file))) &&
394 ((key == sd->async.key) ||
395 (key && sd->async.key && !strcmp(key, sd->async.key))))
398 todo = calloc(1, sizeof(Async_Open_Data));
399 if (!todo) return EINA_FALSE;
404 todo->file = eina_stringshare_add(file);
405 todo->key = eina_stringshare_add(key);
406 todo->f_set = f ? eina_file_dup(f) : NULL;
408 eina_stringshare_replace(&sd->async.file, file);
409 eina_stringshare_replace(&sd->async.key, key);
411 sd->async.todo = todo;
412 sd->async.th = ecore_thread_run(_elm_image_async_open_do,
413 _elm_image_async_open_done,
414 _elm_image_async_open_cancel, todo);
415 if (sd->async.th) return EINA_TRUE;
417 _async_open_data_free(todo);
419 DBG("Could not spawn an async thread!");
424 _elm_image_edje_file_set(Evas_Object *obj,
431 ELM_IMAGE_DATA_GET(obj, sd);
437 pclip = evas_object_clip_get(sd->img);
438 evas_object_del(sd->img);
440 /* Edje object instead */
441 sd->img = edje_object_add(evas_object_evas_get(obj));
442 evas_object_smart_member_add(sd->img, obj);
443 if (sd->show) evas_object_show(sd->img);
444 evas_object_clip_set(sd->img, pclip);
449 sd->edje = EINA_TRUE;
450 if (!sd->async_enable)
454 if (!edje_object_mmap_set(sd->img, f, group))
456 ERR("failed to set edje file '%s', group '%s': %s", file, group,
457 edje_load_error_str(edje_object_load_error_get(sd->img)));
463 if (!edje_object_file_set(sd->img, file, group))
465 ERR("failed to set edje file '%s', group '%s': %s", file, group,
466 edje_load_error_str(edje_object_load_error_get(sd->img)));
472 return _elm_image_async_file_set(obj, sd, file, f, group);
474 /* FIXME: do i want to update icon on file change ? */
475 _elm_image_internal_sizing_eval(obj, sd);
481 _elm_image_efl_image_smooth_scale_set(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, Eina_Bool smooth)
483 if (sd->edje) return;
485 evas_object_image_smooth_scale_set(sd->img, smooth);
488 EOLIAN static Eina_Bool
489 _elm_image_efl_image_smooth_scale_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
491 if (sd->edje) return EINA_FALSE;
493 return evas_object_image_smooth_scale_get(sd->img);
497 _elm_image_fill_inside_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool fill_inside)
499 fill_inside = !!fill_inside;
501 if (sd->fill_inside == fill_inside) return;
503 sd->fill_inside = fill_inside;
505 _elm_image_internal_sizing_eval(obj, sd);
508 EOLIAN static Eina_Bool
509 _elm_image_fill_inside_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
511 return sd->fill_inside;
515 _elm_image_resize_up_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool resize_up)
517 resize_up = !!resize_up;
519 if (sd->resize_up == resize_up) return;
521 sd->resize_up = resize_up;
523 _elm_image_internal_sizing_eval(obj, sd);
526 EOLIAN static Eina_Bool
527 _elm_image_resize_up_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
529 return sd->resize_up;
533 _elm_image_resize_down_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool resize_down)
535 resize_down = !!resize_down;
537 if (sd->resize_down == resize_down) return;
539 sd->resize_down = resize_down;
541 _elm_image_internal_sizing_eval(obj, sd);
544 EOLIAN static Eina_Bool
545 _elm_image_resize_down_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
547 return sd->resize_up;
551 _elm_image_drag_n_drop_cb(void *elm_obj,
553 Elm_Selection_Data *drop)
555 Eina_Bool ret = EINA_FALSE;
556 eo_do(obj, ret = efl_file_set(drop->data, NULL));
559 DBG("dnd: %s, %s, %s", elm_widget_type_get(elm_obj),
560 SIG_DND, (char *)drop->data);
562 eo_do(elm_obj, eo_event_callback_call(ELM_IMAGE_EVENT_DROP, drop->data));
570 _elm_image_evas_object_smart_add(Eo *obj, Elm_Image_Data *priv)
572 eo_do_super(obj, MY_CLASS, evas_obj_smart_add());
573 elm_widget_sub_object_parent_add(obj);
575 priv->hit_rect = evas_object_rectangle_add(evas_object_evas_get(obj));
576 evas_object_smart_member_add(priv->hit_rect, obj);
577 elm_widget_sub_object_add(obj, priv->hit_rect);
579 evas_object_color_set(priv->hit_rect, 0, 0, 0, 0);
580 evas_object_show(priv->hit_rect);
581 evas_object_repeat_events_set(priv->hit_rect, EINA_TRUE);
583 evas_object_event_callback_add
584 (priv->hit_rect, EVAS_CALLBACK_MOUSE_UP, _on_mouse_up, obj);
586 /* starts as an Evas image. may switch to an Edje object */
587 priv->img = _img_new(obj);
589 priv->smooth = EINA_TRUE;
590 priv->fill_inside = EINA_TRUE;
591 priv->resize_up = EINA_TRUE;
592 priv->resize_down = EINA_TRUE;
593 priv->aspect_fixed = EINA_TRUE;
597 elm_widget_can_focus_set(obj, EINA_FALSE);
599 eo_do(obj, elm_obj_image_sizing_eval());
603 _elm_image_evas_object_smart_del(Eo *obj, Elm_Image_Data *sd)
605 ecore_timer_del(sd->anim_timer);
606 evas_object_del(sd->img);
607 evas_object_del(sd->prev_img);
608 if (sd->remote) _elm_url_cancel(sd->remote);
609 free(sd->remote_data);
610 eina_stringshare_del(sd->key);
612 eo_do_super(obj, MY_CLASS, evas_obj_smart_del());
616 _elm_image_evas_object_smart_move(Eo *obj, Elm_Image_Data *sd, Evas_Coord x, Evas_Coord y)
618 eo_do_super(obj, MY_CLASS, evas_obj_smart_move(x, y));
620 if ((sd->img_x == x) && (sd->img_y == y)) return;
624 /* takes care of moving */
625 _elm_image_internal_sizing_eval(obj, sd);
629 _elm_image_evas_object_smart_resize(Eo *obj, Elm_Image_Data *sd, Evas_Coord w, Evas_Coord h)
631 eo_do_super(obj, MY_CLASS, evas_obj_smart_resize(w, h));
633 if ((sd->img_w == w) && (sd->img_h == h)) return;
638 /* takes care of resizing */
639 _elm_image_internal_sizing_eval(obj, sd);
643 _elm_image_evas_object_smart_show(Eo *obj, Elm_Image_Data *sd)
645 sd->show = EINA_TRUE;
646 eo_do_super(obj, MY_CLASS, evas_obj_smart_show());
648 if (sd->preload_status == ELM_IMAGE_PRELOADING)
650 //TIZEN_ONLY(20170106): This code will be added in upstream
651 // after a related patch is applied in evas
652 evas_object_hide(sd->img);
657 evas_object_show(sd->img);
663 _elm_image_evas_object_smart_hide(Eo *obj, Elm_Image_Data *sd)
665 eo_do_super(obj, MY_CLASS, evas_obj_smart_hide());
667 sd->show = EINA_FALSE;
668 evas_object_hide(sd->img);
674 _elm_image_evas_object_smart_member_add(Eo *obj, Elm_Image_Data *sd, Evas_Object *member)
676 eo_do_super(obj, MY_CLASS, evas_obj_smart_member_add(member));
679 evas_object_raise(sd->hit_rect);
683 _elm_image_evas_object_smart_color_set(Eo *obj, Elm_Image_Data *sd, int r, int g, int b, int a)
685 eo_do_super(obj, MY_CLASS, evas_obj_smart_color_set(r, g, b, a));
687 evas_object_color_set(sd->hit_rect, 0, 0, 0, 0);
688 evas_object_color_set(sd->img, r, g, b, a);
689 if (sd->prev_img) evas_object_color_set(sd->prev_img, r, g, b, a);
693 _elm_image_evas_object_smart_clip_set(Eo *obj, Elm_Image_Data *sd, Evas_Object *clip)
695 eo_do_super(obj, MY_CLASS, evas_obj_smart_clip_set(clip));
697 evas_object_clip_set(sd->img, clip);
698 if (sd->prev_img) evas_object_clip_set(sd->prev_img, clip);
702 _elm_image_evas_object_smart_clip_unset(Eo *obj, Elm_Image_Data *sd)
704 eo_do_super(obj, MY_CLASS, evas_obj_smart_clip_unset());
706 evas_object_clip_unset(sd->img);
707 if (sd->prev_img) evas_object_clip_unset(sd->prev_img);
710 EOLIAN static Elm_Theme_Apply
711 _elm_image_elm_widget_theme_apply(Eo *obj, Elm_Image_Data *sd EINA_UNUSED)
713 Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED;
714 eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_theme_apply());
715 if (!int_ret) return ELM_THEME_APPLY_FAILED;
717 eo_do(obj, elm_obj_image_sizing_eval());
723 _key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
725 eo_do(obj, eo_event_callback_call(EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED, NULL));
729 EOLIAN static Eina_Bool
730 _elm_image_elm_widget_event(Eo *obj, Elm_Image_Data *_pd EINA_UNUSED, Evas_Object *src, Evas_Callback_Type type, void *event_info)
733 Evas_Event_Key_Down *ev = event_info;
735 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
736 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
738 if (!_elm_config_key_binding_call(obj, ev, key_actions))
741 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
746 _elm_image_sizing_eval(Eo *obj, Elm_Image_Data *sd)
748 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
752 _elm_image_internal_sizing_eval(obj, sd);
754 eo_do(obj, efl_image_smooth_scale_set(sd->smooth));
757 eo_do(obj, elm_obj_image_scale_set(1.0));
759 eo_do(obj, efl_image_smooth_scale_set(elm_widget_scale_get(obj) * elm_config_scale_get()));
763 eo_do(obj, elm_obj_image_object_size_get(&w, &h));
766 evas_object_size_hint_min_get(obj, &minw, &minh);
772 if ((sd->scale > 1.0) && (sd->resize_up))
774 maxw = minw = w * sd->scale;
775 maxh = minh = h * sd->scale;
777 else if ((sd->scale < 1.0) && (sd->resize_down))
779 maxw = minw = w * sd->scale;
780 maxh = minh = h * sd->scale;
785 if (!sd->resize_down)
787 minw = w * sd->scale;
788 minh = h * sd->scale;
792 maxw = w * sd->scale;
793 maxh = h * sd->scale;
797 evas_object_size_hint_min_set(obj, minw, minh);
798 evas_object_size_hint_max_set(obj, maxw, maxh);
802 _elm_image_file_set_do(Evas_Object *obj)
804 Evas_Object *pclip = NULL;
807 ELM_IMAGE_DATA_GET(obj, sd);
812 pclip = evas_object_clip_get(sd->img);
813 sd->prev_img = sd->img;
816 sd->img = _img_new(obj);
818 evas_object_image_load_orientation_set(sd->img, EINA_TRUE);
820 evas_object_clip_set(sd->img, pclip);
822 sd->edje = EINA_FALSE;
824 if (sd->load_size > 0)
825 evas_object_image_load_size_set(sd->img, sd->load_size, sd->load_size);
828 eo_do((Eo *) obj, elm_obj_image_object_size_get(&w, &h));
829 evas_object_image_load_size_set(sd->img, w, h);
833 EOLIAN static Eina_Bool
834 _elm_image_memfile_set(Eo *obj, Elm_Image_Data *sd, const void *img, size_t size, const char *format, const char *key)
836 EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
838 _elm_image_file_set_do(obj);
840 evas_object_image_memfile_set
841 (sd->img, (void *)img, size, (char *)format, (char *)key);
843 if (sd->preload_status == ELM_IMAGE_PRELOAD_DISABLED)
847 sd->preload_status = ELM_IMAGE_PRELOADING;
848 evas_object_image_preload(sd->img, EINA_FALSE);
851 if (evas_object_image_load_error_get(sd->img) != EVAS_LOAD_ERROR_NONE)
853 ERR("Things are going bad for some random " FMT_SIZE_T
854 " byte chunk of memory (%p)", size, sd->img);
860 _elm_image_internal_sizing_eval(obj, sd);
866 _elm_image_scale_set(Eo *obj, Elm_Image_Data *sd, double scale)
870 _elm_image_internal_sizing_eval(obj, sd);
874 _elm_image_scale_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
880 elm_image_add(Evas_Object *parent)
882 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
883 Evas_Object *obj = eo_add(MY_CLASS, parent);
888 _elm_image_eo_base_constructor(Eo *obj, Elm_Image_Data *pd)
890 obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor());
892 evas_obj_type_set(MY_CLASS_NAME_LEGACY),
893 evas_obj_smart_callbacks_descriptions_set(_smart_callbacks),
894 elm_interface_atspi_accessible_role_set(ELM_ATSPI_ROLE_IMAGE));
902 elm_image_file_set(Evas_Object *obj,
906 Eina_Bool ret = EINA_FALSE;
908 ELM_IMAGE_CHECK(obj) EINA_FALSE;
909 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
911 ret = efl_file_set(file, group);
912 elm_obj_image_sizing_eval());
917 elm_image_file_get(const Eo *obj, const char **file, const char **group)
919 eo_do((Eo *) obj, efl_file_get(file, group));
923 elm_image_mmap_set(Evas_Object *obj,
924 const Eina_File *file,
927 Eina_Bool ret = EINA_FALSE;
929 ELM_IMAGE_CHECK(obj) EINA_FALSE;
930 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
931 eo_do(obj, ret = efl_file_mmap_set(file, group));
936 _elm_image_efl_file_mmap_set(Eo *obj, Elm_Image_Data *pd EINA_UNUSED,
937 const Eina_File *file, const char *key)
939 Eina_Bool ret = EINA_FALSE;
941 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
943 ret = elm_obj_image_mmap_set(file, key),
944 elm_obj_image_sizing_eval());
950 _elm_image_smart_internal_file_set(Eo *obj, Elm_Image_Data *sd,
951 const char *file, const Eina_File *f, const char *key)
955 if (eina_str_has_extension(file, ".edj"))
956 return _elm_image_edje_file_set(obj, file, f, key);
958 _elm_image_file_set_do(obj);
961 evas_object_image_mmap_set(sd->img, f, key);
963 evas_object_image_file_set(sd->img, file, key);
965 err = evas_object_image_load_error_get(sd->img);
966 if (err != EVAS_LOAD_ERROR_NONE)
971 ERR("Failed to load image '%s' '%s': %s. (%p)",
972 file ? file : eina_file_filename_get(f), key,
973 evas_load_error_str(err), obj);
975 ERR("Failed to load image '%s': %s. (%p)",
976 file ? file : eina_file_filename_get(f),
977 evas_load_error_str(err), obj);
981 ERR("NULL image file passed! (%p)", obj);
987 if (sd->preload_status == ELM_IMAGE_PRELOAD_DISABLED)
991 evas_object_hide(sd->img);
992 sd->preload_status = ELM_IMAGE_PRELOADING;
993 evas_object_image_preload(sd->img, EINA_FALSE);
996 _elm_image_internal_sizing_eval(obj, sd);
1002 _elm_image_smart_download_done(void *data, Elm_Url *url, Eina_Binbuf *download)
1005 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1008 Eina_Bool ret = EINA_FALSE;
1010 free(sd->remote_data);
1011 length = eina_binbuf_length_get(download);
1012 sd->remote_data = eina_binbuf_string_steal(download);
1013 f = eina_file_virtualize(_elm_url_get(url),
1014 sd->remote_data, length,
1016 ret = _elm_image_smart_internal_file_set(obj, sd, _elm_url_get(url), f, sd->key);
1022 Elm_Image_Error err = { 0, EINA_TRUE };
1024 free(sd->remote_data);
1025 sd->remote_data = NULL;
1026 evas_object_smart_callback_call(obj, SIG_DOWNLOAD_ERROR, &err);
1030 if (sd->preload_status != ELM_IMAGE_PRELOAD_DISABLED)
1032 sd->preload_status = ELM_IMAGE_PRELOADING;
1033 evas_object_image_preload(sd->img, EINA_FALSE);
1036 evas_object_smart_callback_call(obj, SIG_DOWNLOAD_DONE, NULL);
1039 ELM_SAFE_FREE(sd->key, eina_stringshare_del);
1043 _elm_image_smart_download_cancel(void *data, Elm_Url *url EINA_UNUSED, int error)
1046 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1047 Elm_Image_Error err = { error, EINA_FALSE };
1049 evas_object_smart_callback_call(obj, SIG_DOWNLOAD_ERROR, &err);
1052 ELM_SAFE_FREE(sd->key, eina_stringshare_del);
1056 _elm_image_smart_download_progress(void *data, Elm_Url *url EINA_UNUSED, double now, double total)
1059 Elm_Image_Progress progress;
1062 progress.total = total;
1063 evas_object_smart_callback_call(obj, SIG_DOWNLOAD_PROGRESS, &progress);
1066 static const char *remote_uri[] = {
1067 "http://", "https://", "ftp://"
1070 EOLIAN static Eina_Bool
1071 _elm_image_efl_file_file_set(Eo *obj, Elm_Image_Data *sd, const char *file, const char *key)
1073 Eina_Bool ret = EINA_FALSE;
1076 if (sd->remote) _elm_url_cancel(sd->remote);
1079 for (i = 0; i < sizeof (remote_uri) / sizeof (remote_uri[0]); ++i)
1080 if (file && !strncmp(remote_uri[i], file, strlen(remote_uri[i])))
1082 // Found a remote target !
1083 evas_object_hide(sd->img);
1084 sd->remote = _elm_url_download(file,
1085 _elm_image_smart_download_done,
1086 _elm_image_smart_download_cancel,
1087 _elm_image_smart_download_progress,
1091 evas_object_smart_callback_call(obj, SIG_DOWNLOAD_START, NULL);
1092 eina_stringshare_replace(&sd->key, key);
1100 if (!sd->async_enable)
1101 ret = _elm_image_smart_internal_file_set(obj, sd, file, NULL, key);
1103 ret = _elm_image_async_file_set(obj, sd, file, NULL, key);
1109 _elm_image_edje_object_signal_emit(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, const char *emission, const char *source)
1112 edje_object_signal_emit(sd->img, emission, source);
1116 _elm_image_edje_object_size_min_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int *w, int *h)
1119 edje_object_size_min_get(sd->img, w, h);
1121 evas_object_size_hint_min_get(sd->img, w, h);
1125 _elm_image_edje_object_size_max_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int *w, int *h)
1128 edje_object_size_max_get(sd->img, w, h);
1130 evas_object_size_hint_max_get(sd->img, w, h);
1134 _elm_image_edje_object_calc_force(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1137 edje_object_calc_force(sd->img);
1141 _elm_image_edje_object_size_min_calc(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int *w, int *h)
1144 edje_object_size_min_calc(sd->img, w, h);
1146 evas_object_size_hint_min_get(sd->img, w, h);
1149 EOLIAN static Eina_Bool
1150 _elm_image_mmap_set(Eo *obj, Elm_Image_Data *sd, const Eina_File *f, const char *key)
1154 if (sd->remote) _elm_url_cancel(sd->remote);
1159 if (!sd->async_enable)
1160 ret = _elm_image_smart_internal_file_set(obj, sd, eina_file_filename_get(f), f, key);
1162 ret = _elm_image_async_file_set(obj, sd, eina_file_filename_get(f), f, key);
1168 _elm_image_efl_file_file_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, const char **file, const char **key)
1172 if (file) *file = sd->async.file;
1173 if (key) *key = sd->async.key;
1176 evas_object_image_file_get(sd->img, file, key);
1180 _elm_image_smooth_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool smooth)
1182 sd->smooth = smooth;
1184 eo_do(obj, elm_obj_image_sizing_eval());
1187 EOLIAN static Eina_Bool
1188 _elm_image_smooth_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1194 // Kept for reference: wait for async open to complete - probably unused.
1196 _elm_image_efl_file_async_wait(const Eo *obj EINA_UNUSED, Elm_Image_Data *pd)
1198 Eina_Bool ok = EINA_TRUE;
1199 if (!pd->async_enable) return ok;
1200 if (!pd->async.th) return ok;
1201 if (!ecore_thread_wait(pd->async.th, 1.0))
1203 ERR("Failed to wait on async file open!");
1210 /* Legacy style async API. While legacy only, this is new from 1.19.
1211 * Tizen has used elm_image_async_open_set() internally for a while, despite
1212 * EFL upstream not exposing a proper async API. */
1215 elm_image_async_open_set(Eo *obj, Eina_Bool async)
1217 Elm_Image_Data *pd = eo_data_scope_get(obj, MY_CLASS);
1218 if (pd->async_enable == async) return;
1219 pd->async_enable = async;
1220 if (!async) _async_cancel(pd);
1224 _elm_image_object_size_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int *w, int *h)
1232 if (eo_isa(sd->img, EDJE_OBJECT_CLASS))
1233 edje_object_size_min_get(sd->img, &tw, &th);
1235 evas_object_image_size_get(sd->img, &tw, &th);
1237 if ((sd->resize_up) || (sd->resize_down))
1238 evas_object_geometry_get(sd->img, NULL, NULL, &cw, &ch);
1240 tw = tw > cw ? tw : cw;
1241 th = th > ch ? th : ch;
1242 tw = ((double)tw) * sd->scale;
1243 th = ((double)th) * sd->scale;
1249 _elm_image_no_scale_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool no_scale)
1251 sd->no_scale = no_scale;
1253 eo_do(obj, elm_obj_image_sizing_eval());
1256 EOLIAN static Eina_Bool
1257 _elm_image_no_scale_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1259 return sd->no_scale;
1263 _elm_image_resizable_set(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, Eina_Bool up, Eina_Bool down)
1265 sd->resize_up = !!up;
1266 sd->resize_down = !!down;
1268 eo_do(obj, elm_obj_image_sizing_eval());
1272 _elm_image_resizable_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, Eina_Bool *size_up, Eina_Bool *size_down)
1274 if (size_up) *size_up = sd->resize_up;
1275 if (size_down) *size_down = sd->resize_down;
1279 _elm_image_fill_outside_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool fill_outside)
1281 sd->fill_inside = !fill_outside;
1283 eo_do(obj, elm_obj_image_sizing_eval());
1286 EOLIAN static Eina_Bool
1287 _elm_image_fill_outside_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1289 return !sd->fill_inside;
1292 // TODO: merge preload and async code
1294 _elm_image_preload_disabled_set(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, Eina_Bool disable)
1296 if (sd->edje || !sd->img) return;
1300 if (sd->preload_status == ELM_IMAGE_PRELOADING)
1302 evas_object_image_preload(sd->img, disable);
1303 if (sd->show) evas_object_show(sd->img);
1306 sd->preload_status = ELM_IMAGE_PRELOAD_DISABLED;
1308 else if (sd->preload_status == ELM_IMAGE_PRELOAD_DISABLED)
1310 sd->preload_status = ELM_IMAGE_PRELOADING;
1311 evas_object_image_preload(sd->img, disable);
1316 elm_image_prescale_set(Evas_Object *obj,
1319 ELM_IMAGE_CHECK(obj);
1320 eo_do(obj, efl_image_load_size_set(size, size));
1324 _elm_image_efl_image_load_size_set(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int w, int h)
1333 elm_image_prescale_get(const Evas_Object *obj)
1335 ELM_IMAGE_CHECK(obj) 0;
1338 eo_do((Eo *)obj, efl_image_load_size_get(&w, NULL));
1343 _elm_image_efl_image_load_size_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd, int *w, int *h)
1345 if (w) *w = sd->load_size;
1346 if (h) *h = sd->load_size;
1350 _elm_image_orient_set(Eo *obj, Elm_Image_Data *sd, Elm_Image_Orient orient)
1352 if (sd->edje) return;
1353 if (sd->orient == orient) return;
1355 evas_object_image_orient_set(sd->img, orient);
1356 sd->orient = orient;
1357 _elm_image_internal_sizing_eval(obj, sd);
1360 EOLIAN static Elm_Image_Orient
1361 _elm_image_orient_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1367 * Turns on editing through drag and drop and copy and paste.
1370 _elm_image_editable_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool edit)
1374 WRN("No editing edje objects yet (ever)\n");
1380 if (edit == sd->edit) return;
1386 (obj, ELM_SEL_FORMAT_IMAGE,
1390 _elm_image_drag_n_drop_cb, obj);
1393 (obj, ELM_SEL_FORMAT_IMAGE,
1397 _elm_image_drag_n_drop_cb, obj);
1400 EOLIAN static Eina_Bool
1401 _elm_image_editable_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1406 EOLIAN static Evas_Object*
1407 _elm_image_object_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1413 _elm_image_aspect_fixed_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool fixed)
1416 if (sd->aspect_fixed == fixed) return;
1418 sd->aspect_fixed = fixed;
1420 _elm_image_internal_sizing_eval(obj, sd);
1423 EOLIAN static Eina_Bool
1424 _elm_image_aspect_fixed_get(Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1426 return sd->aspect_fixed;
1430 elm_image_animated_available_get(const Evas_Object *obj)
1433 eo_do(obj, ret = efl_player_playable_get());
1437 EOLIAN static Eina_Bool
1438 _elm_image_efl_player_playable_get(Eo *obj, Elm_Image_Data *sd)
1440 if (sd->edje) return EINA_FALSE;
1442 return evas_object_image_animated_get(elm_image_object_get(obj));
1446 _elm_image_animated_set_internal(Eo *obj, Elm_Image_Data *sd, Eina_Bool anim)
1449 if (sd->anim == anim) return;
1455 edje_object_animation_set(sd->img, anim);
1458 sd->img = elm_image_object_get(obj);
1459 if (!evas_object_image_animated_get(sd->img)) return;
1463 sd->frame_count = evas_object_image_animated_frame_count_get(sd->img);
1465 sd->frame_duration =
1466 evas_object_image_animated_frame_duration_get
1467 (sd->img, sd->cur_frame, 0);
1468 evas_object_image_animated_frame_set(sd->img, sd->cur_frame);
1472 sd->frame_count = -1;
1474 sd->frame_duration = -1;
1481 _elm_image_animated_get_internal(const Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1484 return edje_object_animation_get(sd->img);
1489 elm_image_animated_set(Evas_Object *obj, Eina_Bool anim)
1491 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1493 _elm_image_animated_set_internal(obj, sd, anim);
1497 elm_image_animated_get(const Evas_Object *obj)
1499 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1500 if (!sd) return EINA_FALSE;
1501 return _elm_image_animated_get_internal(obj, sd);
1505 _elm_image_animated_play_set_internal(Eo *obj, Elm_Image_Data *sd, Eina_Bool play)
1507 if (!sd->anim) return;
1508 if (sd->play == play) return;
1512 edje_object_play_set(sd->img, play);
1517 sd->anim_timer = ecore_timer_add
1518 (sd->frame_duration, _elm_image_animate_cb, obj);
1522 ELM_SAFE_FREE(sd->anim_timer, ecore_timer_del);
1527 _elm_image_animated_play_get_internal(const Eo *obj EINA_UNUSED, Elm_Image_Data *sd)
1530 return edje_object_play_get(sd->img);
1535 elm_image_animated_play_set(Elm_Image *obj, Eina_Bool play)
1537 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1539 _elm_image_animated_play_set_internal(obj, sd, play);
1543 elm_image_animated_play_get(const Elm_Image *obj)
1545 Elm_Image_Data *sd = eo_data_scope_get(obj, MY_CLASS);
1546 if (!sd) return EINA_FALSE;
1547 return _elm_image_animated_play_get_internal(obj, sd);
1551 _elm_image_efl_player_play_set(Eo *obj, Elm_Image_Data *sd, Eina_Bool play)
1553 if (play && !_elm_image_animated_get_internal(obj, sd))
1554 _elm_image_animated_set_internal(obj, sd, play);
1555 _elm_image_animated_play_set_internal(obj, sd, play);
1558 EOLIAN static Eina_Bool
1559 _elm_image_efl_player_play_get(Eo *obj, Elm_Image_Data *sd)
1561 return _elm_image_animated_play_get_internal(obj, sd);
1565 _elm_image_class_constructor(Eo_Class *klass)
1567 evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
1573 _elm_image_elm_interface_atspi_image_extents_get(Eo *obj, Elm_Image_Data *sd EINA_UNUSED, Eina_Bool screen_coords, int *x, int *y, int *w, int *h)
1576 Evas_Object *image = elm_image_object_get(obj);
1579 evas_object_geometry_get(image, x, y, NULL, NULL);
1582 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(image));
1584 ecore_evas_geometry_get(ee, &ee_x, &ee_y, NULL, NULL);
1588 elm_image_object_size_get(obj, w, h);
1591 EOLIAN const Elm_Atspi_Action *
1592 _elm_image_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNUSED, Elm_Image_Data *pd EINA_UNUSED)
1594 static Elm_Atspi_Action atspi_actions[] = {
1595 { "activate", "activate", NULL, _key_action_activate },
1596 { NULL, NULL, NULL, NULL },
1598 return &atspi_actions[0];
1604 #include "elm_image.eo.c"