void test_image(void *data, Evas_Object *obj, void *event_info);
void test_remote_image(void *data, Evas_Object *obj, void *event_info);
void test_click_image(void *data, Evas_Object *obj, void *event_info);
+void test_load_image(void *data, Evas_Object *obj, void *event_info);
void test_external_button(void *data, Evas_Object *obj, void *event_info);
void test_external_slider(void *data, Evas_Object *obj, void *event_info);
void test_external_scroller(void *data, Evas_Object *obj, void *event_info);
ADD_TEST(NULL, "Images", "Image", test_image);
ADD_TEST(NULL, "Images", "Image Remote", test_remote_image);
ADD_TEST(NULL, "Images", "Image Click", test_click_image);
+ ADD_TEST(NULL, "Images", "Image Async Load", test_load_image);
ADD_TEST(NULL, "Images", "Slideshow", test_slideshow);
ADD_TEST(NULL, "Images", "Video", test_video);
evas_object_resize(win, 320, 480);
evas_object_show(win);
}
+
+#define STATUS_SET(obj, fmt) do { \
+ elm_object_text_set(obj, fmt); \
+ fprintf(stderr, "%s\n", fmt); fflush(stderr); \
+ } while (0)
+
+static void
+_img_load_open_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *status_text = data;
+
+ STATUS_SET(status_text, "Async file open done.");
+}
+
+static void
+_img_load_ready_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *status_text = data;
+
+ STATUS_SET(status_text, "Image is ready to show.");
+}
+
+static void
+_img_load_error_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *status_text = data;
+
+ STATUS_SET(status_text, "Async file load failed.");
+}
+
+static void
+_img_load_cancel_cb(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *status_text = data;
+
+ STATUS_SET(status_text, "Async file open has been cancelled.");
+}
+
+static void
+_create_image(Evas_Object *data, Eina_Bool async, Eina_Bool preload)
+{
+ Evas_Object *win = data;
+ Evas_Object *im, *status_text;
+ Evas_Object *box = evas_object_data_get(win, "box");
+ char buf[PATH_MAX] = {0};
+
+ im = elm_image_add(win);
+ elm_image_async_open_set(im, async);
+ elm_image_preload_disabled_set(im, preload);
+
+ evas_object_size_hint_weight_set(im, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ evas_object_size_hint_align_set(im, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_data_set(win, "im", im);
+ elm_box_pack_start(box, im);
+ evas_object_show(im);
+
+ status_text = evas_object_data_get(win, "phld");
+ if (!status_text)
+ {
+ status_text = elm_label_add(win);
+ evas_object_size_hint_weight_set(status_text, EVAS_HINT_EXPAND, 0);
+ evas_object_size_hint_align_set(status_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
+ evas_object_data_set(win, "phld", status_text);
+ elm_box_pack_after(box, status_text, im);
+ evas_object_show(status_text);
+ }
+
+ evas_object_smart_callback_add(im, "load,open", _img_load_open_cb, status_text);
+ evas_object_smart_callback_add(im, "load,ready", _img_load_ready_cb, status_text);
+ evas_object_smart_callback_add(im, "load,error", _img_load_error_cb, status_text);
+ evas_object_smart_callback_add(im, "load,cancel", _img_load_cancel_cb, status_text);
+
+ STATUS_SET(status_text, "Loading image...");
+ snprintf(buf, sizeof(buf) - 1, "%s/images/insanely_huge_test_image.jpg", elm_app_data_dir_get());
+ elm_image_file_set(im, buf, NULL);
+}
+
+static void
+_bt_clicked(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *win = data;
+ Evas_Object *im = evas_object_data_get(win, "im");
+ Evas_Object *chk1 = evas_object_data_get(win, "chk1");
+ Evas_Object *chk2 = evas_object_data_get(win, "chk2");
+ Eina_Bool async = elm_check_state_get(chk1);
+ Eina_Bool preload = elm_check_state_get(chk2);
+
+ evas_object_del(im);
+ _create_image(win, async, preload);
+}
+
+void
+test_load_image(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Evas_Object *win, *box, *hbox, *label, *chk1, *chk2, *bt;
+
+ win = elm_win_util_standard_add("image test", "Image Test");
+ elm_win_autodel_set(win, EINA_TRUE);
+
+ box = elm_box_add(win);
+ elm_box_align_set(box, 0.5, 1.0);
+ evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, box);
+ evas_object_show(box);
+ evas_object_data_set(win, "box", box);
+
+ _create_image(win, EINA_FALSE, EINA_FALSE);
+
+ hbox = elm_box_add(win);
+ elm_box_horizontal_set(hbox, EINA_TRUE);
+ elm_box_align_set(hbox, 0, 0.5);
+ evas_object_size_hint_weight_set(hbox, EVAS_HINT_EXPAND, 0.0);
+ evas_object_size_hint_align_set(hbox, EVAS_HINT_FILL, 0.0);
+ {
+ label = elm_label_add(win);
+ elm_object_text_set(label, "Async load options:");
+ evas_object_size_hint_weight_set(label, 0.0, 0.0);
+ evas_object_size_hint_align_set(label, EVAS_HINT_FILL, 0.5);
+ elm_box_pack_end(hbox, label);
+ evas_object_show(label);
+
+ chk1 = elm_check_add(hbox);
+ elm_object_text_set(chk1, "Async file open");
+ evas_object_size_hint_weight_set(chk1, 0.0, 0.0);
+ evas_object_size_hint_align_set(chk1, EVAS_HINT_FILL, 0.5);
+ elm_box_pack_end(hbox, chk1);
+ evas_object_data_set(win, "chk1", chk1);
+ evas_object_show(chk1);
+
+ chk2 = elm_check_add(hbox);
+ elm_object_text_set(chk2, "Disable preload");
+ evas_object_size_hint_weight_set(chk2, 0.0, 0.0);
+ evas_object_size_hint_align_set(chk2, EVAS_HINT_FILL, 0.5);
+ elm_box_pack_end(hbox, chk2);
+ evas_object_data_set(win, "chk2", chk2);
+ evas_object_show(chk2);
+ }
+ evas_object_show(hbox);
+ elm_box_pack_end(box, hbox);
+
+ bt = elm_button_add(win);
+ evas_object_size_hint_align_set(bt, 0.5, 0.0);
+ elm_object_text_set(bt, "Image Reload");
+ evas_object_smart_callback_add(bt, "clicked", _bt_clicked, win);
+ elm_box_pack_end(box, bt);
+ evas_object_show(bt);
+
+ evas_object_resize(win, 320, 480);
+ evas_object_show(win);
+}
$null, otherwise.]]
}
}
- @property async {
- set {
- [[If true, file open will happen asynchronously allowing for better
- performance in some situations. The file will be opened from a
- different thread. Classes implementing async open might then block
- and wait when querying information from the file (eg. image size).
-
- Only a few objects implement this feature, and this flag may
- be ignored by EFL. In that case, get() will always return false.]]
- }
- get {
- [[Retrieves the asynchronous open flag, which will be true only if
- enabled and supported by the object.]]
- }
- values {
- async: bool; [[Flag for asynchronous open.]]
- }
- }
save @const {
[[Save the given image object's contents to an (image) file.
none).]]
}
}
- async_wait @const {
- [[Block and wait until all asynchronous operations are completed. Unless
- the async flag was set on this object, this method has no effect.]]
-
- return: bool;[[$false if an error occurred, else $true]]
- }
- }
- events {
- /* FIXME - remove Efl.File events: async,{opened,error} */
- async,opened; [[The file was successfully opened asynchronously]]
- async,error; [[Error occurred in asynchronous file operation]]
}
}
static const char SIG_DOWNLOAD_PROGRESS[] = "download,progress";
static const char SIG_DOWNLOAD_DONE[] = "download,done";
static const char SIG_DOWNLOAD_ERROR[] = "download,error";
+static const char SIG_LOAD_OPEN[] = "load,open";
+static const char SIG_LOAD_READY[] = "load,ready";
+static const char SIG_LOAD_ERROR[] = "load,error";
+static const char SIG_LOAD_CANCEL[] = "load,cancel";
static const Evas_Smart_Cb_Description _smart_callbacks[] = {
{SIG_DND, ""},
{SIG_CLICKED, ""},
{SIG_DOWNLOAD_PROGRESS, ""},
{SIG_DOWNLOAD_DONE, ""},
{SIG_DOWNLOAD_ERROR, ""},
+ {SIG_LOAD_OPEN, "Triggered when the file has been opened (image size is known)"},
+ {SIG_LOAD_READY, "Triggered when the image file is ready for display"},
+ {SIG_LOAD_ERROR, "Triggered whenener an I/O or decoding error occured"},
+ {SIG_LOAD_CANCEL, "Triggered whenener async I/O was cancelled"},
{NULL, NULL}
};
void *event EINA_UNUSED)
{
Efl_Ui_Image_Data *sd = data;
+ Evas_Load_Error err;
+
sd->preload_status = EFL_UI_IMAGE_PRELOADED;
if (sd->show) evas_object_show(obj);
ELM_SAFE_FREE(sd->prev_img, evas_object_del);
+ err = evas_object_image_load_error_get(obj);
+ if (!err) evas_object_smart_callback_call(sd->self, SIG_LOAD_READY, NULL);
+ else evas_object_smart_callback_call(sd->self, SIG_LOAD_ERROR, NULL);
}
static void
EFL_UI_IMAGE_DATA_GET(todo->obj, sd);
if (sd)
{
+ evas_object_smart_callback_call(todo->obj, SIG_LOAD_CANCEL, NULL);
if (thread == sd->async.th) _async_clear(sd);
}
}
ok = _efl_ui_image_smart_internal_file_set
(sd->self, sd, file, f, key);
}
- if (ok)
- {
- // TODO: Implement Efl.File async,opened event_info type
- efl_event_callback_legacy_call
- (sd->self, EFL_FILE_EVENT_ASYNC_OPENED, NULL);
- _efl_ui_image_internal_sizing_eval(sd->self, sd);
- }
- else
- {
- // keep file,key around for file_get
- efl_event_callback_legacy_call
- (sd->self, EFL_FILE_EVENT_ASYNC_ERROR, NULL);
- }
+ if (ok) evas_object_smart_callback_call(sd->self, SIG_LOAD_OPEN, NULL);
+ else evas_object_smart_callback_call(sd->self, SIG_LOAD_ERROR, NULL);
}
}
}
evas_object_image_file_get(sd->img, file, key);
}
+#if 0
+// Kept for reference: wait for async open to complete - probably unused.
static Eina_Bool
_efl_ui_image_efl_file_async_wait(const Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *pd)
{
}
return ok;
}
+#endif
-EOLIAN static void
-_efl_ui_image_efl_file_async_set(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *pd, Eina_Bool async)
+/* Legacy style async API. While legacy only, this is new from 1.19.
+ * Tizen has used elm_image_async_open_set() internally for a while, despite
+ * EFL upstream not exposing a proper async API. */
+
+EAPI void
+elm_image_async_open_set(Eo *obj, Eina_Bool async)
{
+ Efl_Ui_Image_Data *pd;
+
+ EINA_SAFETY_ON_FALSE_RETURN(efl_isa(obj, MY_CLASS));
+ pd = efl_data_scope_get(obj, MY_CLASS);
if (pd->async_enable == async) return;
pd->async_enable = async;
if (!async) _async_cancel(pd);
}
-EOLIAN static Eina_Bool
-_efl_ui_image_efl_file_async_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd)
-{
- return sd->async_enable;
-}
-
EOLIAN static void
_efl_ui_image_efl_gfx_view_view_size_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Data *sd, int *w, int *h)
{
Efl.File.file.set;
Efl.File.file.get;
Efl.File.mmap.set;
- Efl.File.async.set;
- Efl.File.async.get;
- Efl.File.async_wait;
Efl.Gfx.View.view_size.get;
Efl.Image.Load.load_size.set;
Efl.Image.Load.load_size.get;
* data is of type Elm_Image_Progress.
* @li @c "download,done" - This is called when the download has completed.
* @li @c "download,error"- This is called when the download has failed.
+ * @li @c "load,open" - Triggered when the file has been opened, if async
+ * open is enabled (image size is known). (since 1.19)
+ * @li @c "load,ready" - Triggered when the image file is ready for display,
+ * if preload is enabled. (since 1.19)
+ * @li @c "load,error" - Triggered if an async I/O or decoding error occurred,
+ * if async open or preload is enabled (since 1.19)
+ * @li @c "load,cancel" - Triggered whenener async I/O was cancelled. (since 1.19)
*
* An example of usage for this API follows:
* @li @ref tutorial_image
*/
EAPI Eina_Bool elm_image_aspect_fixed_get(const Evas_Object *obj);
+/**
+ * @brief Enable asynchronous file I/O for elm_image_file_set.
+ *
+ * If @c true, this will make elm_image_file_set() an asynchronous operation.
+ * Use of this function is not recommended and the standard EO-based
+ * asynchronous I/O API should be preferred instead.
+ *
+ * @since 1.19
+ *
+ * @ingroup Elm_Image
+ */
+EAPI void elm_image_async_open_set(Evas_Object *obj, Eina_Bool async);
+
#include "efl_ui_image.eo.legacy.h"
struct _Test_Data
{
int image_id;
- Eina_Bool success;
+ int success;
};
START_TEST (elm_atspi_role_get)
END_TEST
static void
-_async_error_cb(void *data, const Efl_Event *event)
+_async_error_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Test_Data *td = data;
char path[PATH_MAX];
sprintf(path, pathfmt, td->image_id);
- efl_file_set(event->object, path, NULL);
+ elm_image_file_set(obj, path, NULL);
+
+ td->success = 1;
}
static void
-_async_opened_cb(void *data, const Efl_Event *event)
+_async_opened_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
{
Test_Data *td = data;
const char *ff, *kk, *r1, *r2;
char path[PATH_MAX];
sprintf(path, pathfmt, td->image_id);
- efl_file_get(event->object, &ff, &kk);
+ elm_image_file_get(obj, &ff, &kk);
r1 = strrchr(ff, '/');
r2 = strrchr(path, '/');
- ck_assert(!strcmp(r1, r2));
+ ck_assert(eina_streq(r1, r2));
ck_assert(!kk);
+ fprintf(stderr, "opened: %s\n", ff);
+
if (td->image_id < MAX_IMAGE_ID / 2)
{
td->image_id++;
sprintf(path, pathfmt, td->image_id);
- efl_file_set(event->object, path, NULL);
+ elm_image_file_set(obj, path, NULL);
return;
}
else if (td->image_id < MAX_IMAGE_ID)
for (; td->image_id < MAX_IMAGE_ID;)
{
sprintf(path, pathfmt, ++td->image_id);
- efl_file_set(event->object, path, NULL);
+ elm_image_file_set(obj, path, NULL);
}
return;
}
- td->success = 1;
- ecore_main_loop_quit();
+ if (td->success == 1)
+ td->success = 2;
+}
+
+static void
+_async_ready_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED)
+{
+ Test_Data *td = data;
+
+ const char *ff;
+ elm_image_file_get(obj, &ff, 0);
+ fprintf(stderr, "ready : %s\n", ff);
+ if (td->success == 2)
+ {
+ td->success = 3;
+ ecore_main_loop_quit();
+ }
}
static Eina_Bool
START_TEST (elm_image_async_path)
{
Evas_Object *win, *image;
- Eina_Bool one, two, ok;
+ Eina_Bool ok;
Test_Data td;
elm_init(1, NULL);
td.image_id = 0;
image = elm_image_add(win);
- one = efl_file_async_get(image);
- efl_file_async_set(image, 1);
- efl_event_callback_add(image, EFL_FILE_EVENT_ASYNC_ERROR, _async_error_cb, &td);
- efl_event_callback_add(image, EFL_FILE_EVENT_ASYNC_OPENED, _async_opened_cb, &td);
- ok = efl_file_set(image, invalid, NULL);
- two = efl_file_async_get(image);
- ck_assert(!one && two);
+ elm_image_async_open_set(image, 1);
+ evas_object_smart_callback_add(image, "load,error", _async_error_cb, &td);
+ evas_object_smart_callback_add(image, "load,open", _async_opened_cb, &td);
+ evas_object_smart_callback_add(image, "load,ready", _async_ready_cb, &td);
+ evas_object_show(image);
+ ok = elm_image_file_set(image, invalid, NULL);
ck_assert(ok);
ecore_timer_add(10.0, _timeout_cb, &td);
elm_run();
- ck_assert(td.success);
+ ck_assert(td.success == 3);
elm_shutdown();
}
elm_init(1, NULL);
win = elm_win_add(NULL, "image", ELM_WIN_BASIC);
- td.success = 0;
+ td.success = 1; // skip "error" case
td.image_id = 1;
sprintf(path, pathfmt, td.image_id);
ck_assert(f);
image = elm_image_add(win);
- efl_file_async_set(image, 1);
- efl_event_callback_add(image, EFL_FILE_EVENT_ASYNC_ERROR, _async_error_cb, &td);
- efl_event_callback_add(image, EFL_FILE_EVENT_ASYNC_OPENED, _async_opened_cb, &td);
- ok = efl_file_mmap_set(image, f, NULL);
+ elm_image_async_open_set(image, 1);
+ evas_object_smart_callback_add(image, "load,error", _async_error_cb, &td);
+ evas_object_smart_callback_add(image, "load,open", _async_opened_cb, &td);
+ evas_object_smart_callback_add(image, "load,ready", _async_ready_cb, &td);
+ evas_object_show(image);
+ ok = elm_image_mmap_set(image, f, NULL);
ck_assert(ok);
ecore_timer_add(10.0, _timeout_cb, &td);
elm_run();
- ck_assert(td.success);
+ ck_assert(td.success == 3);
eina_file_close(f);