1 #include <Elementary.h>
4 #include "els_scroller.h"
6 typedef struct _Widget_Data Widget_Data;
14 Ecore_Timer *longtimer;
16 #ifdef HAVE_ELEMENTARY_ETHUMB
25 Ethumb_Exists *exists;
27 Ecore_Event_Handler *eeh;
29 Ethumb_Thumb_Format format;
37 #ifdef HAVE_ELEMENTARY_ETHUMB
38 static Eina_List *_elm_icon_retry = NULL;
39 static int _icon_pending_request = 0;
41 static void _icon_thumb_exists(void *data, Ethumb_Client *client __UNUSED__, Ethumb_Exists *thread, Eina_Bool exists);
42 static void _icon_thumb_stop(Widget_Data *wd, void *ethumbd);
45 static const char *widtype = NULL;
46 static void _del_hook(Evas_Object *obj);
47 static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
48 static void _theme_hook(Evas_Object *obj);
49 static void _sizing_eval(Evas_Object *obj);
50 static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
51 static void _mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
53 static const char SIG_CLICKED[] = "clicked";
54 static const char SIG_DRAG_START[] = "drag,start";
55 static const char SIG_DRAG_END[] = "drag,end";
57 static const Evas_Smart_Cb_Description _signals[] = {
66 _del_hook(Evas_Object *obj)
68 Widget_Data *wd = elm_widget_data_get(obj);
69 #ifdef HAVE_ELEMENTARY_ETHUMB
70 Ethumb_Client *ethumbd;
74 #ifdef HAVE_ELEMENTARY_ETHUMB
75 ethumbd = elm_thumb_ethumb_client_get();
76 _icon_thumb_stop(wd, ethumbd);
78 eina_stringshare_del(wd->thumb.file.path);
79 eina_stringshare_del(wd->thumb.file.key);
80 eina_stringshare_del(wd->thumb.thumb.path);
81 eina_stringshare_del(wd->thumb.thumb.key);
84 ecore_event_handler_del(wd->thumb.eeh);
91 _mirrored_set(Evas_Object *obj, Eina_Bool rtl)
93 Widget_Data *wd = elm_widget_data_get(obj);
95 edje_object_mirrored_set(wd->frm, rtl);
99 _theme_hook(Evas_Object *obj)
101 Widget_Data *wd = elm_widget_data_get(obj);
103 _elm_widget_mirrored_reload(obj);
104 _mirrored_set(wd->frm, elm_widget_mirrored_get(obj));
105 _elm_theme_object_set(obj, wd->frm, "photo", "base",
106 elm_widget_style_get(obj));
107 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
108 edje_object_scale_set(wd->frm, elm_widget_scale_get(obj) *
114 _sizing_eval(Evas_Object *obj)
116 Widget_Data *wd = elm_widget_data_get(obj);
117 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
124 scale = (wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
125 evas_object_size_hint_min_set(wd->img, scale, scale);
126 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
127 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
128 edje_object_size_min_restricted_calc(wd->frm, &minw, &minh, minw, minh);
129 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
132 evas_object_size_hint_min_set(obj, minw, minh);
133 evas_object_size_hint_max_set(obj, maxw, maxh);
138 _icon_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
141 Widget_Data *wd = elm_widget_data_get(data);
146 Edje_Message_Int_Set *msg;
147 Evas_Object *icon = _els_smart_icon_object_get(wd->img);
149 evas_object_geometry_get(icon, NULL, NULL, &w, &h);
150 msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
152 msg->val[0] = (int)w;
153 msg->val[1] = (int)h;
155 edje_object_message_send(wd->frm, EDJE_MESSAGE_INT_SET, 0, msg);
158 #ifdef HAVE_ELEMENTARY_ETHUMB
159 if (wd->thumb.file.path)
160 elm_photo_thumb_set(data, wd->thumb.file.path, wd->thumb.file.key);
166 _drag_done_cb(void *unused __UNUSED__, Evas_Object *obj)
168 elm_object_scroll_freeze_pop(obj);
169 evas_object_smart_callback_call(obj, SIG_DRAG_END, NULL);
173 _longpress(void *objv)
175 Widget_Data *wd = elm_widget_data_get(objv);
179 DBG("Long press: start drag!");
180 wd->longtimer = NULL; /* clear: must return NULL now */
181 evas_object_event_callback_del(objv, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
183 tmp = _els_smart_icon_object_get(wd->img);
185 evas_object_image_file_get(tmp,&file,NULL);
189 /* FIXME: Deal with relative paths; use PATH_MAX */
190 snprintf(buf, sizeof(buf), "file://%s", file);
191 if (elm_drag_start(objv, ELM_SEL_FORMAT_IMAGE,
192 buf, _drag_done_cb, NULL))
194 elm_object_scroll_freeze_push(objv);
195 evas_object_smart_callback_call(objv, SIG_DRAG_START, NULL);
199 return 0; /* Don't call again */
203 _mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event)
205 Widget_Data *wd = elm_widget_data_get(data);
206 Evas_Event_Mouse_Move *move = event;
211 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
215 /* if the event is held, stop waiting */
216 if (move->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
218 /* Moved too far: No longpress for you! */
219 ecore_timer_del(wd->longtimer);
220 wd->longtimer = NULL;
221 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
227 _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
229 Widget_Data *wd = elm_widget_data_get(data);
231 if (wd->longtimer) ecore_timer_del(wd->longtimer);
233 /* FIXME: Hard coded timeout */
234 wd->longtimer = ecore_timer_add(0.7, _longpress, data);
235 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
240 _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
242 Widget_Data *wd = elm_widget_data_get(data);
244 if ((wd) && (wd->longtimer))
246 ecore_timer_del(wd->longtimer);
247 wd->longtimer = NULL;
250 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
254 _icon_size_min_get(Evas_Object *icon)
257 _els_smart_icon_size_get(icon, &size, NULL);
258 return (size < 32) ? 32 : size;
262 #ifdef HAVE_ELEMENTARY_ETHUMB
264 _icon_thumb_stop(Widget_Data *wd, void *ethumbd)
266 if (wd->thumb.id >= 0)
268 ethumb_client_generate_cancel(ethumbd, wd->thumb.id, NULL, NULL, NULL);
270 _icon_pending_request--;
273 if (wd->thumb.exists)
275 ethumb_client_thumb_exists_cancel(wd->thumb.exists);
276 wd->thumb.exists = NULL;
277 _icon_pending_request--;
282 _elm_icon_retry = eina_list_remove(_elm_icon_retry, wd);
283 wd->thumb.retry = EINA_FALSE;
288 _icon_thumb_display(Widget_Data *wd)
290 Eina_Bool ret = EINA_FALSE;
292 if (wd->thumb.format == ETHUMB_THUMB_EET)
294 static const char *extensions[] = {
295 ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
297 const char **ext, *ptr;
299 Eina_Bool video = EINA_FALSE;
301 prefix_size = eina_stringshare_strlen(wd->thumb.file.path) - 4;
302 if (prefix_size >= 0)
304 ptr = wd->thumb.file.path + prefix_size;
305 for (ext = extensions; *ext; ++ext)
306 if (!strcasecmp(ptr, *ext))
314 ret = _els_smart_icon_file_edje_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
318 ret = _els_smart_icon_file_key_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
324 _icon_thumb_retry(Widget_Data *wd)
326 return _icon_thumb_display(wd);
330 _icon_thumb_cleanup(Ethumb_Client *ethumbd)
335 EINA_LIST_FOREACH_SAFE(_elm_icon_retry, l, ll, wd)
336 if (_icon_thumb_retry(wd))
338 _elm_icon_retry = eina_list_remove_list(_elm_icon_retry, l);
339 wd->thumb.retry = EINA_FALSE;
342 if (_icon_pending_request == 0)
343 EINA_LIST_FREE(_elm_icon_retry, wd)
344 _icon_thumb_stop(wd, ethumbd);
348 _icon_thumb_finish(Widget_Data *wd, Ethumb_Client *ethumbd)
350 const char *file = NULL, *group = NULL;
353 _els_smart_icon_file_get(wd->img, &file, &group);
354 file = eina_stringshare_ref(file);
355 group = eina_stringshare_ref(group);
357 ret = _icon_thumb_display(wd);
363 if (!wd->thumb.retry)
365 _elm_icon_retry = eina_list_append(_elm_icon_retry, wd);
366 wd->thumb.retry = EINA_TRUE;
369 /* Back to previous image */
370 if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
371 _els_smart_icon_file_edje_set(wd->img, file, group);
373 _els_smart_icon_file_key_set(wd->img, file, group);
376 _icon_thumb_cleanup(ethumbd);
378 eina_stringshare_del(file);
379 eina_stringshare_del(group);
383 _icon_thumb_cb(void *data,
384 Ethumb_Client *ethumbd,
386 const char *file __UNUSED__,
387 const char *key __UNUSED__,
388 const char *thumb_path,
389 const char *thumb_key,
392 Widget_Data *wd = data;
394 EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
397 _icon_pending_request--;
401 eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
402 eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
403 wd->thumb.format = ethumb_client_format_get(ethumbd);
405 _icon_thumb_finish(wd, ethumbd);
409 ERR("could not generate thumbnail for %s (key: %s)", file, key);
410 _icon_thumb_cleanup(ethumbd);
415 _icon_thumb_exists(void *data, Ethumb_Client *client __UNUSED__, Ethumb_Exists *thread, Eina_Bool exists)
417 Widget_Data *wd = data;
418 Ethumb_Client *ethumbd;
420 if (ethumb_client_thumb_exists_check(thread))
423 wd->thumb.exists = NULL;
425 ethumbd = elm_thumb_ethumb_client_get();
429 const char *thumb_path, *thumb_key;
431 _icon_pending_request--;
432 ethumb_client_thumb_path_get(ethumbd, &thumb_path, &thumb_key);
433 eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
434 eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
435 wd->thumb.format = ethumb_client_format_get(ethumbd);
437 _icon_thumb_finish(wd, ethumbd);
439 else if ((wd->thumb.id = ethumb_client_generate(ethumbd, _icon_thumb_cb, wd, NULL)) == -1)
441 ERR("Generate was unable to start !");
442 /* Failed to generate thumbnail */
443 _icon_pending_request--;
448 _icon_thumb_apply(Widget_Data *wd)
450 Ethumb_Client *ethumbd;
452 ethumbd = elm_thumb_ethumb_client_get();
454 _icon_thumb_stop(wd, ethumbd);
456 if (!wd->thumb.file.path) return ;
458 _icon_pending_request++;
459 if (!ethumb_client_file_set(ethumbd, wd->thumb.file.path, wd->thumb.file.key)) return ;
460 ethumb_client_size_set(ethumbd, _icon_size_min_get(wd->img), _icon_size_min_get(wd->img));
461 wd->thumb.exists = ethumb_client_thumb_exists(ethumbd, _icon_thumb_exists, wd);
465 _icon_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
467 Widget_Data *wd = data;
469 _icon_thumb_apply(wd);
470 return ECORE_CALLBACK_RENEW;
475 elm_photo_add(Evas_Object *parent)
482 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
484 ELM_SET_WIDTYPE(widtype, "photo");
485 elm_widget_type_set(obj, "photo");
486 elm_widget_sub_object_add(parent, obj);
487 elm_widget_data_set(obj, wd);
488 elm_widget_del_hook_set(obj, _del_hook);
489 elm_widget_theme_hook_set(obj, _theme_hook);
490 elm_widget_can_focus_set(obj, EINA_FALSE);
492 wd->frm = edje_object_add(e);
493 _elm_theme_object_set(obj, wd->frm, "photo", "base", "default");
494 elm_widget_resize_object_set(obj, wd->frm);
496 wd->img = _els_smart_icon_add(e);
497 _els_smart_icon_scale_up_set(wd->img, 1);
498 _els_smart_icon_scale_down_set(wd->img, 1);
499 _els_smart_icon_smooth_scale_set(wd->img, 1);
500 _els_smart_icon_fill_inside_set(wd->img, 0);
501 _els_smart_icon_scale_size_set(wd->img, 0);
502 wd->fill = EINA_FALSE;
503 _els_smart_icon_scale_set(wd->img,
504 elm_widget_scale_get(obj) * _elm_config->scale);
505 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
507 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
509 evas_object_repeat_events_set(wd->img, 1);
510 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
511 evas_object_show(wd->img);
512 elm_widget_sub_object_add(obj, wd->img);
514 wd->longtimer = NULL;
516 icon = _els_smart_icon_object_get(wd->img);
517 evas_object_event_callback_add(icon, EVAS_CALLBACK_MOVE,
518 _icon_move_resize, obj);
519 evas_object_event_callback_add(icon, EVAS_CALLBACK_RESIZE,
520 _icon_move_resize, obj);
522 evas_object_smart_callbacks_descriptions_set(obj, _signals);
524 #ifdef HAVE_ELEMENTARY_ETHUMB
528 _mirrored_set(obj, elm_widget_mirrored_get(obj));
534 elm_photo_file_set(Evas_Object *obj, const char *file)
536 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
537 Widget_Data *wd = elm_widget_data_get(obj);
539 if (!wd) return EINA_FALSE;
540 if (!_els_smart_icon_file_key_set(wd->img, file, NULL))
548 elm_photo_size_set(Evas_Object *obj, int size)
550 ELM_CHECK_WIDTYPE(obj, widtype);
551 Widget_Data *wd = elm_widget_data_get(obj);
554 wd->size = (size > 0) ? size : 0;
556 _els_smart_icon_scale_size_set(wd->img, wd->size);
562 elm_photo_fill_inside_set(Evas_Object *obj, Eina_Bool fill)
564 ELM_CHECK_WIDTYPE(obj, widtype);
565 Widget_Data *wd = elm_widget_data_get(obj);
568 _els_smart_icon_fill_inside_set(wd->img, fill);
574 elm_photo_editable_set(Evas_Object *obj, Eina_Bool set)
576 ELM_CHECK_WIDTYPE(obj, widtype);
577 Widget_Data *wd = elm_widget_data_get(obj);
580 _els_smart_icon_edit_set(wd->img, set, obj);
584 elm_photo_thumb_set(const Evas_Object *obj, const char *file, const char *group)
586 ELM_CHECK_WIDTYPE(obj, widtype);
587 Widget_Data *wd = elm_widget_data_get(obj);
590 #ifdef HAVE_ELEMENTARY_ETHUMB
591 eina_stringshare_replace(&wd->thumb.file.path, file);
592 eina_stringshare_replace(&wd->thumb.file.key, group);
594 if (elm_thumb_ethumb_client_connected())
596 _icon_thumb_apply(wd);
602 wd->thumb.eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, _icon_thumb_apply_cb, wd);
612 elm_photo_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed)
614 ELM_CHECK_WIDTYPE(obj, widtype);
615 Widget_Data *wd = elm_widget_data_get(obj);
617 return _els_smart_icon_aspect_ratio_retained_set(wd->img, fixed);
621 elm_photo_aspect_fixed_get(const Evas_Object *obj)
623 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
624 Widget_Data *wd = elm_widget_data_get(obj);
625 if (!wd) return EINA_FALSE;
626 return _els_smart_icon_aspect_ratio_retained_get(wd->img);
631 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/