diff --git a/legacy/elementary/src/lib/elm_thumb.c b/legacy/elementary/src/lib/elm_thumb.c index baba610d94..af5369378f 100644 --- a/legacy/elementary/src/lib/elm_thumb.c +++ b/legacy/elementary/src/lib/elm_thumb.c @@ -1,39 +1,46 @@ #include #include "elm_priv.h" -#include +#include "elm_widget_layout.h" -typedef struct _Widget_Data Widget_Data; +static const char THUMB_SMART_NAME[] = "elm_thumb"; -struct _Widget_Data +typedef struct _Elm_Thumb_Smart_Data Elm_Thumb_Smart_Data; + +struct _Elm_Thumb_Smart_Data { - Evas_Object *self; - Evas_Object *frame; - Evas_Object *view; - const char *file; - const char *key; + Elm_Layout_Smart_Data base; + + Evas_Object *view; /* actual thumbnail, to be swallowed + * at the thumb frame */ + + /* original object's file/key pair */ + const char *file; + const char *key; + struct - { - const char *file; - const char *key; + { + /* object's thumbnail file/key pair */ + const char *file; + const char *key; #ifdef HAVE_ELEMENTARY_ETHUMB - const char *thumb_path; - const char *thumb_key; - Ethumb_Client_Async *request; + const char *thumb_path; + const char *thumb_key; + Ethumb_Client_Async *request; - Ethumb_Thumb_Format format; + Ethumb_Thumb_Format format; - Eina_Bool retry : 1; + Eina_Bool retry : 1; #endif - } thumb; - Ecore_Event_Handler *eeh; - Elm_Thumb_Animation_Setting anim_setting; - Eina_Bool on_hold : 1; - Eina_Bool is_video : 1; - Eina_Bool was_video : 1; - Eina_Bool edit : 1; -}; + } thumb; -static const char *widtype = NULL; + Ecore_Event_Handler *eeh; + Elm_Thumb_Animation_Setting anim_setting; + + Eina_Bool edit : 1; + Eina_Bool on_hold : 1; + Eina_Bool is_video : 1; + Eina_Bool was_video : 1; +}; static const char SIG_CLICKED[] = "clicked"; static const char SIG_CLICKED_DOUBLE[] = "clicked,double"; @@ -42,28 +49,28 @@ static const char SIG_GENERATE_START[] = "generate,start"; static const char SIG_GENERATE_STOP[] = "generate,stop"; static const char SIG_LOAD_ERROR[] = "load,error"; static const char SIG_PRESS[] = "press"; - -static const Evas_Smart_Cb_Description _signals[] = +static const Evas_Smart_Cb_Description _smart_callbacks[] = { - {SIG_CLICKED, ""}, - {SIG_CLICKED_DOUBLE, ""}, - {SIG_GENERATE_ERROR, ""}, - {SIG_GENERATE_START, ""}, - {SIG_GENERATE_STOP, ""}, - {SIG_LOAD_ERROR, ""}, - {SIG_PRESS, ""}, - {NULL, NULL} + {SIG_CLICKED, ""}, + {SIG_CLICKED_DOUBLE, ""}, + {SIG_GENERATE_ERROR, ""}, + {SIG_GENERATE_START, ""}, + {SIG_GENERATE_STOP, ""}, + {SIG_LOAD_ERROR, ""}, + {SIG_PRESS, ""}, + {NULL, NULL} }; #define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start" -#define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop" +#define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop" #define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error" -#define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error" -#define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start" -#define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop" +#define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error" +#define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start" +#define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop" + +static struct _Ethumb_Client *_elm_ethumb_client = NULL; +static Eina_Bool _elm_ethumb_connected = EINA_FALSE; -struct _Ethumb_Client *_elm_ethumb_client = NULL; -Eina_Bool _elm_ethumb_connected = EINA_FALSE; #ifdef HAVE_ELEMENTARY_ETHUMB static Eina_List *retry = NULL; static int pending_request = 0; @@ -71,401 +78,449 @@ static int pending_request = 0; EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0; -static void -_del_hook(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); +#define ELM_THUMB_DATA_GET(o, sd) \ + Elm_Thumb_Smart_Data * sd = evas_object_smart_data_get(o) -#ifdef HAVE_ELEMENTARY_ETHUMB - if (wd->thumb.request) - { - ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request); - wd->thumb.request = NULL; - } - if (wd->thumb.retry) - { - retry = eina_list_remove(retry, wd); - wd->thumb.retry = EINA_FALSE; - } +#define ELM_THUMB_DATA_GET_OR_RETURN(o, ptr) \ + ELM_THUMB_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return; \ + } - eina_stringshare_del(wd->thumb.thumb_path); - eina_stringshare_del(wd->thumb.thumb_key); -#endif +#define ELM_THUMB_DATA_GET_OR_RETURN_VAL(o, ptr, val) \ + ELM_THUMB_DATA_GET(o, ptr); \ + if (!ptr) \ + { \ + CRITICAL("No widget data for object %p (%s)", \ + o, evas_object_type_get(o)); \ + return val; \ + } - eina_stringshare_del(wd->file); - eina_stringshare_del(wd->key); - if (wd->eeh) ecore_event_handler_del(wd->eeh); - free(wd); -} +#define ELM_THUMB_CHECK(obj) \ + if (!obj || !elm_widget_type_check((obj), THUMB_SMART_NAME, __func__)) \ + return -static void -_theme_hook(Evas_Object *obj) -{ - Widget_Data *wd = elm_widget_data_get(obj); - _elm_theme_object_set(obj, wd->frame, "thumb", "base", - elm_widget_style_get(obj)); -} +/* Inheriting from elm_layout. Besides, we need no more than what is + * there */ +EVAS_SMART_SUBCLASS_NEW + (THUMB_SMART_NAME, _elm_thumb, Elm_Layout_Smart_Class, + Elm_Layout_Smart_Class, elm_layout_smart_class_get, _smart_callbacks); #ifdef HAVE_ELEMENTARY_ETHUMB static void -_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_mouse_down_cb(void *data, + Evas *e __UNUSED__, + Evas_Object *obj, + void *event_info) { - Widget_Data *wd = data; + Elm_Thumb_Smart_Data *sd = data; Evas_Event_Mouse_Down *ev = event_info; if (ev->button != 1) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) - wd->on_hold = EINA_TRUE; + sd->on_hold = EINA_TRUE; else - wd->on_hold = EINA_FALSE; + sd->on_hold = EINA_FALSE; if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK) - evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL); + evas_object_smart_callback_call(obj, SIG_CLICKED_DOUBLE, NULL); else - evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL); + evas_object_smart_callback_call(obj, SIG_PRESS, NULL); } static void -_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info) +_mouse_up_cb(void *data, + Evas *e __UNUSED__, + Evas_Object *obj, + void *event_info) { - Widget_Data *wd = data; + Elm_Thumb_Smart_Data *sd = data; Evas_Event_Mouse_Up *ev = event_info; if (ev->button != 1) return; if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) - wd->on_hold = EINA_TRUE; + sd->on_hold = EINA_TRUE; else - wd->on_hold = EINA_FALSE; - if (!wd->on_hold) - evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL); - wd->on_hold = EINA_FALSE; + sd->on_hold = EINA_FALSE; + if (!sd->on_hold) + evas_object_smart_callback_call(obj, SIG_CLICKED, NULL); + + sd->on_hold = EINA_FALSE; } static void -_thumb_ready(Widget_Data *wd, const char *thumb_path, const char *thumb_key) +_thumb_ready_inform(Elm_Thumb_Smart_Data *sd, + const char *thumb_path, + const char *thumb_key) { Evas_Coord mw, mh; Evas_Coord aw, ah; - evas_object_image_size_get(wd->view, &aw, &ah); - evas_object_size_hint_aspect_set(wd->view, - EVAS_ASPECT_CONTROL_BOTH, - aw, ah); - edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view); - edje_object_size_min_get(wd->frame, &mw, &mh); - edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh); - evas_object_size_hint_min_set(wd->self, mw, mh); - eina_stringshare_replace(&(wd->thumb.file), thumb_path); - eina_stringshare_replace(&(wd->thumb.key), thumb_key); - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm"); - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm"); - evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL); + evas_object_image_size_get(sd->view, &aw, &ah); + evas_object_size_hint_aspect_set + (sd->view, EVAS_ASPECT_CONTROL_BOTH, aw, ah); + elm_layout_content_set + (ELM_WIDGET_DATA(sd)->obj, "elm.swallow.content", sd->view); + edje_object_size_min_get(ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh); + edje_object_size_min_restricted_calc + (ELM_WIDGET_DATA(sd)->resize_obj, &mw, &mh, mw, mh); + evas_object_size_hint_min_set(ELM_WIDGET_DATA(sd)->obj, mw, mh); + eina_stringshare_replace(&(sd->thumb.file), thumb_path); + eina_stringshare_replace(&(sd->thumb.key), thumb_key); + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_PULSE_STOP, "elm"); + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_GENERATE_STOP, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_STOP, NULL); } static void -_thumb_loaded(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +_on_thumb_preloaded(void *data, + Evas *e __UNUSED__, + Evas_Object *obj __UNUSED__, + void *event_info __UNUSED__) { - Widget_Data *wd = data; + Elm_Thumb_Smart_Data *sd = data; const char *thumb_path; const char *thumb_key; - evas_object_image_file_get(wd->view, &thumb_path, &thumb_key); + evas_object_image_file_get(sd->view, &thumb_path, &thumb_key); - _thumb_ready(wd, thumb_path, thumb_key); + _thumb_ready_inform(sd, thumb_path, thumb_key); } -/* As we do use stat to check if a thumbnail is available, it's possible - that we end up accessing before the file is completly written on disk. - By retrying each time a thumbnail is finished we should be fine or not. -*/ +/* As we do use stat to check if a thumbnail is available, it's + * possible that we end up accessing it before the file is completly + * written on disk. By retrying each time a thumbnail is finished we + * should be fine or not. + */ static Eina_Bool -_retry_thumb(Widget_Data *wd) +_thumb_retry(Elm_Thumb_Smart_Data *sd) { int r; - if ((wd->is_video) && (wd->thumb.format == ETHUMB_THUMB_EET)) + if ((sd->is_video) && (sd->thumb.format == ETHUMB_THUMB_EET)) { - edje_object_file_set(wd->view, NULL, NULL); - if (!edje_object_file_set(wd->view, - wd->thumb.thumb_path, - "movie/thumb")) + edje_object_file_set(sd->view, NULL, NULL); + if (!edje_object_file_set + (sd->view, sd->thumb.thumb_path, "movie/thumb")) { if (pending_request == 0) ERR("could not set file=%s key=%s for %s", - wd->thumb.thumb_path, - wd->thumb.thumb_key, - wd->file); + sd->thumb.thumb_path, + sd->thumb.thumb_key, + sd->file); goto view_err; } - /* FIXME: Do we want to reload a thumbnail when the file change ? I think no at the moment as - this may increase the presure on the system a lot when using it in a file browser */ + /* FIXME: Do we want to reload a thumbnail when the file + changes? I think not at the moment, as this may increase + the presure on the system a lot when using it in a file + browser */ } else { - evas_object_image_file_set(wd->view, NULL, NULL); - evas_object_image_file_set(wd->view, - wd->thumb.thumb_path, - wd->thumb.thumb_key); - r = evas_object_image_load_error_get(wd->view); + evas_object_image_file_set(sd->view, NULL, NULL); + evas_object_image_file_set + (sd->view, sd->thumb.thumb_path, sd->thumb.thumb_key); + r = evas_object_image_load_error_get(sd->view); if (r != EVAS_LOAD_ERROR_NONE) { if (pending_request == 0) - ERR("%s: %s", wd->thumb.thumb_path, evas_load_error_str(r)); + ERR("%s: %s", sd->thumb.thumb_path, evas_load_error_str(r)); goto view_err; } - evas_object_event_callback_add(wd->view, - EVAS_CALLBACK_IMAGE_PRELOADED, - _thumb_loaded, wd); - evas_object_image_preload(wd->view, EINA_TRUE); + evas_object_event_callback_add + (sd->view, EVAS_CALLBACK_IMAGE_PRELOADED, _on_thumb_preloaded, sd); + evas_object_image_preload(sd->view, EINA_TRUE); + return EINA_TRUE; } - _thumb_ready(wd, wd->thumb.thumb_path, wd->thumb.thumb_key); + _thumb_ready_inform(sd, sd->thumb.thumb_path, sd->thumb.thumb_key); - eina_stringshare_del(wd->thumb.thumb_path); - wd->thumb.thumb_path = NULL; + eina_stringshare_del(sd->thumb.thumb_path); + sd->thumb.thumb_path = NULL; - eina_stringshare_del(wd->thumb.thumb_key); - wd->thumb.thumb_key = NULL; + eina_stringshare_del(sd->thumb.thumb_key); + sd->thumb.thumb_key = NULL; return EINA_TRUE; - view_err: +view_err: return EINA_FALSE; } static void -_finished_thumb(Widget_Data *wd, - const char *thumb_path, - const char *thumb_key) +_thumb_finish(Elm_Thumb_Smart_Data *sd, + const char *thumb_path, + const char *thumb_key) { Eina_List *l, *ll; Evas *evas; int r; - evas = evas_object_evas_get(wd->self); - if ((wd->view) && (wd->is_video ^ wd->was_video)) + evas = evas_object_evas_get(ELM_WIDGET_DATA(sd)->obj); + if ((sd->view) && (sd->is_video ^ sd->was_video)) { - evas_object_del(wd->view); - wd->view = NULL; + evas_object_del(sd->view); + sd->view = NULL; } - wd->was_video = wd->is_video; + sd->was_video = sd->is_video; - if ((wd->is_video) && + if ((sd->is_video) && (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET)) { - if (!wd->view) + if (!sd->view) { - wd->view = edje_object_add(evas); - if (!wd->view) + sd->view = edje_object_add(evas); + if (!sd->view) { ERR("could not create edje object"); goto err; } - elm_widget_sub_object_add(wd->self, wd->view); } - if (!edje_object_file_set(wd->view, thumb_path, thumb_key)) + if (!edje_object_file_set(sd->view, thumb_path, thumb_key)) { - wd->thumb.thumb_path = eina_stringshare_ref(thumb_path); - wd->thumb.thumb_key = eina_stringshare_ref(thumb_key); - wd->thumb.format = ethumb_client_format_get(_elm_ethumb_client); - wd->thumb.retry = EINA_TRUE; + sd->thumb.thumb_path = eina_stringshare_ref(thumb_path); + sd->thumb.thumb_key = eina_stringshare_ref(thumb_key); + sd->thumb.format = ethumb_client_format_get(_elm_ethumb_client); + sd->thumb.retry = EINA_TRUE; - retry = eina_list_append(retry, wd); - return ; + retry = eina_list_append(retry, sd); + return; } } else { - if (!wd->view) + if (!sd->view) { - wd->view = evas_object_image_filled_add(evas); - if (!wd->view) + sd->view = evas_object_image_filled_add(evas); + if (!sd->view) { ERR("could not create image object"); goto err; } - evas_object_event_callback_add(wd->view, - EVAS_CALLBACK_IMAGE_PRELOADED, - _thumb_loaded, wd); - elm_widget_sub_object_add(wd->self, wd->view); - evas_object_hide(wd->view); + evas_object_event_callback_add + (sd->view, EVAS_CALLBACK_IMAGE_PRELOADED, _on_thumb_preloaded, + sd); + evas_object_hide(sd->view); } - evas_object_image_file_set(wd->view, thumb_path, thumb_key); - r = evas_object_image_load_error_get(wd->view); + evas_object_image_file_set(sd->view, thumb_path, thumb_key); + r = evas_object_image_load_error_get(sd->view); if (r != EVAS_LOAD_ERROR_NONE) { WRN("%s: %s", thumb_path, evas_load_error_str(r)); - wd->thumb.thumb_path = eina_stringshare_ref(thumb_path); - wd->thumb.thumb_key = eina_stringshare_ref(thumb_key); - wd->thumb.format = ethumb_client_format_get(_elm_ethumb_client); - wd->thumb.retry = EINA_TRUE; + sd->thumb.thumb_path = eina_stringshare_ref(thumb_path); + sd->thumb.thumb_key = eina_stringshare_ref(thumb_key); + sd->thumb.format = ethumb_client_format_get(_elm_ethumb_client); + sd->thumb.retry = EINA_TRUE; - retry = eina_list_append(retry, wd); - return ; + retry = eina_list_append(retry, sd); + return; } - evas_object_image_preload(wd->view, 0); - return ; + evas_object_image_preload(sd->view, EINA_FALSE); + return; } - _thumb_ready(wd, thumb_path, thumb_key); + _thumb_ready_inform(sd, thumb_path, thumb_key); - EINA_LIST_FOREACH_SAFE(retry, l, ll, wd) - if (_retry_thumb(wd)) - retry = eina_list_remove_list(retry, l); + EINA_LIST_FOREACH_SAFE (retry, l, ll, sd) + { + if (_thumb_retry(sd)) + retry = eina_list_remove_list(retry, l); + } if (pending_request == 0) - EINA_LIST_FREE(retry, wd) + EINA_LIST_FREE (retry, sd) { - eina_stringshare_del(wd->thumb.thumb_path); - wd->thumb.thumb_path = NULL; + eina_stringshare_del(sd->thumb.thumb_path); + sd->thumb.thumb_path = NULL; - eina_stringshare_del(wd->thumb.thumb_key); - wd->thumb.thumb_key = NULL; + eina_stringshare_del(sd->thumb.thumb_key); + sd->thumb.thumb_key = NULL; - evas_object_del(wd->view); - wd->view = NULL; + evas_object_del(sd->view); + sd->view = NULL; - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm"); - evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL); + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_LOAD_ERROR, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_LOAD_ERROR, NULL); } return; err: - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm"); - evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL); + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_LOAD_ERROR, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_LOAD_ERROR, NULL); } static void -_elm_thumb_done(Ethumb_Client *client __UNUSED__, const char *thumb_path, const char *thumb_key, void *data) +_on_ethumb_thumb_done(Ethumb_Client *client __UNUSED__, + const char *thumb_path, + const char *thumb_key, + void *data) { - Widget_Data *wd = data; + Elm_Thumb_Smart_Data *sd = data; - assert(wd->thumb.request); - - pending_request--; - wd->thumb.request = NULL; - - _finished_thumb(wd, thumb_path, thumb_key); -} - -static void -_elm_thumb_error(Ethumb_Client *client __UNUSED__, void *data) -{ - Widget_Data *wd = data; - - assert(wd->thumb.request); - - pending_request--; - wd->thumb.request = NULL; - - ERR("could not generate thumbnail for %s (key: %s)", wd->thumb.file, wd->thumb.key ? wd->thumb.key : ""); - - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm"); - evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL); -} - -static void -_thumb_apply(Widget_Data *wd) -{ - if (wd->thumb.request) + if (EINA_UNLIKELY(!sd->thumb.request)) { - ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request); - wd->thumb.request = NULL; - } - if (wd->thumb.retry) - { - retry = eina_list_remove(retry, wd); - wd->thumb.retry = EINA_FALSE; + ERR("Something odd happened with a thumbnail request"); + return; } - if (!wd->file) return; + pending_request--; + sd->thumb.request = NULL; - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START, "elm"); - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START, "elm"); - evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL); + _thumb_finish(sd, thumb_path, thumb_key); +} + +static void +_on_ethumb_thumb_error(Ethumb_Client *client __UNUSED__, + void *data) +{ + Elm_Thumb_Smart_Data *sd = data; + + if (EINA_UNLIKELY(!sd->thumb.request)) + { + ERR("Something odd happened with a thumbnail request"); + return; + } + + pending_request--; + sd->thumb.request = NULL; + + ERR("could not generate thumbnail for %s (key: %s)", + sd->thumb.file, sd->thumb.key ? sd->thumb.key : ""); + + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_GENERATE_ERROR, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_ERROR, NULL); +} + +static void +_thumb_start(Elm_Thumb_Smart_Data *sd) +{ + if (sd->thumb.request) + { + ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request); + sd->thumb.request = NULL; + } + if (sd->thumb.retry) + { + retry = eina_list_remove(retry, sd); + sd->thumb.retry = EINA_FALSE; + } + + if (!sd->file) return; + + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_PULSE_START, "elm"); + elm_layout_signal_emit + (ELM_WIDGET_DATA(sd)->obj, EDJE_SIGNAL_GENERATE_START, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_START, NULL); pending_request++; - ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key); - wd->thumb.request = ethumb_client_thumb_async_get(_elm_ethumb_client, - _elm_thumb_done, - _elm_thumb_error, - wd); + ethumb_client_file_set(_elm_ethumb_client, sd->file, sd->key); + sd->thumb.request = ethumb_client_thumb_async_get + (_elm_ethumb_client, _on_ethumb_thumb_done, _on_ethumb_thumb_error, sd); } static Eina_Bool -_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__) +_thumbnailing_available_cb(void *data, + int type __UNUSED__, + void *ev __UNUSED__) { - _thumb_apply(data); + _thumb_start(data); + return ECORE_CALLBACK_RENEW; } static void -_thumb_show(Widget_Data *wd) +_thumb_show(Elm_Thumb_Smart_Data *sd) { - evas_object_show(wd->frame); + evas_object_show(ELM_WIDGET_DATA(sd)->resize_obj); if (elm_thumb_ethumb_client_connected_get()) { - _thumb_apply(wd); + _thumb_start(sd); return; } - if (!wd->eeh) - wd->eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, - _thumb_apply_cb, wd); -} - -static void -_thumb_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - _thumb_show(data); -} - -static void -_thumb_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) -{ - Widget_Data *wd = data; - - evas_object_hide(wd->frame); - - if (wd->thumb.request) - { - ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request); - wd->thumb.request = NULL; - - edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm"); - evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL); - } - - if (wd->thumb.retry) - { - retry = eina_list_remove(retry, wd); - wd->thumb.retry = EINA_FALSE; - } - - if (wd->eeh) - { - ecore_event_handler_del(wd->eeh); - wd->eeh = NULL; - } + if (!sd->eeh) + sd->eeh = ecore_event_handler_add + (ELM_ECORE_EVENT_ETHUMB_CONNECT, _thumbnailing_available_cb, sd); } #endif +static void +_elm_thumb_smart_show(Evas_Object *obj) +{ + ELM_THUMB_DATA_GET(obj, sd); + + ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.show(obj); + +#ifdef ELM_ETHUMB + _thumb_show(sd); +#endif +} + +static void +_elm_thumb_smart_hide(Evas_Object *obj) +{ + ELM_THUMB_DATA_GET(obj, sd); + + ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.hide(obj); + + evas_object_hide(ELM_WIDGET_DATA(sd)->resize_obj); + +#ifdef ELM_ETHUMB + if (sd->thumb.request) + { + ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request); + sd->thumb.request = NULL; + + elm_layout_signal_emit(obj, EDJE_SIGNAL_GENERATE_STOP, "elm"); + evas_object_smart_callback_call + (ELM_WIDGET_DATA(sd)->obj, SIG_GENERATE_STOP, NULL); + } + + if (sd->thumb.retry) + { + retry = eina_list_remove(retry, sd); + sd->thumb.retry = EINA_FALSE; + } + + if (sd->eeh) + { + ecore_event_handler_del(sd->eeh); + sd->eeh = NULL; + } +#endif +} + #ifdef ELM_ETHUMB static int _elm_need_ethumb = 0; - static void _on_die_cb(void *, Ethumb_Client *); static void -_connect_cb(void *data __UNUSED__, Ethumb_Client *c, Eina_Bool success) +_connect_cb(void *data __UNUSED__, + Ethumb_Client *c, + Eina_Bool success) { if (success) { @@ -478,9 +533,11 @@ _connect_cb(void *data __UNUSED__, Ethumb_Client *c, Eina_Bool success) } static void -_on_die_cb(void *data __UNUSED__, Ethumb_Client *c __UNUSED__) +_on_die_cb(void *data __UNUSED__, + Ethumb_Client *c __UNUSED__) { ethumb_client_disconnect(_elm_ethumb_client); + _elm_ethumb_client = NULL; _elm_ethumb_connected = EINA_FALSE; _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL); @@ -501,7 +558,9 @@ _elm_unneed_ethumb(void) } static Eina_Bool -_elm_thumb_dropcb(void *data __UNUSED__, Evas_Object *o, Elm_Selection_Data *drop) +_elm_thumb_dnd_cb(void *data __UNUSED__, + Evas_Object *o, + Elm_Selection_Data *drop) { if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE; elm_thumb_file_set(o, drop->data, NULL); @@ -513,176 +572,220 @@ elm_need_ethumb(void) { #ifdef ELM_ETHUMB if (_elm_need_ethumb++) return EINA_TRUE; + ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new(); ethumb_client_init(); _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL); + return EINA_TRUE; #else return EINA_FALSE; #endif } +static void +_elm_thumb_smart_add(Evas_Object *obj) +{ + EVAS_SMART_DATA_ALLOC(obj, Elm_Thumb_Smart_Data); + + ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.add(obj); + + elm_layout_theme_set(obj, "thumb", "base", elm_widget_style_get(obj)); + + priv->view = NULL; + priv->file = NULL; + priv->key = NULL; + priv->eeh = NULL; + priv->on_hold = EINA_FALSE; + priv->is_video = EINA_FALSE; + priv->was_video = EINA_FALSE; + +#ifdef HAVE_ELEMENTARY_ETHUMB + priv->thumb.thumb_path = NULL; + priv->thumb.thumb_key = NULL; + priv->thumb.request = NULL; + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down_cb, priv); + evas_object_event_callback_add + (obj, EVAS_CALLBACK_MOUSE_UP, _mouse_up_cb, priv); +#endif + + elm_widget_can_focus_set(obj, EINA_FALSE); +} + +static void +_elm_thumb_smart_del(Evas_Object *obj) +{ + ELM_THUMB_DATA_GET(obj, sd); + +#ifdef HAVE_ELEMENTARY_ETHUMB + if (sd->thumb.request) + { + ethumb_client_thumb_async_cancel(_elm_ethumb_client, sd->thumb.request); + sd->thumb.request = NULL; + } + if (sd->thumb.retry) + { + retry = eina_list_remove(retry, sd); + sd->thumb.retry = EINA_FALSE; + } + + eina_stringshare_del(sd->thumb.thumb_path); + eina_stringshare_del(sd->thumb.thumb_key); +#endif + + eina_stringshare_del(sd->file); + eina_stringshare_del(sd->key); + + if (sd->eeh) ecore_event_handler_del(sd->eeh); + + ELM_WIDGET_CLASS(_elm_thumb_parent_sc)->base.del(obj); +} + +static void +_elm_thumb_smart_set_user(Elm_Layout_Smart_Class *sc) +{ + ELM_WIDGET_CLASS(sc)->base.add = _elm_thumb_smart_add; + ELM_WIDGET_CLASS(sc)->base.del = _elm_thumb_smart_del; + + ELM_WIDGET_CLASS(sc)->base.show = _elm_thumb_smart_show; + ELM_WIDGET_CLASS(sc)->base.hide = _elm_thumb_smart_hide; +} + EAPI Evas_Object * elm_thumb_add(Evas_Object *parent) { Evas *e; - Widget_Data *wd; Evas_Object *obj; - Evas_Coord minw, minh; - ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); + EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL); - ELM_SET_WIDTYPE(widtype, "thumb"); - elm_widget_type_set(obj, "thumb"); - elm_widget_sub_object_add(parent, obj); - elm_widget_data_set(obj, wd); - elm_widget_del_hook_set(obj, _del_hook); - elm_widget_theme_hook_set(obj, _theme_hook); - elm_widget_can_focus_set(obj, EINA_FALSE); + e = evas_object_evas_get(parent); + if (!e) return NULL; - wd->frame = edje_object_add(e); - _elm_theme_object_set(obj, wd->frame, "thumb", "base", "default"); - elm_widget_resize_object_set(obj, wd->frame); + obj = evas_object_smart_add(e, _elm_thumb_smart_class_new()); - edje_object_size_min_calc(obj, &minw, &minh); - evas_object_size_hint_min_set(obj, minw, minh); + if (!elm_widget_sub_object_add(parent, obj)) + ERR("could not add %p as sub object of %p", obj, parent); - wd->self = obj; - wd->view = NULL; - wd->file = NULL; - wd->key = NULL; - wd->eeh = NULL; - wd->on_hold = EINA_FALSE; - wd->is_video = EINA_FALSE; - wd->was_video = EINA_FALSE; - -#ifdef HAVE_ELEMENTARY_ETHUMB - wd->thumb.thumb_path = NULL; - wd->thumb.thumb_key = NULL; - wd->thumb.request = NULL; - evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN, - _mouse_down_cb, wd); - evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP, - _mouse_up_cb, wd); - evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, - _thumb_show_cb, wd); - evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, - _thumb_hide_cb, wd); -#endif - - // TODO: convert Elementary to subclassing of Evas_Smart_Class - // TODO: and save some bytes, making descriptions per-class and not instance! - evas_object_smart_callbacks_descriptions_set(obj, _signals); return obj; } EAPI void elm_thumb_reload(Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj); + ELM_THUMB_DATA_GET(obj, sd); - eina_stringshare_replace(&(wd->thumb.file), NULL); - eina_stringshare_replace(&(wd->thumb.key), NULL); + eina_stringshare_replace(&(sd->thumb.file), NULL); + eina_stringshare_replace(&(sd->thumb.key), NULL); #ifdef HAVE_ELEMENTARY_ETHUMB if (evas_object_visible_get(obj)) - _thumb_show(wd); + _thumb_show(sd); #endif } EAPI void -elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key) +elm_thumb_file_set(Evas_Object *obj, + const char *file, + const char *key) { - ELM_CHECK_WIDTYPE(obj, widtype); Eina_Bool file_replaced, key_replaced; - Widget_Data *wd = elm_widget_data_get(obj); - file_replaced = eina_stringshare_replace(&(wd->file), file); - key_replaced = eina_stringshare_replace(&(wd->key), key); + ELM_THUMB_CHECK(obj); + ELM_THUMB_DATA_GET(obj, sd); + + file_replaced = eina_stringshare_replace(&(sd->file), file); + key_replaced = eina_stringshare_replace(&(sd->key), key); if (file_replaced) { int prefix_size; const char **ext, *ptr; static const char *extensions[] = - { - ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL - }; + { + ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL + }; - prefix_size = eina_stringshare_strlen(wd->file) - 4; + prefix_size = eina_stringshare_strlen(sd->file) - 4; if (prefix_size >= 0) { - ptr = wd->file + prefix_size; - wd->is_video = EINA_FALSE; + ptr = sd->file + prefix_size; + sd->is_video = EINA_FALSE; for (ext = extensions; *ext; ext++) if (!strcasecmp(ptr, *ext)) { - wd->is_video = EINA_TRUE; + sd->is_video = EINA_TRUE; break; } } } - eina_stringshare_replace(&(wd->thumb.file), NULL); - eina_stringshare_replace(&(wd->thumb.key), NULL); + eina_stringshare_replace(&(sd->thumb.file), NULL); + eina_stringshare_replace(&(sd->thumb.key), NULL); #ifdef HAVE_ELEMENTARY_ETHUMB if (((file_replaced) || (key_replaced)) && (evas_object_visible_get(obj))) - _thumb_show(wd); + _thumb_show(sd); #else (void)key_replaced; #endif } EAPI void -elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key) +elm_thumb_file_get(const Evas_Object *obj, + const char **file, + const char **key) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj); + ELM_THUMB_DATA_GET(obj, sd); if (file) - *file = wd->file; + *file = sd->file; if (key) - *key = wd->key; + *key = sd->key; } EAPI void -elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key) +elm_thumb_path_get(const Evas_Object *obj, + const char **file, + const char **key) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj); + ELM_THUMB_DATA_GET(obj, sd); if (file) - *file = wd->thumb.file; + *file = sd->thumb.file; if (key) - *key = wd->thumb.key; + *key = sd->thumb.key; } EAPI void -elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting setting) +elm_thumb_animate_set(Evas_Object *obj, + Elm_Thumb_Animation_Setting setting) { - ELM_CHECK_WIDTYPE(obj, widtype); - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj); + ELM_THUMB_DATA_GET(obj, sd); EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST); - wd->anim_setting = setting; + sd->anim_setting = setting; if (setting == ELM_THUMB_ANIMATION_LOOP) - edje_object_signal_emit(wd->view, "animate_loop", ""); + edje_object_signal_emit(sd->view, "animate_loop", ""); else if (setting == ELM_THUMB_ANIMATION_START) - edje_object_signal_emit(wd->view, "animate", ""); + edje_object_signal_emit(sd->view, "animate", ""); else if (setting == ELM_THUMB_ANIMATION_STOP) - edje_object_signal_emit(wd->view, "animate_stop", ""); + edje_object_signal_emit(sd->view, "animate_stop", ""); } EAPI Elm_Thumb_Animation_Setting elm_thumb_animate_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) ELM_THUMB_ANIMATION_LAST; - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj) ELM_THUMB_ANIMATION_LAST; + ELM_THUMB_DATA_GET(obj, sd); - return wd->anim_setting; + return sd->anim_setting; } EAPI void * @@ -698,19 +801,18 @@ elm_thumb_ethumb_client_connected_get(void) } EAPI Eina_Bool -elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit) +elm_thumb_editable_set(Evas_Object *obj, + Eina_Bool edit) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj) EINA_FALSE; + ELM_THUMB_DATA_GET(obj, sd); - if (!wd) return EINA_FALSE; edit = !!edit; - if (wd->edit == edit) return EINA_TRUE; + if (sd->edit == edit) return EINA_TRUE; - wd->edit = edit; - if (wd->edit) - elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE, - _elm_thumb_dropcb, obj); + sd->edit = edit; + if (sd->edit) + elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE, _elm_thumb_dnd_cb, obj); else elm_drop_target_del(obj); @@ -720,11 +822,8 @@ elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit) EAPI Eina_Bool elm_thumb_editable_get(const Evas_Object *obj) { - ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; - Widget_Data *wd = elm_widget_data_get(obj); + ELM_THUMB_CHECK(obj) EINA_FALSE; + ELM_THUMB_DATA_GET(obj, sd); - if (!wd) return EINA_FALSE; - return wd->edit; + return sd->edit; } - -/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/ diff --git a/legacy/elementary/src/lib/elm_thumb.h b/legacy/elementary/src/lib/elm_thumb.h index 5eabaf6edb..dc330d6062 100644 --- a/legacy/elementary/src/lib/elm_thumb.h +++ b/legacy/elementary/src/lib/elm_thumb.h @@ -1,40 +1,46 @@ /** - * @defgroup Thumb Thumb + * @defgroup Thumb Thumbnail * @ingroup Elementary * * @image html img/widget/thumb/preview-00.png * @image latex img/widget/thumb/preview-00.eps * - * A thumb object is used for displaying the thumbnail of an image or video. - * You must have compiled Elementary with Ethumb_Client support and the DBus - * service must be present and auto-activated in order to have thumbnails to - * be generated. You must also have a Session bus, not System bus. + * A thumbnail object is used for displaying the thumbnail of an image + * or video. You must have compiled Elementary with @c Ethumb_Client + * support. Also, Ethumb's DBus service must be present and + * auto-activated in order to have thumbnails generated. You must also + * have a @b session bus, not a @b system one. * - * Once the thumbnail object becomes visible, it will check if there is a - * previously generated thumbnail image for the file set on it. If not, it - * will start generating this thumbnail. + * Once the thumbnail object becomes visible, it will check if there + * is a previously generated thumbnail image for the file set on + * it. If not, it will start generating this thumbnail. * - * Different config settings will cause different thumbnails to be generated - * even on the same file. + * Different configuration settings will cause different thumbnails to + * be generated even on the same file. * - * Generated thumbnails are stored under @c $HOME/.thumbnails/. Check the - * Ethumb documentation to change this path, and to see other configuration - * options. + * Generated thumbnails are stored under @c $HOME/.thumbnails/. Check + * Ethumb's documentation to change this path, and to see other + * configuration options. * - * Signals that you can add callbacks for are: + * This widget inherits from the @ref Layout one, so that all the + * functions acting on it also work for thumbnail objects. * - * - "clicked" - This is called when a user has clicked the thumb without dragging - * around. - * - "clicked,double" - This is called when a user has double-clicked the thumb. - * - "press" - This is called when a user has pressed down the thumb. - * - "generate,start" - The thumbnail generation started. - * - "generate,stop" - The generation process stopped. - * - "generate,error" - The generation failed. - * - "load,error" - The thumbnail image loading failed. + * This widget emits the following signals, besides the ones sent from + * @ref Layout: + * - @c "clicked" - This is called when a user has clicked the + * thumbnail object without dragging it around. + * - @c "clicked,double" - This is called when a user has double-clicked + * the thumbnail object. + * - @c "press" - This is called when a user has pressed down over the + * thumbnail object. + * - @c "generate,start" - The thumbnail generation has started. + * - @c "generate,stop" - The generation process has stopped. + * - @c "generate,error" - The thumbnail generation failed. + * - @c "load,error" - The thumbnail image loading failed. * - * available styles: - * - default - * - noframe + * Available styles: + * - @c "default" + * - @c "noframe" * * An example of use of thumbnail: * @@ -94,15 +100,19 @@ EAPI Evas_Object *elm_thumb_add(Evas_Object *parent); EAPI void elm_thumb_reload(Evas_Object *obj); /** - * Set the file that will be used as thumbnail. + * Set the file that will be used as thumbnail @b source. * * @param obj The thumb object. - * @param file The path to file that will be used as thumb. + * @param file The path to file that will be used as thumbnail source. * @param key The key used in case of an EET file. * - * The file can be an image or a video (in that case, acceptable extensions are: - * avi, mp4, ogv, mov, mpg and wmv). To start the video animation, use the - * function elm_thumb_animate(). + * The file can be an image or a video (in that case, acceptable + * extensions are: avi, mp4, ogv, mov, mpg and wmv). To start the + * video animation, use the function elm_thumb_animate(). + * + * @warning Not to be confused with elm_layout_file_set(), which sets + * the file giving the thumbnail objcet's @b decoration, not the + * thumbnail image's source. * * @see elm_thumb_file_get() * @see elm_thumb_reload()