Elementary thumb: Added ethumb check routine.
[framework/uifw/elementary.git] / src / lib / elm_thumb.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Thumb Thumb
6  *
7  * A thumb object is used for displaying the thumbnail of an image or video.
8  * You must have compiled Elementary with Ethumb_Client support and the DBus
9  * service must be present and auto-activated in order to have thumbnails to
10  * be generated.
11  *
12  * Signals that you can add callbacks for are:
13  *
14  * "clicked" - This is called when a user has clicked the thumb without dragging
15  *             around.
16  * "clicked,double" - This is called when a user has double-clicked the thumb.
17  * "press" - This is called when a user has pressed down the thumb.
18  * "generate,start" - The thumbnail generation started.
19  * "generate,stop" - The generation process stopped.
20  * "generate,error" - The generation failed.
21  * "load,error" - The thumbnail image loading failed.
22  */
23
24 typedef struct _Widget_Data Widget_Data;
25
26 struct _Widget_Data
27 {
28    Evas_Object *self;
29    Evas_Object *frame;
30    Evas_Object *view;
31    const char *file;
32    const char *key;
33    struct
34      {
35         int id;
36         const char *file;
37         const char *key;
38 #ifdef HAVE_ELEMENTARY_ETHUMB
39         Ethumb_Exists *exists;
40 #endif
41      } thumb;
42    Ecore_Event_Handler *eeh;
43    Elm_Thumb_Animation_Setting anim_setting;
44    Eina_Bool on_hold : 1;
45    Eina_Bool is_video : 1;
46    Eina_Bool was_video : 1;
47    Eina_Bool edit : 1;
48 };
49
50 static const char *widtype = NULL;
51
52 static const char SIG_CLICKED[] = "clicked";
53 static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
54 static const char SIG_GENERATE_ERROR[] = "generate,error";
55 static const char SIG_GENERATE_START[] = "generate,start";
56 static const char SIG_GENERATE_STOP[] = "generate,stop";
57 static const char SIG_LOAD_ERROR[] = "load,error";
58 static const char SIG_PRESS[] = "press";
59
60 static const Evas_Smart_Cb_Description _signals[] =
61 {
62      {SIG_CLICKED, ""},
63      {SIG_CLICKED_DOUBLE, ""},
64      {SIG_GENERATE_ERROR, ""},
65      {SIG_GENERATE_START, ""},
66      {SIG_GENERATE_STOP, ""},
67      {SIG_LOAD_ERROR, ""},
68      {SIG_PRESS, ""},
69      {NULL, NULL}
70 };
71
72 #define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start"
73 #define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop"
74 #define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error"
75 #define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error"
76 #define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start"
77 #define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop"
78
79 struct _Ethumb_Client *_elm_ethumb_client = NULL;
80 Eina_Bool _elm_ethumb_connected = EINA_FALSE;
81
82 EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
83
84 static void
85 _del_hook(Evas_Object *obj)
86 {
87    Widget_Data *wd = elm_widget_data_get(obj);
88
89 #ifdef HAVE_ELEMENTARY_ETHUMB
90    if (wd->thumb.id >= 0)
91      ethumb_client_generate_cancel(_elm_ethumb_client, wd->thumb.id,
92                                    NULL, NULL, NULL);
93    if (wd->thumb.exists)
94      {
95         ethumb_client_thumb_exists_cancel(wd->thumb.exists);
96         wd->thumb.exists = NULL;
97      }
98 #endif
99
100    eina_stringshare_del(wd->file);
101    eina_stringshare_del(wd->key);
102    if (wd->eeh) ecore_event_handler_del(wd->eeh);
103    free(wd);
104 }
105
106 static void
107 _theme_hook(Evas_Object *obj)
108 {
109    Widget_Data *wd = elm_widget_data_get(obj);
110    _elm_theme_object_set(obj, wd->frame, "thumb", "base",
111                          elm_widget_style_get(obj));
112 }
113
114 #ifdef HAVE_ELEMENTARY_ETHUMB
115 static void
116 _mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
117 {
118    Widget_Data *wd = data;
119    Evas_Event_Mouse_Down *ev = event_info;
120
121    if (ev->button != 1)
122      return;
123    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
124      wd->on_hold = EINA_TRUE;
125    else
126      wd->on_hold = EINA_FALSE;
127    if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
128      evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL);
129    else
130      evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL);
131 }
132
133 static void
134 _mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
135 {
136    Widget_Data *wd = data;
137    Evas_Event_Mouse_Up *ev = event_info;
138
139    if (ev->button != 1)
140      return;
141    if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
142      wd->on_hold = EINA_TRUE;
143    else
144      wd->on_hold = EINA_FALSE;
145    if (!wd->on_hold)
146      evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL);
147    wd->on_hold = EINA_FALSE;
148 }
149
150 static void
151 _finished_thumb(Widget_Data *wd, const char *thumb_path, const char *thumb_key)
152 {
153    Eina_Bool new_view = EINA_FALSE;
154    int r;
155    Evas_Coord mw, mh;
156    Evas *evas;
157
158    evas = evas_object_evas_get(wd->self);
159    if ((wd->view) && (wd->is_video ^ wd->was_video))
160      {
161         evas_object_del(wd->view);
162         wd->view = NULL;
163      }
164    wd->was_video = wd->is_video;
165
166    if ((wd->is_video) &&
167        (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
168      {
169         if (!wd->view)
170           {
171              wd->view = edje_object_add(evas);
172              if (!wd->view)
173                {
174                   ERR("could not create edje object");
175                   goto err;
176                }
177              new_view = EINA_TRUE;
178           }
179
180         if (!edje_object_file_set(wd->view, thumb_path, "movie/thumb"))
181           {
182              ERR("could not set file=%s key=%s for %s", thumb_path, thumb_key,
183                  wd->file);
184              goto view_err;
185           }
186      }
187    else
188      {
189         if (!wd->view)
190           {
191              wd->view = evas_object_image_filled_add(evas);
192              if (!wd->view)
193                {
194                   ERR("could not create image object");
195                   goto err;
196                }
197              new_view = EINA_TRUE;
198           }
199
200         evas_object_image_file_set(wd->view, thumb_path, thumb_key);
201         r = evas_object_image_load_error_get(wd->view);
202         if (r != EVAS_LOAD_ERROR_NONE)
203           {
204              ERR("%s: %s", thumb_path, evas_load_error_str(r));
205              goto view_err;
206           }
207      }
208
209    if (new_view) elm_widget_sub_object_add(wd->self, wd->view);
210    edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view);
211    edje_object_size_min_get(wd->frame, &mw, &mh);
212    edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh);
213    evas_object_size_hint_min_set(wd->self, mw, mh);
214    eina_stringshare_replace(&(wd->thumb.file), thumb_path);
215    eina_stringshare_replace(&(wd->thumb.key), thumb_key);
216    edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
217    evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
218    return;
219
220 view_err:
221    evas_object_del(wd->view);
222    wd->view = NULL;
223 err:
224    edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
225    evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
226 }
227
228 static void
229 _finished_thumb_cb(void *data, Ethumb_Client *c __UNUSED__, int id, const char *file, const char *key, const char *thumb_path, const char *thumb_key, Eina_Bool success)
230 {
231    Widget_Data *wd = data;
232
233    EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
234    wd->thumb.id = -1;
235
236    edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm");
237
238    if (success)
239      {
240         _finished_thumb(wd, thumb_path, thumb_key);
241         return;
242      }
243
244    ERR("could not generate thumbnail for %s (key: %s)", file, key ? key : "");
245    edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
246    evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
247 }
248
249 static void
250 _thumb_exists(Ethumb_Client *client __UNUSED__, Ethumb_Exists *thread,
251               Eina_Bool exists, void *data)
252 {
253    Widget_Data *wd = data;
254
255    if (ethumb_client_thumb_exists_check(thread))
256      return ;
257
258    if (exists)
259      {
260         const char *thumb_path, *thumb_key;
261
262         wd->thumb.id = -1;
263         ethumb_client_thumb_path_get(_elm_ethumb_client, &thumb_path,
264                                      &thumb_key);
265         _finished_thumb(wd, thumb_path, thumb_key);
266         return;
267      }
268    else if ((wd->thumb.id = ethumb_client_generate
269              (_elm_ethumb_client, _finished_thumb_cb, wd, NULL)) != -1)
270      {
271         edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START, "elm");
272         edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START, "elm");
273         evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL);
274      }
275    else
276      {
277         wd->thumb.id = -1;
278         edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
279         evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
280      }
281
282 }
283
284 static void
285 _thumb_apply(Widget_Data *wd)
286 {
287    if (wd->thumb.id > 0)
288      {
289         ethumb_client_generate_cancel
290            (_elm_ethumb_client, wd->thumb.id, NULL, NULL, NULL);
291         wd->thumb.id = -1;
292      }
293
294    if (wd->thumb.exists)
295      {
296         ethumb_client_thumb_exists_cancel(wd->thumb.exists);
297         wd->thumb.exists = NULL;
298      }
299
300    if (!wd->file) return;
301
302    ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key);
303    ethumb_client_thumb_exists(_elm_ethumb_client, _thumb_exists, wd);
304 }
305
306 static Eina_Bool
307 _thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
308 {
309    _thumb_apply(data);
310    return ECORE_CALLBACK_RENEW;
311 }
312
313 static void
314 _thumb_show(Widget_Data *wd)
315 {
316    evas_object_show(wd->frame);
317
318    if (elm_thumb_ethumb_client_connected())
319      {
320         _thumb_apply(wd);
321         return;
322      }
323
324    if (!wd->eeh)
325      wd->eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT,
326                                        _thumb_apply_cb, wd);
327 }
328
329 static void
330 _thumb_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
331 {
332    _thumb_show(data);
333 }
334
335 static void
336 _thumb_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
337 {
338    Widget_Data *wd = data;
339
340    evas_object_hide(wd->frame);
341
342    if (wd->thumb.id >= 0)
343      {
344         ethumb_client_generate_cancel
345            (_elm_ethumb_client, wd->thumb.id, NULL, NULL, NULL);
346         wd->thumb.id = -1;
347
348         edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
349         evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
350      }
351
352    if (wd->thumb.exists)
353      {
354         ethumb_client_thumb_exists_cancel(wd->thumb.exists);
355         wd->thumb.exists = NULL;
356      }
357
358    if (wd->eeh)
359      {
360         ecore_event_handler_del(wd->eeh);
361         wd->eeh = NULL;
362      }
363 }
364
365 #endif
366
367 #ifdef ELM_ETHUMB
368 static int _elm_need_ethumb = 0;
369
370 static void _on_die_cb(void *, Ethumb_Client *);
371
372 static void
373 _connect_cb(void *data __UNUSED__, Ethumb_Client *c, Eina_Bool success)
374 {
375    if (success)
376      {
377         ethumb_client_on_server_die_callback_set(c, _on_die_cb, NULL, NULL);
378         _elm_ethumb_connected = EINA_TRUE;
379         ecore_event_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, NULL, NULL, NULL);
380      }
381    else
382      _elm_ethumb_client = NULL;
383 }
384
385 static void
386 _on_die_cb(void *data __UNUSED__, Ethumb_Client *c __UNUSED__)
387 {
388    ethumb_client_disconnect(_elm_ethumb_client);
389    _elm_ethumb_client = NULL;
390    _elm_ethumb_connected = EINA_FALSE;
391    _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
392 }
393 #endif
394
395 void
396 _elm_unneed_ethumb(void)
397 {
398 #ifdef ELM_ETHUMB
399    if (--_elm_need_ethumb) return;
400
401    ethumb_client_disconnect(_elm_ethumb_client);
402    _elm_ethumb_client = NULL;
403    ethumb_client_shutdown();
404    ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
405 #endif
406 }
407
408 static Eina_Bool
409 _elm_thumb_dropcb(void *data __UNUSED__, Evas_Object *o, Elm_Selection_Data *drop)
410 {
411    if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE;
412    elm_thumb_file_set(o, drop->data, NULL);
413    return EINA_TRUE;
414 }
415
416 /**
417  * This must be called before any other function that handle with
418  * elm_thumb objects or ethumb_client instances.
419  *
420  * @ingroup Thumb
421  */
422 EAPI Eina_Bool
423 elm_need_ethumb(void)
424 {
425 #ifdef ELM_ETHUMB
426    if (_elm_need_ethumb++) return EINA_TRUE;
427    ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new();
428    ethumb_client_init();
429    _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
430    return EINA_TRUE;
431 #else
432    return EINA_FALSE;
433 #endif
434 }
435
436 /**
437  * Add a new thumb object to the parent.
438  *
439  * @param parent The parent object.
440  * @return The new object or NULL if it cannot be created.
441  *
442  * @see elm_thumb_file_set()
443  * @see elm_thumb_ethumb_client_get()
444  *
445  * @ingroup Thumb
446  */
447 EAPI Evas_Object *
448 elm_thumb_add(Evas_Object *parent)
449 {
450    Evas *e;
451    Widget_Data *wd;
452    Evas_Object *obj;
453    Evas_Coord minw, minh;
454
455    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
456
457    ELM_SET_WIDTYPE(widtype, "thumb");
458    elm_widget_type_set(obj, "thumb");
459    elm_widget_sub_object_add(parent, obj);
460    elm_widget_data_set(obj, wd);
461    elm_widget_del_hook_set(obj, _del_hook);
462    elm_widget_theme_hook_set(obj, _theme_hook);
463    elm_widget_can_focus_set(obj, EINA_FALSE);
464
465    wd->frame = edje_object_add(e);
466    _elm_theme_object_set(obj, wd->frame, "thumb", "base", "default");
467    elm_widget_resize_object_set(obj, wd->frame);
468
469    edje_object_size_min_calc(obj, &minw, &minh);
470    evas_object_size_hint_min_set(obj, minw, minh);
471
472    wd->self = obj;
473    wd->view = NULL;
474    wd->file = NULL;
475    wd->key = NULL;
476    wd->eeh = NULL;
477    wd->thumb.id = -1;
478    wd->on_hold = EINA_FALSE;
479    wd->is_video = EINA_FALSE;
480    wd->was_video = EINA_FALSE;
481
482 #ifdef HAVE_ELEMENTARY_ETHUMB
483    wd->thumb.exists = NULL;
484    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
485                                   _mouse_down_cb, wd);
486    evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
487                                   _mouse_up_cb, wd);
488    evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW,
489                                   _thumb_show_cb, wd);
490    evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
491                                   _thumb_hide_cb, wd);
492 #endif
493
494    // TODO: convert Elementary to subclassing of Evas_Smart_Class
495    // TODO: and save some bytes, making descriptions per-class and not instance!
496    evas_object_smart_callbacks_descriptions_set(obj, _signals);
497    return obj;
498 }
499
500 /**
501  * Reload thumbnail if it was generated before.
502  *
503  * This is useful if the ethumb client configuration changed, like its
504  * size, aspect or any other property one set in the handle returned
505  * by elm_thumb_ethumb_client_get().
506  *
507  * @param obj The thumb object to reload
508  *
509  * @see elm_thumb_file_set()
510  *
511  * @ingroup Thumb
512  */
513 EAPI void
514 elm_thumb_reload(Evas_Object *obj)
515 {
516    ELM_CHECK_WIDTYPE(obj, widtype);
517    Widget_Data *wd = elm_widget_data_get(obj);
518
519    eina_stringshare_replace(&(wd->thumb.file), NULL);
520    eina_stringshare_replace(&(wd->thumb.key), NULL);
521
522 #ifdef HAVE_ELEMENTARY_ETHUMB
523    if (evas_object_visible_get(obj))
524      _thumb_show(wd);
525 #endif
526 }
527
528 /**
529  * Set the file that will be used as thumbnail.
530  *
531  * The file can be an image or a video (in that case, acceptable extensions are:
532  * avi, mp4, ogv, mov, mpg and wmv). To start the video animation, use the
533  * function elm_thumb_animate().
534  *
535  * @param obj The thumb object.
536  * @param file The path to file that will be used as thumb.
537  * @param key The key used in case of an EET file.
538  *
539  * @see elm_thumb_file_get()
540  * @see elm_thumb_reload()
541  * @see elm_thumb_animate()
542  *
543  * @ingroup Thumb
544  */
545 EAPI void
546 elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key)
547 {
548    ELM_CHECK_WIDTYPE(obj, widtype);
549    Eina_Bool file_replaced, key_replaced;
550    Widget_Data *wd = elm_widget_data_get(obj);
551
552    file_replaced = eina_stringshare_replace(&(wd->file), file);
553    key_replaced = eina_stringshare_replace(&(wd->key), key);
554
555    if (file_replaced)
556      {
557         int prefix_size;
558         const char **ext, *ptr;
559         static const char *extensions[] =
560           {
561              ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
562           };
563
564         prefix_size = eina_stringshare_strlen(wd->file) - 4;
565         if (prefix_size >= 0)
566           {
567              ptr = wd->file + prefix_size;
568              wd->is_video = EINA_FALSE;
569              for (ext = extensions; *ext; ext++)
570                if (!strcasecmp(ptr, *ext))
571                  {
572                     wd->is_video = EINA_TRUE;
573                     break;
574                  }
575           }
576      }
577
578    eina_stringshare_replace(&(wd->thumb.file), NULL);
579    eina_stringshare_replace(&(wd->thumb.key), NULL);
580
581 #ifdef HAVE_ELEMENTARY_ETHUMB
582    if (((file_replaced) || (key_replaced)) && (evas_object_visible_get(obj)))
583      _thumb_show(wd);
584 #endif
585 }
586
587 /**
588  * Get the image or video path and key used to generate the thumbnail.
589  *
590  * @param obj The thumb object.
591  * @param file Pointer to filename.
592  * @param key Pointer to key.
593  *
594  * @see elm_thumb_file_set()
595  * @see elm_thumb_path_get()
596  * @see elm_thumb_animate()
597  *
598  * @ingroup Thumb
599  */
600 EAPI void
601 elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key)
602 {
603    ELM_CHECK_WIDTYPE(obj, widtype);
604    Widget_Data *wd = elm_widget_data_get(obj);
605
606    if (file)
607      *file = wd->file;
608    if (key)
609      *key = wd->key;
610 }
611
612 /**
613  * Get the path and key to the image or video generated by ethumb.
614  *
615  * One just need to make sure that the thumbnail was generated before getting
616  * its path; otherwise, the path will be NULL. One way to do that is by asking
617  * for the path when/after the "generate,stop" smart callback is called.
618  *
619  * @param obj The thumb object.
620  * @param file Pointer to thumb path.
621  * @param key Pointer to thumb key.
622  *
623  * @see elm_thumb_file_get()
624  *
625  * @ingroup Thumb
626  */
627 EAPI void
628 elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key)
629 {
630    ELM_CHECK_WIDTYPE(obj, widtype);
631    Widget_Data *wd = elm_widget_data_get(obj);
632
633    if (file)
634      *file = wd->thumb.file;
635    if (key)
636      *key = wd->thumb.key;
637 }
638
639 /**
640  * Set the animation state for the thumb object. If its content is an animated
641  * video, you may start/stop the animation or tell it to play continuously and
642  * looping.
643  *
644  * @param obj The thumb object.
645  * @param setting The animation setting.
646  *
647  * @see elm_thumb_file_set()
648  *
649  * @ingroup Thumb
650  */
651 EAPI void
652 elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting setting)
653 {
654    ELM_CHECK_WIDTYPE(obj, widtype);
655    Widget_Data *wd = elm_widget_data_get(obj);
656
657    EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST);
658
659    wd->anim_setting = setting;
660    if (setting == ELM_THUMB_ANIMATION_LOOP)
661      edje_object_signal_emit(wd->view, "animate_loop", "");
662    else if (setting == ELM_THUMB_ANIMATION_START)
663      edje_object_signal_emit(wd->view, "animate", "");
664    else if (setting == ELM_THUMB_ANIMATION_STOP)
665      edje_object_signal_emit(wd->view, "animate_stop", "");
666 }
667
668 /**
669  * Get the animation state for the thumb object.
670  *
671  * @param obj The thumb object.
672  * @return getting The animation setting or @c ELM_THUMB_ANIMATION_LAST,
673  * on errors.
674  *
675  * @see elm_thumb_file_get()
676  *
677  * @ingroup Thumb
678  */
679 EAPI Elm_Thumb_Animation_Setting
680 elm_thumb_animate_get(const Evas_Object *obj)
681 {
682    ELM_CHECK_WIDTYPE(obj, widtype) ELM_THUMB_ANIMATION_LAST;
683    Widget_Data *wd = elm_widget_data_get(obj);
684
685    return wd->anim_setting;
686 }
687
688 /**
689  * Get the ethumb_client handle so custom configuration can be made.
690  * This must be called before the objects are created to be sure no object is
691  * visible and no generation started.
692  *
693  * @return Ethumb_Client instance or NULL.
694  *
695  * Example of usage:
696  *
697  * @code
698  * #include <Elementary.h>
699  * #ifndef ELM_LIB_QUICKLAUNCH
700  * EAPI int
701  * elm_main(int argc, char **argv)
702  * {
703  *    Ethumb_Client *client;
704  *
705  *    elm_need_ethumb();
706  *
707  *    // ... your code
708  *
709  *    client = elm_thumb_ethumb_client_get();
710  *    if (!client)
711  *      {
712  *         ERR("could not get ethumb_client");
713  *         return 1;
714  *      }
715  *    ethumb_client_size_set(client, 100, 100);
716  *    ethumb_client_crop_align_set(client, 0.5, 0.5);
717  *    // ... your code
718  *
719  *    // Create elm_thumb objects here
720  *
721  *    elm_run();
722  *    elm_shutdown();
723  *    return 0;
724  * }
725  * #endif
726  * ELM_MAIN()
727  * @endcode
728  *
729  * @ingroup Thumb
730  */
731 EAPI void *
732 elm_thumb_ethumb_client_get(void)
733 {
734    return _elm_ethumb_client;
735 }
736
737 /**
738  * Get the ethumb_client connection state.
739  *
740  * @return EINA_TRUE if the client is connected to the server or
741  *         EINA_FALSE otherwise.
742  */
743 EAPI Eina_Bool
744 elm_thumb_ethumb_client_connected(void)
745 {
746    return _elm_ethumb_connected;
747 }
748
749 EAPI Eina_Bool
750 elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit)
751 {
752    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
753    Widget_Data *wd = elm_widget_data_get(obj);
754
755    if (!wd) return EINA_FALSE;
756    edit = !!edit;
757    if (wd->edit == edit) return EINA_TRUE;
758
759    wd->edit = edit;
760    if (wd->edit)
761      elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE,
762                          _elm_thumb_dropcb, obj);
763    else
764      elm_drop_target_del(obj);
765
766    return EINA_TRUE;
767 }
768
769 EAPI Eina_Bool
770 elm_thumb_editable_get(const Evas_Object *obj)
771 {
772    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
773    Widget_Data *wd = elm_widget_data_get(obj);
774
775    if (!wd) return EINA_FALSE;
776    return wd->edit;
777 }
778
779 /* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/