From bc05ebeec3a90f13e9924ee20deb8b7e7be532be Mon Sep 17 00:00:00 2001 From: Amitesh Singh Date: Fri, 2 Jun 2017 10:45:25 +0900 Subject: Efl.Ui.Image.Zoomable: implement Ui.Image.icon property @feature --- src/bin/elementary/test.c | 2 + src/bin/elementary/test_photocam.c | 117 +++++++++ src/lib/elementary/efl_ui_image_zoomable.c | 290 +++++++++++++++++++++ src/lib/elementary/efl_ui_image_zoomable.eo | 3 +- src/lib/elementary/efl_ui_image_zoomable_private.h | 7 + src/lib/elementary/elm_priv.h | 2 + src/lib/elementary/elm_theme.c | 2 +- 7 files changed, 420 insertions(+), 3 deletions(-) diff --git a/src/bin/elementary/test.c b/src/bin/elementary/test.c index fd26f0bd1b..49869bf525 100644 --- a/src/bin/elementary/test.c +++ b/src/bin/elementary/test.c @@ -180,6 +180,7 @@ void test_index3(void *data, Evas_Object *obj, void *event_info); void test_index_horizontal(void *data, Evas_Object *obj, void *event_info); void test_photocam(void *data, Evas_Object *obj, void *event_info); void test_photocam_remote(void *data, Evas_Object *obj, void *event_info); +void test_photocam_icon(void *data, Evas_Object *obj, void *event_info); void test_photo(void *data, Evas_Object *obj, void *event_info); void test_prefs(void *data, Evas_Object *obj, void *event_info); void test_thumb(void *data, Evas_Object *obj, void *event_info); @@ -675,6 +676,7 @@ add_tests: ADD_TEST(NULL, "Images", "Icon Standard", test_icon_standard); ADD_TEST(NULL, "Images", "Photocam", test_photocam); ADD_TEST(NULL, "Images", "Photocam Remote", test_photocam_remote); + ADD_TEST(NULL, "Images", "Photocam Icon", test_photocam_icon); ADD_TEST(NULL, "Images", "Photo", test_photo); ADD_TEST(NULL, "Images", "Thumb", test_thumb); ADD_TEST(NULL, "Images", "Image", test_image); diff --git a/src/bin/elementary/test_photocam.c b/src/bin/elementary/test_photocam.c index be6a1724b1..df586dabcf 100644 --- a/src/bin/elementary/test_photocam.c +++ b/src/bin/elementary/test_photocam.c @@ -614,3 +614,120 @@ test_photocam_remote(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void evas_object_resize(win, 800, 800); evas_object_show(win); } + +static const struct { + unsigned char val; + const char *name; +} photocam_icons[] = { + {0, "home"}, + {1, "folder"}, + {2, "network-server"}, + {3, "folder-music"}, + {4, "user-trash"}, + {5, "start-here"}, + {6, "folder-download"}, + {7, "emblem-system"}, + {8, "emblem-mail"}, + {9, "None"}, + {0, NULL} +}; + +static void +_radio_changed_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + unsigned char index = efl_ui_radio_value_get(obj); + efl_ui_image_icon_set(data, photocam_icons[index].name); + printf("icon is %s\n", efl_ui_image_icon_get(data)); +} + +void +test_photocam_icon(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Evas_Object *win, *ph, *tb2, *bt, *bx, *rd; + Evas_Object *rdg = NULL; + Evas_Object *rect = NULL; + int i; + + win = elm_win_util_standard_add("photocam", "PhotoCam"); + elm_win_autodel_set(win, EINA_TRUE); + + ph = elm_photocam_add(win); + evas_object_size_hint_weight_set(ph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + efl_ui_image_icon_set(ph, "home"); + elm_win_resize_object_add(win, ph); + + rect = evas_object_rectangle_add(evas_object_evas_get(win)); + evas_object_color_set(rect, 0, 0, 0, 0); + evas_object_repeat_events_set(rect, EINA_TRUE); + evas_object_show(rect); + evas_object_event_callback_add(rect, EVAS_CALLBACK_MOUSE_WHEEL, _photocam_mouse_wheel_cb, ph); + evas_object_raise(rect); + + evas_object_event_callback_add(ph, EVAS_CALLBACK_RESIZE, _photocam_move_resize_cb, rect); + evas_object_event_callback_add(ph, EVAS_CALLBACK_MOVE, _photocam_move_resize_cb, rect); + + evas_object_smart_callback_add(ph, "clicked", my_ph_clicked, win); + evas_object_smart_callback_add(ph, "press", my_ph_press, win); + evas_object_smart_callback_add(ph, "longpressed", my_ph_longpressed, win); + evas_object_smart_callback_add(ph, "clicked,double", my_ph_clicked_double, win); + evas_object_smart_callback_add(ph, "load", my_ph_load, win); + evas_object_smart_callback_add(ph, "loaded", my_ph_loaded, win); + evas_object_smart_callback_add(ph, "load,details", my_ph_load_details, win); + evas_object_smart_callback_add(ph, "loaded,details", my_ph_loaded_details, win); + evas_object_smart_callback_add(ph, "zoom,start", my_ph_zoom_start, win); + evas_object_smart_callback_add(ph, "zoom,stop", my_ph_zoom_stop, win); + evas_object_smart_callback_add(ph, "zoom,change", my_ph_zoom_change, win); + evas_object_smart_callback_add(ph, "scroll,anim,start", my_ph_anim_start, win); + evas_object_smart_callback_add(ph, "scroll,anim,stop", my_ph_anim_stop, win); + evas_object_smart_callback_add(ph, "scroll,drag,start", my_ph_drag_start, win); + evas_object_smart_callback_add(ph, "scroll,drag,stop", my_ph_drag_stop, win); + evas_object_smart_callback_add(ph, "scroll", my_ph_scroll, win); + + evas_object_show(ph); + + tb2 = elm_table_add(win); + evas_object_size_hint_weight_set(tb2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, tb2); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Z -"); + evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_out, ph); + evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bt, 0.1, 0.1); + elm_table_pack(tb2, bt, 0, 0, 1, 1); + evas_object_show(bt); + + bt = elm_button_add(win); + elm_object_text_set(bt, "Z +"); + evas_object_smart_callback_add(bt, "clicked", my_bt_zoom_in, ph); + evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bt, 0.9, 0.1); + elm_table_pack(tb2, bt, 2, 0, 1, 1); + evas_object_show(bt); + + evas_object_show(tb2); + + bx = elm_box_add(win); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_box_horizontal_set(bx, EINA_TRUE); + elm_table_pack(tb2, bx, 1, 2, 1, 1); + evas_object_show(bx); + + for (i = 0; photocam_icons[i].name; ++i) + { + rd = elm_radio_add(win); + evas_object_size_hint_weight_set(rd, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_object_text_set(rd, photocam_icons[i].name); + efl_ui_radio_state_value_set(rd, photocam_icons[i].val); + elm_box_pack_end(bx, rd); + evas_object_smart_callback_add(rd, "changed", _radio_changed_cb, ph); + if(!rdg) + rdg = rd; + else + elm_radio_group_add(rd, rdg); + evas_object_show(rd); + } + + evas_object_resize(win, 150, 150); + evas_object_show(win); +} diff --git a/src/lib/elementary/efl_ui_image_zoomable.c b/src/lib/elementary/efl_ui_image_zoomable.c index ff1d944626..ac65ae0bb2 100644 --- a/src/lib/elementary/efl_ui_image_zoomable.c +++ b/src/lib/elementary/efl_ui_image_zoomable.c @@ -86,6 +86,7 @@ static Eina_Error PHOTO_FILE_LOAD_ERROR_UNKNOWN_FORMAT; static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); static Eina_Bool _key_action_zoom(Evas_Object *obj, const char *params); static void _efl_ui_image_zoomable_remote_copier_cancel(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd); +static Eina_Bool _internal_efl_ui_image_zoomable_icon_set(Evas_Object *obj, const char *name, Eina_Bool *fdo, Eina_Bool resize); static const Elm_Action key_actions[] = { {"move", _key_action_move}, @@ -93,6 +94,9 @@ static const Elm_Action key_actions[] = { {NULL, NULL} }; +static const char *icon_theme = NULL; +#define NON_EXISTING (void *)-1 + static inline void _photocam_image_file_set(Evas_Object *obj, Efl_Ui_Image_Zoomable_Data *sd) { @@ -885,6 +889,11 @@ EOLIAN static Elm_Theme_Apply _efl_ui_image_zoomable_elm_widget_theme_apply(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd EINA_UNUSED) { Elm_Theme_Apply int_ret = ELM_THEME_APPLY_FAILED; + Eina_Bool fdo = EINA_FALSE; + + if (sd->stdicon) + _internal_efl_ui_image_zoomable_icon_set(obj, sd->stdicon, &fdo, EINA_TRUE); + int_ret = elm_obj_widget_theme_apply(efl_super(obj, MY_CLASS)); if (!int_ret) return ELM_THEME_APPLY_FAILED; @@ -1487,6 +1496,8 @@ _efl_ui_image_zoomable_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Image_Zoomable { Efl_Ui_Image_Zoomable_Grid *g; + ELM_SAFE_FREE(sd->icon_edje, evas_object_del); + EINA_LIST_FREE(sd->grids, g) { _grid_clear(obj, g); @@ -1798,6 +1809,9 @@ _efl_ui_image_zoomable_file_set_internal(Eo *obj, Efl_Ui_Image_Zoomable_Data *sd { Evas_Load_Error ret = EVAS_LOAD_ERROR_NONE; + ELM_SAFE_FREE(sd->icon_edje, evas_object_del); + eina_stringshare_replace(&sd->stdicon, NULL); + _grid_clear_all(obj); _efl_ui_image_zoomable_zoom_reset(obj, sd); _efl_ui_image_zoomable_bounce_reset(obj, sd); @@ -2321,6 +2335,282 @@ _efl_ui_image_zoomable_gesture_enabled_set(Eo *obj, Efl_Ui_Image_Zoomable_Data * _g_layer_zoom_end_cb, obj); } +static void +_icon_size_get(Evas_Object *o, int *w, int *h) +{ + ELM_PHOTOCAM_DATA_GET(o, sd); + + efl_gfx_view_size_get(o, w, h); + + if (*w == 0 || *h == 0) + { + evas_object_geometry_get(o, NULL, NULL, w, h); + + if (*w == 0 || *h == 0) + { + edje_object_size_min_get(sd->icon_edje, w, h); + } + } +} + +static Eina_Bool +_image_zoomable_object_icon_set(Evas_Object *o, const char *group, char *style, Eina_Bool resize) +{ + Elm_Theme *th = elm_widget_theme_get(o); + ELM_PHOTOCAM_DATA_GET(o, sd); + Evas_Load_Error err; + + char buf[1024]; + Eina_File *file; + int w, h; + + if (!th) th = elm_theme_default_get(); + + snprintf(buf, sizeof(buf), "elm/icon/%s/%s", group, style); + file = _elm_theme_group_file_find(th, buf); + if (file) + { + ELM_WIDGET_DATA_GET_OR_RETURN(o, wd, EINA_FALSE); + double tz; + + eina_stringshare_replace(&sd->file, eina_file_filename_get(file)); + if (sd->f) eina_file_close(sd->f); + sd->f = file; + sd->zoom = 1.0; + evas_object_image_smooth_scale_set(sd->img, (sd->no_smooth == 0)); + evas_object_image_file_set(sd->img, NULL, NULL); + evas_object_image_source_set(sd->img, NULL); + evas_object_image_load_scale_down_set(sd->img, 0); + if (!sd->icon_edje) sd->icon_edje = edje_object_add(evas_object_evas_get(o)); + if (!resize) edje_object_mmap_set(sd->icon_edje, file, buf); + _icon_size_get(o, &w, &h); + evas_object_resize(sd->icon_edje, w, h); + + evas_object_image_source_set(sd->img, sd->icon_edje); + evas_object_image_source_visible_set(sd->img, EINA_FALSE); + evas_object_size_hint_min_set(sd->img, w, h); + evas_object_show(sd->img); + evas_object_show(sd->icon_edje); + + err = evas_object_image_load_error_get(sd->img); + if (err != EVAS_LOAD_ERROR_NONE) + { + ERR("Things are going bad for '%s' (%p) : %i", eina_file_filename_get(file), sd->img, err); + + ELM_SAFE_FREE(sd->icon_edje, evas_object_del); + + return EINA_FALSE; + } + + sd->do_region = 0; + sd->size.imw = w; + sd->size.imh = h; + sd->size.w = sd->size.imw / sd->zoom; + sd->size.h = sd->size.imh / sd->zoom; + evas_object_image_preload(sd->img, 0); + sd->main_load_pending = EINA_TRUE; + + sd->calc_job = ecore_job_add(_calc_job_cb, o); + efl_event_callback_legacy_call(o, EFL_UI_IMAGE_ZOOMABLE_EVENT_LOAD, NULL); + sd->preload_num++; + if (sd->preload_num == 1) + { + edje_object_signal_emit + (wd->resize_obj, "elm,state,busy,start", "elm"); + efl_event_callback_legacy_call(o, EFL_UI_IMAGE_ZOOMABLE_EVENT_LOAD_DETAIL, NULL); + } + + tz = sd->zoom; + sd->zoom = 0.0; + elm_photocam_zoom_set(o, tz); + sd->orient = EFL_ORIENT_NONE; + sd->flip = EFL_FLIP_NONE; + sd->orientation_changed = EINA_FALSE; + return EINA_TRUE; + } + + ELM_SAFE_FREE(sd->icon_edje, evas_object_del); + _sizing_eval(o); + WRN("Failed to set icon '%s'. Icon theme '%s' not found", group, buf); + ELM_SAFE_FREE(sd->f, eina_file_close); + + return EINA_FALSE; +} + +static Eina_Bool +_icon_standard_set(Evas_Object *obj, const char *name, Eina_Bool resize) +{ + ELM_PHOTOCAM_DATA_GET(obj, sd); + + if (_image_zoomable_object_icon_set(obj, name, "default", resize)) + { + /* TODO: elm_unneed_efreet() */ + sd->freedesktop.use = EINA_FALSE; + return EINA_TRUE; + } + return EINA_FALSE; +} + +static Eina_Bool +_icon_freedesktop_set(Evas_Object *obj, const char *name, int size) +{ + const char *path; + + ELM_PHOTOCAM_DATA_GET(obj, sd); + + elm_need_efreet(); + + if (icon_theme == NON_EXISTING) return EINA_FALSE; + + if (!icon_theme) + { + Efreet_Icon_Theme *theme; + /* TODO: Listen for EFREET_EVENT_ICON_CACHE_UPDATE */ + theme = efreet_icon_theme_find(elm_config_icon_theme_get()); + if (!theme) + { + const char **itr; + static const char *themes[] = { + "gnome", "Human", "oxygen", "hicolor", NULL + }; + for (itr = themes; *itr; itr++) + { + theme = efreet_icon_theme_find(*itr); + if (theme) break; + } + } + + if (!theme) + { + icon_theme = NON_EXISTING; + return EINA_FALSE; + } + else + icon_theme = eina_stringshare_add(theme->name.internal); + } + path = efreet_icon_path_find(icon_theme, name, size); + sd->freedesktop.use = !!path; + if (sd->freedesktop.use) + { + sd->freedesktop.requested_size = size; + efl_file_set(obj, path, NULL); + return EINA_TRUE; + } + return EINA_FALSE; +} + +static inline int +_icon_size_min_get(Evas_Object *image) +{ + int w, h; + + evas_object_geometry_get(image, NULL, NULL, &w, &h); + + return MAX(16, MIN(w, h)); +} + +/* FIXME: move this code to ecore */ +#ifdef _WIN32 +static Eina_Bool +_path_is_absolute(const char *path) +{ + //TODO: Check if this works with all absolute paths in windows + return (isalpha(*path)) && (*(path + 1) == ':') && + ((*(path + 2) == '\\') || (*(path + 2) == '/')); +} + +#else +static Eina_Bool +_path_is_absolute(const char *path) +{ + return *path == '/'; +} + +#endif + +static Eina_Bool +_internal_efl_ui_image_zoomable_icon_set(Evas_Object *obj, const char *name, Eina_Bool *fdo, Eina_Bool resize) +{ + char *tmp; + Eina_Bool ret = EINA_FALSE; + + ELM_PHOTOCAM_DATA_GET(obj, sd); + + /* try locating the icon using the specified theme */ + if (!strcmp(ELM_CONFIG_ICON_THEME_ELEMENTARY, elm_config_icon_theme_get())) + { + ret = _icon_standard_set(obj, name, resize); + if (ret && fdo) *fdo = EINA_FALSE; + } + else + { + ret = _icon_freedesktop_set(obj, name, _icon_size_min_get(obj)); + if (ret && fdo) *fdo = EINA_TRUE; + } + + if (ret) + { + eina_stringshare_replace(&sd->stdicon, name); + _sizing_eval(obj); + return EINA_TRUE; + } + else + eina_stringshare_replace(&sd->stdicon, NULL); + + if (_path_is_absolute(name)) + { + if (fdo) + *fdo = EINA_FALSE; + return efl_file_set(obj, name, NULL); + } + + /* if that fails, see if icon name is in the format size/name. if so, + try locating a fallback without the size specification */ + if (!(tmp = strchr(name, '/'))) return EINA_FALSE; + ++tmp; + if (*tmp) return _internal_efl_ui_image_zoomable_icon_set(obj, tmp, fdo, resize); + /* give up */ + return EINA_FALSE; +} + +static void +_efl_ui_image_zoomable_icon_resize_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +{ + ELM_PHOTOCAM_DATA_GET(data, sd); + const char *refup = eina_stringshare_ref(sd->stdicon); + Eina_Bool fdo = EINA_FALSE; + + if (!_internal_efl_ui_image_zoomable_icon_set(obj, sd->stdicon, &fdo, EINA_TRUE) || (!fdo)) + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_RESIZE, _efl_ui_image_zoomable_icon_resize_cb, data); + eina_stringshare_del(refup); +} + +EOLIAN static Eina_Bool +_efl_ui_image_zoomable_efl_ui_image_icon_set(Eo *obj, Efl_Ui_Image_Zoomable_Data *pd EINA_UNUSED, const char *name) +{ + Eina_Bool fdo = EINA_FALSE; + + if (!name) return EINA_FALSE; + + evas_object_event_callback_del_full + (obj, EVAS_CALLBACK_RESIZE, _efl_ui_image_zoomable_icon_resize_cb, obj); + + Eina_Bool int_ret = _internal_efl_ui_image_zoomable_icon_set(obj, name, &fdo, EINA_FALSE); + + if (fdo) + evas_object_event_callback_add + (obj, EVAS_CALLBACK_RESIZE, _efl_ui_image_zoomable_icon_resize_cb, obj); + + return int_ret; +} + +EOLIAN static const char * +_efl_ui_image_zoomable_efl_ui_image_icon_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Zoomable_Data *pd) +{ + return pd->stdicon; +} + EOLIAN static Eina_Bool _efl_ui_image_zoomable_gesture_enabled_get(Eo *obj EINA_UNUSED, Efl_Ui_Image_Zoomable_Data *sd) { diff --git a/src/lib/elementary/efl_ui_image_zoomable.eo b/src/lib/elementary/efl_ui_image_zoomable.eo index 6cb5f0d663..cba8268f62 100644 --- a/src/lib/elementary/efl_ui_image_zoomable.eo +++ b/src/lib/elementary/efl_ui_image_zoomable.eo @@ -4,8 +4,6 @@ class Efl.Ui.Image.Zoomable (Efl.Ui.Image, Efl.Ui.Zoom, { [[Elementary Image Zoomable class]] legacy_prefix: elm_photocam; - //eo_prefix: elm_obj_photocam; - //event_prefix: elm_photocam; methods { @property gesture_enabled { set { @@ -53,6 +51,7 @@ class Efl.Ui.Image.Zoomable (Efl.Ui.Image, Efl.Ui.Zoom, Efl.Gfx.size { set; } Efl.Gfx.View.view_size { get; } Efl.Image.image_size { get; } + Efl.Ui.Image.icon { set; get; } Efl.Ui.Zoom.zoom_animation { set; get; } Efl.Ui.Zoom.zoom { set; get; } Efl.Ui.Zoom.zoom_mode { set; get; } diff --git a/src/lib/elementary/efl_ui_image_zoomable_private.h b/src/lib/elementary/efl_ui_image_zoomable_private.h index 7f1358e7dd..26c789f6a1 100644 --- a/src/lib/elementary/efl_ui_image_zoomable_private.h +++ b/src/lib/elementary/efl_ui_image_zoomable_private.h @@ -120,6 +120,13 @@ struct _Efl_Ui_Image_Zoomable_Data int no_smooth; int preload_num; + const char *stdicon; + Evas_Object *icon_edje; + struct { + int requested_size; + Eina_Bool use : 1; + } freedesktop; + Eina_List *grids; Efl_Orient orient; Efl_Flip flip; diff --git a/src/lib/elementary/elm_priv.h b/src/lib/elementary/elm_priv.h index e11855103b..c4aac1ad77 100644 --- a/src/lib/elementary/elm_priv.h +++ b/src/lib/elementary/elm_priv.h @@ -408,6 +408,8 @@ Eina_Bool _elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style); +Eina_File *_elm_theme_group_file_find(Elm_Theme *th, + const char *group); void _elm_theme_parse(Elm_Theme *th, const char *theme); void _elm_theme_shutdown(void); diff --git a/src/lib/elementary/elm_theme.c b/src/lib/elementary/elm_theme.c index a2ee5d6f0c..14beb6b110 100644 --- a/src/lib/elementary/elm_theme.c +++ b/src/lib/elementary/elm_theme.c @@ -203,7 +203,7 @@ _elm_theme_clear(Elm_Theme *th) } } -static Eina_File * +Eina_File * _elm_theme_group_file_find(Elm_Theme *th, const char *group) { const Eina_List *l; -- cgit v1.2.1