diff --git a/legacy/elementary/configure.in b/legacy/elementary/configure.in index 4bb00dacb9..47d7c2c867 100644 --- a/legacy/elementary/configure.in +++ b/legacy/elementary/configure.in @@ -45,7 +45,9 @@ case "$host_os" in AC_DEFINE(ELEMENTARY_BUILD, 1, [Define to mention that evas is built]) lt_enable_auto_import="-Wl,--enable-auto-import" ELM_WINCE_DEF="#define" - ;; +dnl managed by evil + AC_DEFINE(HAVE_DLADDR) + ;; mingw*) PKG_CHECK_MODULES([EVIL], [evil]) AC_DEFINE(HAVE_EVIL, 1, [Set to 1 if evil package is installed.]) @@ -56,8 +58,21 @@ case "$host_os" in ;; *) ELM_UNIX_DEF="#define" + AC_CHECK_FUNCS(dlopen, res=yes, res=no) + if test "x$res" = "xyes"; then + AC_CHECK_FUNCS(dladdr, AC_DEFINE(HAVE_DLADDR)) + else + AC_CHECK_LIB(dl, dlopen, res=yes, res=no) + if test "x$res" = "xyes"; then + AC_CHECK_LIB(dl, dladdr, AC_DEFINE(HAVE_DLADDR)) + dlopen_libs=-ldl + else + AC_MSG_ERROR(Cannot find dlopen) + fi + fi ;; esac +AC_SUBST(dlopen_libs) AC_SUBST(lt_enable_auto_import) AC_SUBST(ELM_UNIX_DEF) AC_SUBST(ELM_WIN32_DEF) diff --git a/legacy/elementary/elementary.pc.in b/legacy/elementary/elementary.pc.in index 2ea55aa25f..0564b12e5a 100644 --- a/legacy/elementary/elementary.pc.in +++ b/legacy/elementary/elementary.pc.in @@ -8,5 +8,5 @@ Description: Mobile device touchscreen widget library Requires: evas ecore ecore-x ecore-evas ecore-job ecore-txt ecore-file eet edje Version: @VERSION@ Libs: -L${libdir} -lelementary -Libs.private: @my_libs@ @ELEMENTARY_LIBS@ @ELEMENTARY_X_LIBS@ @ELEMENTARY_FB_LIBS@ @ELEMENTARY_WINCE_LIBS@ @ELEMENTARY_EDBUS_LIBS@ +Libs.private: @dlopen_libs@ @my_libs@ @ELEMENTARY_LIBS@ @ELEMENTARY_X_LIBS@ @ELEMENTARY_FB_LIBS@ @ELEMENTARY_WINCE_LIBS@ @ELEMENTARY_EDBUS_LIBS@ Cflags: -I${includedir} -I${includedir}/elementary @ELEMENTARY_CFLAGS@ @ELEMENTARY_X_CFLAGS@ @ELEMENTARY_FB_CFLAGS@ @ELEMENTARY_WINCE_CFLAGS@ @ELEMENTARY_EDBUS_CFLAGS@ diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 79c97f2954..123e8d00fb 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -432,7 +432,16 @@ extern "C" { * "selected" - when the user selected an item * "unselected" - when the user selected an item */ - + + typedef struct _Elm_Carousel_Item Elm_Carousel_Item; + EAPI Evas_Object *elm_carousel_add(Evas_Object *parent); + EAPI Elm_Carousel_Item *elm_carousel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data); + EAPI void elm_carousel_item_del(Elm_Carousel_Item *item); + EAPI void elm_carousel_item_select(Elm_Carousel_Item *item); + /* smart callbacks called: + * "clicked" - when the user clicks on a carousel item and becomes selected + */ + //////////////////////////////////////////////////////////////////////////// /// FIXME: TODO LIST /////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// diff --git a/legacy/elementary/src/lib/Makefile.am b/legacy/elementary/src/lib/Makefile.am index dfbd393409..0998a7a991 100644 --- a/legacy/elementary/src/lib/Makefile.am +++ b/legacy/elementary/src/lib/Makefile.am @@ -41,6 +41,7 @@ elm_bubble.c \ elm_photo.c \ elm_toolbar.c \ elm_list.c \ +elm_carousel.c \ \ elc_notepad.c \ elc_anchorview.c \ @@ -60,5 +61,5 @@ els_icon.h libelementary_la_CFLAGS = -libelementary_la_LIBADD = @ELEMENTARY_LIBS@ @ELEMENTARY_X_LIBS@ @ELEMENTARY_FB_LIBS@ @ELEMENTARY_WINCE_LIBS@ @ELEMENTARY_EDBUS_LIBS@ @my_libs@ +libelementary_la_LIBADD = @my_libs@ @dlopen_libs@ @ELEMENTARY_LIBS@ @ELEMENTARY_X_LIBS@ @ELEMENTARY_FB_LIBS@ @ELEMENTARY_WINCE_LIBS@ @ELEMENTARY_EDBUS_LIBS@ libelementary_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@ diff --git a/legacy/elementary/src/lib/elm_carousel.c b/legacy/elementary/src/lib/elm_carousel.c new file mode 100644 index 0000000000..02af673c72 --- /dev/null +++ b/legacy/elementary/src/lib/elm_carousel.c @@ -0,0 +1,259 @@ +#include +#include "elm_priv.h" + +// FIXME: this is NOT the carousel - yet! + +typedef struct _Widget_Data Widget_Data; +typedef struct _Item Item; + +struct _Widget_Data +{ + Evas_Object *scr, *bx; + Eina_List *items; + int icon_size; + Evas_Bool scrollable : 1; +}; + +struct _Item +{ + Evas_Object *obj; + Evas_Object *base; + const char *label; + Evas_Object *icon; + void (*func) (void *data, Evas_Object *obj, void *event_info); + const void *data; + Evas_Bool selected : 1; +}; + +static void _del_hook(Evas_Object *obj); +static void _theme_hook(Evas_Object *obj); +static void _sizing_eval(Evas_Object *obj); + +static void +_item_show(Item *it) +{ + Widget_Data *wd = elm_widget_data_get(it->obj); + Evas_Coord x, y, w, h, bx, by; + + evas_object_geometry_get(wd->bx, &bx, &by, NULL, NULL); + evas_object_geometry_get(it->base, &x, &y, &w, &h); + elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h); +} + +static void +_item_select(Item *it) +{ + Item *it2; + Widget_Data *wd = elm_widget_data_get(it->obj); + Evas_Object *obj2; + Eina_List *l; + if (it->selected) return; + for (l = wd->items; l; l = l->next) + { + it2 = l->data; + if (it2->selected) + { + it2->selected = 0; + edje_object_signal_emit(it2->base, "elm,state,unselected", "elm"); + break; + } + } + it->selected = 1; + edje_object_signal_emit(it->base, "elm,state,selected", "elm"); + _item_show(it); + obj2 = it->obj; + if (it->func) it->func((void *)(it->data), it->obj, it); + evas_object_smart_callback_call(obj2, "clicked", it); +} + +static void +_del_hook(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + free(wd); +} + +static void +_theme_hook(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + Eina_List *l; + Item *it; + Evas_Coord mw, mh; + for (l = wd->items; l; l = l->next) + { + it = l->data; + if (it->selected) + edje_object_signal_emit(it->base, "elm,state,selected", "elm"); + _elm_theme_set(it->base, "carousel", "item", "default"); + if (it->icon) + { + edje_extern_object_min_size_set(it->icon, + (double)wd->icon_size * _elm_config->scale, + (double)wd->icon_size * _elm_config->scale); + edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon); + } + edje_object_part_text_set(it->base, "elm.text", it->label); + edje_object_size_min_calc(it->base, &mw, &mh); + evas_object_size_hint_min_set(it->base, mw, mh); + evas_object_size_hint_max_set(it->base, 9999, mh); + } + _sizing_eval(obj); +} + +static void +_sizing_eval(Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; + Evas_Coord vw = 0, vh = 0; + + edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh); + evas_object_resize(wd->scr, 500, 500); + evas_object_size_hint_min_get(wd->bx, &minw, &minh); + evas_object_resize(wd->bx, minw, minh); + elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh); + if (wd->scrollable) + { + minw = 500 - vw; + minh = minh + (500 - vh); + } + else + { + minw = minw + (500 - vw); + minh = minh + (500 - vh); + } + evas_object_size_hint_min_set(obj, minw, minh); + evas_object_size_hint_max_set(obj, maxw, maxh); +} + +static void +_resize(void *data, Evas *e, Evas_Object *obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(data); + Evas_Coord mw, mh, vw, vh, w, h; + Eina_List *l; + Item *it; + + elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh); + evas_object_size_hint_min_get(wd->bx, &mw, &mh); + evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h); + if (vw >= mw) + { + if (w != vw) evas_object_resize(wd->bx, vw, h); + } + for (l = wd->items; l; l = l->next) + { + it = l->data; + if (it->selected) + { + _item_show(it); + break; + } + } + +} + +static void +_select(void *data, Evas_Object *obj, const char *emission, const char *source) +{ + _item_select(data); +} + +EAPI Evas_Object * +elm_carousel_add(Evas_Object *parent) +{ + Evas_Object *obj; + Evas *e; + Widget_Data *wd; + + wd = ELM_NEW(Widget_Data); + e = evas_object_evas_get(parent); + obj = elm_widget_add(e); + 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, 0); + + wd->scr = elm_smart_scroller_add(e); + elm_smart_scroller_theme_set(wd->scr, "carousel", "base", "default"); + elm_widget_resize_object_set(obj, wd->scr); + elm_smart_scroller_policy_set(wd->scr, + ELM_SMART_SCROLLER_POLICY_AUTO, + ELM_SMART_SCROLLER_POLICY_OFF); + + wd->icon_size = 32; + wd->scrollable = 1; + + wd->bx = _els_smart_box_add(e); + _els_smart_box_orientation_set(wd->bx, 1); + _els_smart_box_homogenous_set(wd->bx, 1); + elm_widget_sub_object_add(obj, wd->bx); + elm_smart_scroller_child_set(wd->scr, wd->bx); + evas_object_show(wd->bx); + + evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, + _resize, obj); + + _sizing_eval(obj); + return obj; +} + +EAPI Elm_Carousel_Item * +elm_carousel_item_add(Evas_Object *obj, Evas_Object *icon, const char *label, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data) +{ + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Coord mw, mh; + Item *it = calloc(1, sizeof(Item)); + if (!it) return NULL; + wd->items = eina_list_append(wd->items, it); + it->obj = obj; + it->label = eina_stringshare_add(label); + it->icon = icon; + it->func = func; + it->data = data; + it->base = edje_object_add(evas_object_evas_get(obj)); + _elm_theme_set(it->base, "carousel", "item", "default"); + edje_object_signal_callback_add(it->base, "elm,action,click", "elm", + _select, it); + elm_widget_sub_object_add(obj, it->base); + if (it->icon) + { + edje_extern_object_min_size_set(it->icon, + (double)wd->icon_size * _elm_config->scale, + (double)wd->icon_size * _elm_config->scale); + edje_object_part_swallow(it->base, "elm.swallow.icon", it->icon); + evas_object_show(it->icon); + elm_widget_sub_object_add(obj, it->icon); + } + edje_object_part_text_set(it->base, "elm.text", it->label); + edje_object_size_min_calc(it->base, &mw, &mh); + evas_object_size_hint_weight_set(it->base, 0.0, 0.0); + evas_object_size_hint_align_set(it->base, -1.0, -1.0); + evas_object_size_hint_min_set(it->base, mw, mh); + evas_object_size_hint_max_set(it->base, 9999, mh); + _els_smart_box_pack_end(wd->bx, it->base); + evas_object_show(it->base); + _sizing_eval(obj); + return (Elm_Carousel_Item *)it; +} + +EAPI void +elm_carousel_item_del(Elm_Carousel_Item *item) +{ + Item *it = (Item *)item; + Widget_Data *wd = elm_widget_data_get(it->obj); + Evas_Object *obj2 = it->obj; + wd->items = eina_list_remove(wd->items, it); + eina_stringshare_del(it->label); + if (it->icon) evas_object_del(it->icon); + evas_object_del(it->base); + free(it); + _theme_hook(obj2); +} + +EAPI void +elm_carousel_item_select(Elm_Carousel_Item *item) +{ + _item_select(item); +} diff --git a/legacy/elementary/src/lib/elm_main.c b/legacy/elementary/src/lib/elm_main.c index da8fd92bb5..ab6ddf340b 100644 --- a/legacy/elementary/src/lib/elm_main.c +++ b/legacy/elementary/src/lib/elm_main.c @@ -1,3 +1,9 @@ +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include /* dlopen,dlclose,etc */ + #ifdef HAVE_CONFIG_H # include "elementary_config.h" #endif @@ -9,6 +15,7 @@ #include #include "elm_priv.h" + static int _elm_signal_exit(void *data, int ev_type, void *ev); #ifdef HAVE_ELEMENTARY_X static int _elm_window_property_change(void *data, int ev_type, void *ev); @@ -17,9 +24,11 @@ static void _elm_rescale(void); char *_elm_appname = NULL; Elm_Config *_elm_config = NULL; -Ecore_Event_Handler *_elm_event_property_change = NULL; +const char *_elm_data_dir = NULL; + +static Ecore_Event_Handler *_elm_event_property_change = NULL; #ifdef HAVE_ELEMENTARY_X -Ecore_X_Atom _elm_atom_enlightenment_scale = 0; +static Ecore_X_Atom _elm_atom_enlightenment_scale = 0; #endif static int @@ -68,7 +77,8 @@ EAPI void elm_init(int argc, char **argv) { int i; - const char *elm_engine, *elm_scale; + const char *elm_engine, *elm_scale, *elm_theme, *elm_prefix, *elm_data_dir; + char buf[PATH_MAX]; eet_init(); ecore_init(); @@ -84,7 +94,56 @@ elm_init(int argc, char **argv) elm_engine = getenv("ELM_ENGINE"); elm_scale = getenv("ELM_SCALE"); + elm_theme = getenv("ELM_THEME"); + elm_prefix = getenv("ELM_PREFIX"); + elm_data_dir = getenv("ELM_DATA_DIR"); + if (!_elm_data_dir) + { + _elm_data_dir = eina_stringshare_add(elm_data_dir); + } + if (!_elm_data_dir) + { + if (elm_prefix) + { + snprintf(buf, sizeof(buf), "%s/share/elementary", elm_prefix); + _elm_data_dir = eina_stringshare_add(buf); + } + } +#ifdef HAVE_DLADDR + if (!_elm_data_dir) + { + Dl_info elementary_dl; + // libelementary.so/../../share/elementary/ + if (dladdr(elm_init, &elementary_dl)) + { + char *dir, *dir2; + + dir = ecore_file_dir_get(elementary_dl.dli_fname); + if (dir) + { + dir2 = ecore_file_dir_get(dir); + if (dir2) + { + snprintf(buf, sizeof(buf), "%s/share/elementary", dir2); + if (ecore_file_is_dir(buf)) + _elm_data_dir = eina_stringshare_add(buf); + free(dir2); + } + free(dir); + } + } + } +#endif + if (!_elm_data_dir) + { + _elm_data_dir = eina_stringshare_add(PACKAGE_DATA_DIR); + } + if (!_elm_data_dir) + { + _elm_data_dir = eina_stringshare_add("/"); + } + // FIXME: actually load config _elm_config = ELM_NEW(Elm_Config); _elm_config->engine = ELM_SOFTWARE_X11; @@ -157,9 +216,13 @@ elm_init(int argc, char **argv) } if (elm_scale) - { - _elm_config->scale = atof(elm_scale); - } + _elm_config->scale = atof(elm_scale); + + if (elm_theme) + _elm_theme_parse(elm_theme); + else + _elm_theme_parse("default"); + /* FIXME: implement quickstart below */ /* if !quickstart return * else @@ -200,6 +263,9 @@ elm_shutdown(void) ecore_x_shutdown(); #endif } + + eina_stringshare_del(_elm_data_dir); + _elm_data_dir = NULL; free(_elm_config); free(_elm_appname); diff --git a/legacy/elementary/src/lib/elm_priv.h b/legacy/elementary/src/lib/elm_priv.h index cd30d335f7..dbbb1d6c53 100644 --- a/legacy/elementary/src/lib/elm_priv.h +++ b/legacy/elementary/src/lib/elm_priv.h @@ -52,7 +52,8 @@ void _elm_win_rescale(void); int _elm_theme_set(Evas_Object *o, const char *clas, const char *group, const char *style); int _elm_theme_icon_set(Evas_Object *o, const char *group, const char *style); - +int _elm_theme_parse(const char *theme); + /* FIXME: should this be public? for now - private (but public symbols) */ EAPI Evas_Object *elm_widget_add(Evas *evas); EAPI void elm_widget_del_hook_set(Evas_Object *obj, void (*func) (Evas_Object *obj)); @@ -92,7 +93,7 @@ EAPI void elm_widget_scroll_hold_pop(Evas_Object *obj); EAPI int elm_widget_scroll_hold_get(Evas_Object *obj); extern char *_elm_appname; - extern Elm_Config *_elm_config; +extern const char *_elm_data_dir; #endif diff --git a/legacy/elementary/src/lib/elm_theme.c b/legacy/elementary/src/lib/elm_theme.c index 60dff78827..6e51f4f1ea 100644 --- a/legacy/elementary/src/lib/elm_theme.c +++ b/legacy/elementary/src/lib/elm_theme.c @@ -1,39 +1,154 @@ #include #include "elm_priv.h" +static Eina_List *themes = NULL; +static Eina_Hash *cache = NULL; + +static const char * +_elm_theme_group_file_find(const char *group) +{ + Eina_List *l; + char buf[PATH_MAX]; + char *p; + static const char *home = NULL; + const char *file = eina_hash_find(cache, group); + if (file) return file; + if (!home) + { + home = getenv("HOME"); + if (!home) home = ""; + } + for (l = themes; l; l = l->next) + { + snprintf(buf, sizeof(buf), "%s/.elementary/themes/%s.edj", home, l->data); + if (edje_file_group_exists(buf, group)) + { + file = eina_stringshare_add(buf); + if (file) + { + eina_hash_add(cache, group, file); + return file; + } + } + snprintf(buf, sizeof(buf), "%s/themes/%s.edj", PACKAGE_DATA_DIR, l->data); + if (edje_file_group_exists(buf, group)) + { + file = eina_stringshare_add(buf); + if (file) + { + eina_hash_add(cache, group, file); + return file; + } + } + } + return NULL; +} + int _elm_theme_set(Evas_Object *o, const char *clas, const char *group, const char *style) { - char buf[PATH_MAX]; + const char *file; char buf2[1024]; int ok; - // FIXME: actually handle themes for real - snprintf(buf, sizeof(buf), "%s/themes/%s.edj", PACKAGE_DATA_DIR, "default"); snprintf(buf2, sizeof(buf2), "elm/%s/%s/%s", clas, group, style); - ok = edje_object_file_set(o, buf, buf2); - if (ok) return 1; + file = _elm_theme_group_file_find(buf2); + if (file) + { + ok = edje_object_file_set(o, file, buf2); + if (ok) return 1; + } snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group); - ok = edje_object_file_set(o, buf, buf2); + file = _elm_theme_group_file_find(buf2); + if (!file) return 0; + ok = edje_object_file_set(o, file, buf2); return ok; } int _elm_theme_icon_set(Evas_Object *o, const char *group, const char *style) { - char buf[PATH_MAX]; + const char *file; char buf2[1024]; int w, h; int ok; - // FIXME: actually handle themes for real - snprintf(buf, sizeof(buf), "%s/themes/%s.edj", PACKAGE_DATA_DIR, "default"); snprintf(buf2, sizeof(buf2), "elm/icon/%s/%s", group, style); - _els_smart_icon_file_edje_set(o, buf, buf2); - _els_smart_icon_size_get(o, &w, &h); - if (w > 0) return 1; + file = _elm_theme_group_file_find(buf2); + if (file) + { + _els_smart_icon_file_edje_set(o, file, buf2); + _els_smart_icon_size_get(o, &w, &h); + if (w > 0) return 1; + } snprintf(buf2, sizeof(buf2), "elm/icon/%s/default", group); - _els_smart_icon_file_edje_set(o, buf, buf2); + file = _elm_theme_group_file_find(buf2); + if (!file) return 0; + _els_smart_icon_file_edje_set(o, file, buf2); _els_smart_icon_size_get(o, &w, &h); return (w > 0); } + +static Eina_Bool +_cache_free_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata) +{ + eina_stringshare_del(data); +} + +int +_elm_theme_parse(const char *theme) +{ + Eina_List *names = NULL; + const char *p, *pe; + + p = theme; + pe = p; + for (;;) + { + if ((*pe == '/') || (*pe == 0)) + { // p -> pe == 'name/' + if (pe > p) + { + char *n = malloc(pe - p + 1); + if (n) + { + const char *nn; + strncpy(n, p, pe - p); + n[pe - p] = 0; + nn = eina_stringshare_add(n); + if (nn) + names = eina_list_append(names, nn); + free(n); + } + } + if (*pe == 0) break; + p = pe + 1; + pe = p; + } + else + pe++; + } + p = eina_list_data_get(eina_list_last(names)); + if ((!p) || ((p) && (strcmp(p, "default")))) + { + p = eina_stringshare_add("default"); + if (p) + names = eina_list_append(names, p); + } + if (cache) + { + eina_hash_foreach(cache, _cache_free_cb, NULL); + eina_hash_free(cache); + cache = NULL; + } + cache = eina_hash_string_superfast_new(NULL); + + while (themes) + { + eina_stringshare_del(themes->data); + themes = eina_list_remove_list(themes, themes); + } + + themes = names; + return 1; +} diff --git a/legacy/elementary/src/lib/elm_toolbar.c b/legacy/elementary/src/lib/elm_toolbar.c index 828dc63825..1a8d83cf3a 100644 --- a/legacy/elementary/src/lib/elm_toolbar.c +++ b/legacy/elementary/src/lib/elm_toolbar.c @@ -60,7 +60,7 @@ _item_select(Item *it) edje_object_signal_emit(it->base, "elm,state,selected", "elm"); _item_show(it); obj2 = it->obj; - if (it->func) it->func(it->data, it->obj, it); + if (it->func) it->func((void *)(it->data), it->obj, it); evas_object_smart_callback_call(obj2, "clicked", it); }