From eeeb5214a15e4079b84b7fcee876c3ce470d45d1 Mon Sep 17 00:00:00 2001 From: Bruno Dilly Date: Thu, 7 Oct 2010 18:44:43 +0000 Subject: [PATCH] Add yet another kind of list widget to elm - diskpicker This is one more widget whose idea come from Samsung set of contributions to Elementary. SVN revision: 53150 --- legacy/elementary/data/themes/bar_shine.png | Bin 0 -> 3045 bytes legacy/elementary/data/themes/default.edc | 186 +++ legacy/elementary/src/bin/Makefile.am | 3 +- legacy/elementary/src/bin/test.c | 2 + legacy/elementary/src/bin/test_diskpicker.c | 122 ++ legacy/elementary/src/lib/Elementary.h.in | 38 + legacy/elementary/src/lib/Makefile.am | 1 + legacy/elementary/src/lib/elm_diskpicker.c | 1429 +++++++++++++++++++ 8 files changed, 1780 insertions(+), 1 deletion(-) create mode 100644 legacy/elementary/data/themes/bar_shine.png create mode 100644 legacy/elementary/src/bin/test_diskpicker.c create mode 100644 legacy/elementary/src/lib/elm_diskpicker.c diff --git a/legacy/elementary/data/themes/bar_shine.png b/legacy/elementary/data/themes/bar_shine.png new file mode 100644 index 0000000000000000000000000000000000000000..95df605ac943baacf7f5ed80f2309ae6c9b78535 GIT binary patch literal 3045 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 literal 0 HcmV?d00001 diff --git a/legacy/elementary/data/themes/default.edc b/legacy/elementary/data/themes/default.edc index 9205237006..abc3246681 100644 --- a/legacy/elementary/data/themes/default.edc +++ b/legacy/elementary/data/themes/default.edc @@ -27860,3 +27860,189 @@ collections { } } } + +//////////////////////////////////////////////////////////////////////////////// +// diskpicker +//////////////////////////////////////////////////////////////////////////////// + group { name: "elm/diskpicker/base/default"; + images { + image: "bar_shine.png" COMP; + } + + parts { + part { name: "bg"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + color: 0 0 0 255; + } + } + part { name: "shine_left"; + mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "bg"; + rel1.relative: -0.1 0; + rel2.to: "bg"; + rel2.relative: 0.1 1; + image.normal: "bar_shine.png"; + color: 255 255 255 120; + } + } + part { name: "shine_center"; + mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "bg"; + rel1.relative: 0.2 0; + rel2.to: "bg"; + rel2.relative: 0.8 1; + image.normal: "bar_shine.png"; + color: 255 255 255 180; + } + } + part { name: "shine_right"; + mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "bg"; + rel1.relative: 0.9 0; + rel2.to: "bg"; + rel2.relative: 1.1 1; + image.normal: "bar_shine.png"; + color: 255 255 255 120; + } + } + part { name: "clipper"; + type: RECT; + mouse_events: 0; + description { state: "default" 0.0; + rel1.to: "bg"; + rel2.to: "bg"; + rel1.offset: 2 2; + rel2.offset: -3 -3; + } + } + part { name: "elm.swallow.content"; + clip_to: "clipper"; + type: SWALLOW; + description { state: "default" 0.0; + rel1.to: "bg"; + rel2.to: "bg"; + } + } + } + } + + group { name: "elm/diskpicker/item/default"; + + data { + item: "len_threshold" "14"; + } + + parts { + part { name: "elm.swallow.icon"; + type: SWALLOW; + description { state: "default" 0.0; + fixed: 1 0; + align: 0.0 0.5; + rel1 { + relative: 0 0; + offset: 4 4; + } + rel2 { + relative: 0 1; + offset: 4 -5; + } + } + description { state: "show" 0.0; + inherit: "default" 0.0; + } + description { state: "default_small" 0.0; + inherit: "default" 0.0; + rel1.relative: 0 0.2; + rel2.relative: 0 0.8; + } + description { state: "left_side" 0.0; + inherit: "default" 0.0; + rel1.relative: 0 0.2; + rel2.relative: 0 0.8; + color: 255 255 255 160; + } + description { state: "right_side" 0.0; + inherit: "left_side" 0.0; + rel1.relative: 0.4 0.2; + rel2.relative: 0.4 0.8; + color: 255 255 255 160; + } + } + part { name: "elm.text"; + type: TEXT; + mouse_events: 0; + scale: 1; + description { state: "default" 0.0; + rel1.relative: 1 0.0; + rel1.to_x: "elm.swallow.icon"; + rel2.relative: 1.0 1.0; + color: 255 255 255 255; + visible: 0; + text { + font: "Sans,Edje-Vera"; + size: 13; + align: 0.5 0.5; + } + } + description { state: "show" 0.0; + inherit: "default" 0.0; + visible: 1; + } + description { state: "default_small" 0.0; + inherit: "default" 0.0; + visible: 1; + text.size: 10; + } + description { state: "left_side" 0.0; + inherit: "default" 0.0; + color: 172 172 172 255; + text.size: 10; + visible: 1; + text.align: 0.2 0.5; + } + description { state: "right_side" 0.0; + inherit: "default" 0.0; + color: 172 172 172 255; + visible: 1; + text.size: 10; + text.align: 0.8 0.5; + } + } + } + + programs { + program { name: "center_text"; + signal: "elm,state,center"; + source: "elm"; + action: STATE_SET "show" 0.0; + target: "elm.text"; + target: "elm.swallow.icon"; + } + program { name: "center_small_text"; + signal: "elm,state,center_small"; + source: "elm"; + action: STATE_SET "default_small" 0.0; + target: "elm.text"; + target: "elm.swallow.icon"; + } + program { name: "l_side_text"; + signal: "elm,state,left_side"; + source: "elm"; + action: STATE_SET "left_side" 0.0; + target: "elm.text"; + target: "elm.swallow.icon"; + } + program { name: "r_side_text"; + signal: "elm,state,right_side"; + source: "elm"; + action: STATE_SET "right_side" 0.0; + target: "elm.text"; + target: "elm.swallow.icon"; + } + } + } diff --git a/legacy/elementary/src/bin/Makefile.am b/legacy/elementary/src/bin/Makefile.am index bda07f66fc..b58e0945f0 100644 --- a/legacy/elementary/src/bin/Makefile.am +++ b/legacy/elementary/src/bin/Makefile.am @@ -87,7 +87,8 @@ test_tooltip.c \ test_cursor.c \ test_focus.c \ test_focus2.c \ -test_flippicker.c +test_flippicker.c \ +test_diskpicker.c elementary_test_LDADD = $(top_builddir)/src/lib/libelementary.la @ELEMENTARY_EWEATHER_LIBS@ elementary_test_LDFLAGS = diff --git a/legacy/elementary/src/bin/test.c b/legacy/elementary/src/bin/test.c index 28ba8014cb..3b894f6d08 100644 --- a/legacy/elementary/src/bin/test.c +++ b/legacy/elementary/src/bin/test.c @@ -88,6 +88,7 @@ void test_cursor3(void *data, Evas_Object *obj, void *event_info); void test_focus(void *data, Evas_Object *obj, void *event_info); void test_focus2(void *data, Evas_Object *obj, void *event_info); void test_flippicker(void *data, Evas_Object *obj, void *event_info); +void test_diskpicker(void *data, Evas_Object *obj, void *event_info); struct elm_test { @@ -296,6 +297,7 @@ my_win_main(char *autorun) ADD_TEST("Focus", test_focus); ADD_TEST("Focus 2", test_focus2); ADD_TEST("Flippicker", test_flippicker); + ADD_TEST("Diskpicker", test_diskpicker); #undef ADD_TEST if (autorun) diff --git a/legacy/elementary/src/bin/test_diskpicker.c b/legacy/elementary/src/bin/test_diskpicker.c new file mode 100644 index 0000000000..bc3c3a2297 --- /dev/null +++ b/legacy/elementary/src/bin/test_diskpicker.c @@ -0,0 +1,122 @@ +#include +#ifndef ELM_LIB_QUICKLAUNCH + +static void +_disk_sel(void *data, Evas_Object * obj, void *event_info) +{ + Elm_Diskpicker_Item *it = event_info; + printf("Equinox: %s\n", elm_diskpicker_item_label_get(it)); +} + +static void +_disk_next(void *data, Evas_Object * obj, void *event_info) +{ + Elm_Diskpicker_Item *next, *prev, *it = event_info; + prev = elm_diskpicker_item_prev(it); + next = elm_diskpicker_item_next(it); + printf("Prev: %s, Next: %s\n", elm_diskpicker_item_label_get(prev), + elm_diskpicker_item_label_get(next)); +} + +static void +_print_disk_info_cb(void *data, Evas_Object *obj, void *event_info) +{ + Elm_Diskpicker_Item *it = event_info; + printf("Selected label: %s\n", elm_diskpicker_item_label_get(it)); +} + +static Evas_Object * +_disk_create(Evas_Object *win, Eina_Bool round) +{ + Elm_Diskpicker_Item *it; + Evas_Object *di; + + di = elm_diskpicker_add(win); + + elm_diskpicker_item_append(di, "January", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "February", NULL, _disk_next, NULL); + elm_diskpicker_item_append(di, "March", NULL, _disk_sel, NULL); + elm_diskpicker_item_append(di, "April", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "May", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "June", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "July", NULL, NULL, NULL); + it = elm_diskpicker_item_append(di, "August", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "September", NULL, _disk_sel, NULL); + elm_diskpicker_item_append(di, "October", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "November", NULL, NULL, NULL); + elm_diskpicker_item_append(di, "December", NULL, NULL, NULL); + + elm_diskpicker_item_selected_set(it); + elm_diskpicker_round_set(di, round); + + return di; +} + +void +test_diskpicker(void *data, Evas_Object *obj, void *event_info) +{ + Evas_Object *win, *bg, *bx, *disk, *ic; + char buf[PATH_MAX]; + + win = elm_win_add(NULL, "diskpicker", ELM_WIN_BASIC); + elm_win_title_set(win, "Diskpicker"); + elm_win_autodel_set(win, 1); + + bg = elm_bg_add(win); + elm_win_resize_object_add(win, bg); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bg, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(bg); + + bx = elm_box_add(win); + elm_win_resize_object_add(win, bx); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(bx, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(bx); + + disk = _disk_create(win, EINA_TRUE); + evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5); + elm_box_pack_end(bx, disk); + evas_object_show(disk); + evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL); + + disk = _disk_create(win, EINA_FALSE); + evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5); + elm_box_pack_end(bx, disk); + evas_object_show(disk); + evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL); + + disk = _disk_create(win, EINA_FALSE); + evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5); + elm_box_pack_end(bx, disk); + evas_object_show(disk); + evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL); + elm_diskpicker_side_label_lenght_set(disk, 4); + + disk = elm_diskpicker_add(win); + ic = elm_icon_add(win); + snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR); + elm_icon_file_set(ic, buf, NULL); + elm_icon_scale_set(ic, 1, 1); + elm_diskpicker_item_append(disk, "Sunday", ic, NULL, NULL); + elm_diskpicker_item_append(disk, "Monday", NULL, NULL, NULL); + elm_diskpicker_item_append(disk, "Tuesday", NULL, NULL, NULL); + elm_diskpicker_item_append(disk, "Wednesday", NULL, NULL, NULL); + elm_diskpicker_item_append(disk, "Thursday", NULL, NULL, NULL); + elm_diskpicker_item_append(disk, "Friday", NULL, NULL, NULL); + elm_diskpicker_item_append(disk, "Saturday", NULL, NULL, NULL); + elm_diskpicker_round_set(disk, EINA_TRUE); + evas_object_size_hint_weight_set(disk, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(disk, EVAS_HINT_FILL, 0.5); + elm_box_pack_end(bx, disk); + evas_object_show(disk); + evas_object_smart_callback_add(disk, "selected", _print_disk_info_cb, NULL); + + evas_object_resize(win, 320, 480); + evas_object_show(win); +} + +#endif diff --git a/legacy/elementary/src/lib/Elementary.h.in b/legacy/elementary/src/lib/Elementary.h.in index 511c48fb0d..e71ed3a510 100644 --- a/legacy/elementary/src/lib/Elementary.h.in +++ b/legacy/elementary/src/lib/Elementary.h.in @@ -1869,6 +1869,44 @@ extern "C" { * month. */ + /* diskpicker */ + typedef struct _Elm_Diskpicker_Item Elm_Diskpicker_Item; + + EAPI Evas_Object *elm_diskpicker_add(Evas_Object *parent); + EAPI Eina_Bool elm_diskpicker_round_get(const Evas_Object *obj); + EAPI void elm_diskpicker_round_set(Evas_Object *obj, Eina_Bool round); + EAPI int elm_diskpicker_side_label_lenght_get(const Evas_Object *obj); + EAPI void elm_diskpicker_side_label_lenght_set(Evas_Object *obj, int len); + EAPI void elm_diskpicker_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce); + EAPI void elm_diskpicker_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v); + EAPI void elm_diskpicker_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v); + EAPI void elm_diskpicker_clear(Evas_Object *obj); + EAPI const Eina_List *elm_diskpicker_items_get(const Evas_Object *obj); + EAPI Elm_Diskpicker_Item *elm_diskpicker_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data); + EAPI void elm_diskpicker_item_del(Elm_Diskpicker_Item *it); + EAPI void elm_diskpicker_item_del_cb_set(Elm_Diskpicker_Item *item, Evas_Smart_Cb func); + EAPI void *elm_diskpicker_item_data_get(const Elm_Diskpicker_Item *item); + EAPI Evas_Object *elm_diskpicker_item_icon_get(const Elm_Diskpicker_Item *item); + EAPI void elm_diskpicker_item_icon_set(Elm_Diskpicker_Item *item, Evas_Object *icon); + EAPI const char *elm_diskpicker_item_label_get(const Elm_Diskpicker_Item *it); + EAPI void elm_diskpicker_item_label_set(Elm_Diskpicker_Item *it, const char *label); + EAPI Elm_Diskpicker_Item *elm_diskpicker_item_selected_get(const Evas_Object *obj); + EAPI void elm_diskpicker_item_selected_set(Elm_Diskpicker_Item *it); + EAPI Elm_Diskpicker_Item *elm_diskpicker_item_prev(const Elm_Diskpicker_Item *it); + EAPI Elm_Diskpicker_Item *elm_diskpicker_item_next(const Elm_Diskpicker_Item *it); + EAPI void elm_diskpicker_item_tooltip_content_cb_set(Elm_Diskpicker_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb); + EAPI void elm_diskpicker_item_tooltip_unset(Elm_Diskpicker_Item *item); + EAPI void elm_diskpicker_item_tooltip_style_set(Elm_Diskpicker_Item *item, const char *style); + EAPI const char* elm_diskpicker_item_tooltip_style_get(const Elm_Diskpicker_Item *item); + EAPI void elm_diskpicker_item_cursor_set(Elm_Diskpicker_Item *item, const char *cursor); + EAPI void elm_diskpicker_item_cursor_unset(Elm_Diskpicker_Item *item); + EAPI const char* elm_diskpicker_item_cursor_style_get(const Elm_Diskpicker_Item *item); + EAPI void elm_diskpicker_item_cursor_engine_only_set(Elm_Diskpicker_Item *item, Eina_Bool engine_only); + EAPI Eina_Bool elm_diskpicker_item_cursor_engine_only_get(const Elm_Diskpicker_Item *item); + /* smart callbacks called: + * "selected" - when item is selected (scroller stops) + */ + /* debug * don't use it unless you are sure */ diff --git a/legacy/elementary/src/lib/Makefile.am b/legacy/elementary/src/lib/Makefile.am index f9572aad73..475284e851 100644 --- a/legacy/elementary/src/lib/Makefile.am +++ b/legacy/elementary/src/lib/Makefile.am @@ -83,6 +83,7 @@ elm_config.c \ elm_animator.c \ elm_calendar.c \ elm_flippicker.c \ +elm_diskpicker.c \ \ elc_anchorblock.c \ elc_anchorview.c \ diff --git a/legacy/elementary/src/lib/elm_diskpicker.c b/legacy/elementary/src/lib/elm_diskpicker.c new file mode 100644 index 0000000000..5e59579b79 --- /dev/null +++ b/legacy/elementary/src/lib/elm_diskpicker.c @@ -0,0 +1,1429 @@ +/** + * @defgroup Diskpicker + * + * A diskpicker is a kind of list widget. It scrolls horizontally, + * and can contain label and icon objects. Three items are displayed + * with the selected on the middle. + * + * It can act like a circular list with round mode and labels can be + * reduced for a defined lenght for side items. + * + * Signal emitted by this widget: + * "selected" - when item is selected (scroller stops) + */ + +#include +#include "elm_priv.h" + +typedef struct _Widget_Data Widget_Data; + +struct _Widget_Data +{ + Evas_Object *self; + Evas_Object *scroller; + Evas_Object *main_box; + Evas_Object *left_blank; + Evas_Object *right_blank; + Elm_Diskpicker_Item *selected_item; + Elm_Diskpicker_Item *first; + Elm_Diskpicker_Item *second; + Elm_Diskpicker_Item *s_last; + Elm_Diskpicker_Item *last; + Eina_List *items; + Eina_List *r_items; + int item_count, len_threshold, len_side; + Ecore_Idler *idler; + Ecore_Idler *check_idler; + Eina_Bool init:1; + Eina_Bool round:1; +}; + +struct _Elm_Diskpicker_Item +{ + Elm_Widget_Item base; + Eina_List *node; + Evas_Object *icon; + const char *label; + Evas_Smart_Cb func; +}; + +static const char *widtype = NULL; + +#define ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, ...) \ + ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \ + ELM_CHECK_WIDTYPE(it->base.widget, widtype) __VA_ARGS__; + +static Eina_Bool _move_scroller(void *data); +static void _del_hook(Evas_Object * obj); +static void _del_pre_hook(Evas_Object * obj); +static void _sizing_eval(Evas_Object * obj); +static void _theme_hook(Evas_Object * obj); +static void _on_focus_hook(void *data, Evas_Object *obj); +static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info); +static void _sub_del(void *data, Evas_Object * obj, void *event_info); +static void _round_items_del(Widget_Data *wd); +static void _scroller_move_cb(void *data, Evas_Object *obj, void *event_info); + +static const char SIG_SELECTED[] = "selected"; +static const Evas_Smart_Cb_Description _signals[] = { + {SIG_SELECTED, ""}, + {NULL, NULL} +}; + +static void +_diskpicker_object_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) +{ + Widget_Data *wd; + Evas_Coord w, h, minw = -1, minh = -1; + + wd = elm_widget_data_get(data); + if (!wd) return; + + elm_coords_finger_size_adjust(6, &minw, 1, &minh); + edje_object_size_min_restricted_calc(elm_smart_scroller_edje_object_get( + wd->scroller), &minw, &minh, minw, minh); + evas_object_size_hint_min_set(obj, minw, minh); + evas_object_size_hint_max_set(obj, -1, -1); + + evas_object_geometry_get(wd->scroller, NULL, NULL, &w, &h); + if (wd->round) + evas_object_resize(wd->main_box, w / 3 * (wd->item_count + 4), h); + else + evas_object_resize(wd->main_box, w / 3 * (wd->item_count + 2), h); + + elm_smart_scroller_paging_set(wd->scroller, 0, 0, + (int)(w / 3), 0); + + if (!wd->idler) + wd->idler = ecore_idler_add(_move_scroller, data); +} + +static Elm_Diskpicker_Item * +_item_new(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data) +{ + Elm_Diskpicker_Item *it; + const char *style = elm_widget_style_get(obj); + + it = elm_widget_item_new(obj, Elm_Diskpicker_Item); + if (!it) return NULL; + + it->label = eina_stringshare_add(label); + it->icon = icon; + it->func = func; + it->base.data = data; + it->base.view = edje_object_add(evas_object_evas_get(obj)); + _elm_theme_object_set(obj, it->base.view, "diskpicker", "item", style); + evas_object_size_hint_weight_set(it->base.view, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(it->base.view, EVAS_HINT_FILL, + EVAS_HINT_FILL); + evas_object_show(it->base.view); + + if (it->label) + edje_object_part_text_set(it->base.view, "elm.text", it->label); + if (it->icon) + { + evas_object_size_hint_min_set(it->icon, 24, 24); + evas_object_size_hint_max_set(it->icon, 40, 40); + edje_object_part_swallow(it->base.view, "elm.swallow.icon", it->icon); + evas_object_show(it->icon); + elm_widget_sub_object_add(obj, it->icon); + } + return it; +} + +static void +_item_del(Elm_Diskpicker_Item *item) +{ + if (!item) return; + eina_stringshare_del(item->label); + if (item->icon) + evas_object_del(item->icon); + elm_widget_item_del(item); +} + +static void +_theme_data_get(Widget_Data *wd) +{ + const char* str; + str = edje_object_data_get(wd->right_blank, "len_threshold"); + if (str) wd->len_threshold = atoi(str); + else wd->len_threshold = 0; +} + +static void +_del_hook(Evas_Object * obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + free(wd); +} + +static void +_del_pre_hook(Evas_Object * obj) +{ + Elm_Diskpicker_Item *it; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + + if (wd->left_blank) + evas_object_del(wd->left_blank); + if (wd->right_blank) + evas_object_del(wd->right_blank); + if (wd->last) + { + eina_stringshare_del(wd->last->label); + evas_object_del(wd->last->base.view); + free(wd->last); + } + if (wd->s_last) + { + eina_stringshare_del(wd->s_last->label); + evas_object_del(wd->s_last->base.view); + free(wd->s_last); + } + if (wd->second) + { + eina_stringshare_del(wd->second->label); + evas_object_del(wd->second->base.view); + free(wd->second); + } + if (wd->first) + { + eina_stringshare_del(wd->first->label); + evas_object_del(wd->first->base.view); + free(wd->first); + } + + EINA_LIST_FREE(wd->items, it) _item_del(it); + eina_list_free(wd->r_items); +} + +static void +_sizing_eval(Evas_Object * obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + _diskpicker_object_resize(obj, NULL, obj, NULL); +} + +static void +_theme_hook(Evas_Object * obj) +{ + Eina_List *l; + Elm_Diskpicker_Item *it; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + + if (wd->scroller) + elm_smart_scroller_object_theme_set(obj, wd->scroller, "diskpicker", + "base", elm_widget_style_get(obj)); + if (wd->round) + { + EINA_LIST_FOREACH(wd->r_items, l, it) + { + _elm_theme_object_set(obj, it->base.view, "diskpicker", "item", + elm_widget_style_get(obj)); + } + } + else + { + EINA_LIST_FOREACH(wd->items, l, it) + { + _elm_theme_object_set(obj, it->base.view, "diskpicker", "item", + elm_widget_style_get(obj)); + } + } + _theme_data_get(wd); + _sizing_eval(obj); +} + +static void +_sub_del(void *data __UNUSED__, Evas_Object * obj, void *event_info) +{ + Widget_Data *wd = elm_widget_data_get(obj); + Evas_Object *sub = event_info; + Elm_Diskpicker_Item *it; + const Eina_List *l; + + if (!wd) return; + if (!sub) abort(); + if (sub == wd->scroller) + wd->scroller = NULL; + else + { + EINA_LIST_FOREACH(wd->items, l, it) + { + if (sub == it->icon) + { + it->icon = NULL; + _sizing_eval(obj); + break; + } + } + } +} + +static void +_select_item(Elm_Diskpicker_Item *it) +{ + if (!it) return; + Widget_Data *wd = elm_widget_data_get(it->base.widget); + wd->selected_item = it; + if (it->func) it->func((void *)it->base.data, it->base.widget, it); + evas_object_smart_callback_call(it->base.widget, SIG_SELECTED, it); +} + +static void +_on_focus_hook(void *data __UNUSED__, Evas_Object *obj) +{ + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) + return; + + if (elm_widget_focus_get(obj)) + { + edje_object_signal_emit(wd->self, "elm,action,focus", "elm"); + evas_object_focus_set(wd->self, EINA_TRUE); + } + else + { + edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm"); + evas_object_focus_set(wd->self, EINA_FALSE); + } +} + +static Eina_Bool +_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info) +{ + if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; + Evas_Event_Key_Down *ev = event_info; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; + if (elm_widget_disabled_get(obj)) return EINA_FALSE; + + Elm_Diskpicker_Item *it = NULL; + Eina_List *l; + + if (!wd->selected_item) { + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + return EINA_TRUE; + } + + if (!strcmp(ev->keyname, "Left") || !strcmp(ev->keyname, "KP_Left") || + !strcmp(ev->keyname, "Up") || !strcmp(ev->keyname, "KP_Up")) + { + l = wd->selected_item->node->prev; + if (!l && wd->round) + l = eina_list_last(wd->items); + } + else if (!strcmp(ev->keyname, "Right") || !strcmp(ev->keyname, "KP_Right") || + !strcmp(ev->keyname, "Down") || !strcmp(ev->keyname, "KP_Down")) + { + l = wd->selected_item->node->next; + if (!l && wd->round) + l = wd->items; + } + else if (!strcmp(ev->keyname, "Home")) + l = wd->items; + else if (!strcmp(ev->keyname, "End")) + l = eina_list_last(wd->items); + else return EINA_FALSE; + + if (l) + it = eina_list_data_get(l); + + if (it) + { + wd->selected_item = it; + if (!wd->idler) + wd->idler = ecore_idler_add(_move_scroller, obj); + } + + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + return EINA_TRUE; +} + +static int +_check_letter(const char *str, int length) +{ + int code = str[length]; + + if (code == '\0') + return length; // null string + else if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) + return length; // alphabet + else if (48 <= code && code < 58) + return length; // number + else if ((33 <= code && code < 47) || (58 <= code && code < 64) + || (91 <= code && code < 96) || (123 <= code && code < 126)) + return length; // special letter + return length - 1; +} + +static Eina_Bool +_check_string(void *data) +{ + int mid, steps, length, diff, len; + Elm_Diskpicker_Item *it; + Eina_List *list, *l; + Evas_Coord ox, ow; + char buf[1024]; + Widget_Data *wd = data; + + evas_object_geometry_get(wd->scroller, &ox, NULL, &ow, NULL); + if (ow <= 0) + return EINA_FALSE; + if (!wd->init) + return EINA_FALSE; + if (!wd->round) + list = wd->items; + else + list = wd->r_items; + + EINA_LIST_FOREACH(list, l, it) + { + Evas_Coord x, w; + evas_object_geometry_get(it->base.view, &x, NULL, &w, NULL); + /* item not visible */ + if (x + w <= ox || x >= ox + ow) + continue; + + if (x <= ox + 5) + edje_object_signal_emit(it->base.view, "elm,state,left_side", + "elm"); + else if (x + w >= ox + ow - 5) + edje_object_signal_emit(it->base.view, "elm,state,right_side", + "elm"); + else + { + if ((wd->len_threshold) && (strlen(it->label) > wd->len_threshold)) + edje_object_signal_emit(it->base.view, "elm,state,center_small", + "elm"); + else + edje_object_signal_emit(it->base.view, "elm,state,center", + "elm"); + } + + len = strlen(it->label); + if (len <= wd->len_side) + continue; + + steps = len - wd->len_side + 1; + mid = x + w / 2; + if (mid <= ox + ow / 2) + diff = (ox + ow / 2) - mid; + else + diff = mid - (ox + ow / 2); + + length = len - (int)(diff * steps / (ow / 3)); + length = MAX(length, wd->len_side); + length = _check_letter(it->label, length); + strncpy(buf, it->label, length); + buf[length] = '\0'; + edje_object_part_text_set(it->base.view, "elm.text", buf); + } + + if (wd->check_idler) + ecore_idler_del(wd->check_idler); + wd->check_idler = NULL; + return EINA_FALSE; +} + +static void +_scroller_move_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Evas_Coord x, y, w, h, bw; + Widget_Data *wd = data; + + _check_string(wd); + elm_smart_scroller_child_pos_get(obj, &x, &y); + elm_smart_scroller_child_viewport_size_get(obj, &w, &h); + if (wd->round) + { + evas_object_geometry_get(wd->main_box, NULL, NULL, &bw, NULL); + if (x > w / 3 * (wd->item_count + 1)) + elm_smart_scroller_child_region_show(wd->scroller, + x - w / 3 * wd->item_count, + y, w, h); + else if (x < 0) + elm_smart_scroller_child_region_show(wd->scroller, + x + w / 3 * wd->item_count, + y, w, h); + } +} + +static void +_scroller_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) +{ + Elm_Diskpicker_Item *it; + Widget_Data *wd = data; + Evas_Coord x, w, ow; + Eina_List *l, *list; + + if (wd->idler) + return; + + if (!wd->round) + list = wd->items; + else + list = wd->r_items; + + evas_object_geometry_get(wd->scroller, NULL, NULL, &ow, NULL); + EINA_LIST_FOREACH(list, l, it) + { + evas_object_geometry_get(it->base.view, &x, NULL, &w, NULL); + if (abs((int)(ow / 2 - (int)(x + w / 2))) < 10) + break; + } + + if (!it) + return; + + _select_item(it); +} + +static Eina_Bool +_move_scroller(void *data) +{ + Evas_Object *obj = data; + Widget_Data *wd; + Eina_List *l; + Elm_Diskpicker_Item *dit; + Evas_Coord y, w, h; + int i; + + wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + + if (wd->round) + i = 1; + else + i = 0; + + EINA_LIST_FOREACH(wd->items, l, dit) + { + if (wd->selected_item == dit) + break; + i++; + } + if (!dit) + { + wd->selected_item = + (Elm_Diskpicker_Item *) eina_list_nth(wd->items, 0); + return EINA_FALSE; + } + + evas_object_geometry_get(wd->scroller, NULL, &y, &w, &h); + elm_smart_scroller_child_region_show(wd->scroller, w / 3 * i, y, w, h); + _select_item(dit); + if (wd->idler) + { + ecore_idler_del(wd->idler); + wd->idler = NULL; + } + wd->init = EINA_TRUE; + _check_string(wd); + + return EINA_TRUE; +} + +static void +_round_item_del(Widget_Data *wd, Elm_Diskpicker_Item *it) +{ + if (!it) return; + elm_box_unpack(wd->main_box, it->base.view); + wd->r_items = eina_list_remove(wd->r_items, it); + eina_stringshare_del(it->label); + evas_object_del(it->base.view); + free(it); +} + +static void +_round_items_del(Widget_Data *wd) +{ + _round_item_del(wd, wd->last); + wd->last = NULL; + _round_item_del(wd, wd->s_last); + wd->s_last = NULL; + _round_item_del(wd, wd->second); + wd->second = NULL; + _round_item_del(wd, wd->first); + wd->first = NULL; +} + +static void +_round_items_add(Widget_Data *wd) +{ + Elm_Diskpicker_Item *dit; + Elm_Diskpicker_Item *it; + + dit = it = eina_list_nth(wd->items, 0); + if (!dit) return; + + if (!wd->first) + { + wd->first = _item_new(it->base.widget, it->icon, it->label, it->func, + it->base.data); + wd->first->node = it->node; + wd->r_items = eina_list_append(wd->r_items, wd->first); + } + + it = eina_list_nth(wd->items, 1); + if (!it) + it = dit; + if (!wd->second) + { + wd->second = _item_new(it->base.widget, it->icon, it->label, it->func, + it->base.data); + wd->second->node = it->node; + wd->r_items = eina_list_append(wd->r_items, wd->second); + } + + it = eina_list_nth(wd->items, wd->item_count - 1); + if (!it) + it = dit; + if (!wd->last) + { + wd->last = _item_new(it->base.widget, it->icon, it->label, it->func, + it->base.data); + wd->last->node = it->node; + wd->r_items = eina_list_prepend(wd->r_items, wd->last); + } + + it = eina_list_nth(wd->items, wd->item_count - 2); + if (!it) + it = dit; + if (!wd->s_last) + { + wd->s_last = _item_new(it->base.widget, it->icon, it->label, it->func, + it->base.data); + wd->s_last->node = it->node; + wd->r_items = eina_list_prepend(wd->r_items, wd->s_last); + } +} + +/** + * Add a new diskpicker object + * + * @param parent The parent object + * @return The new object or NULL if it cannot be created + * + * @ingroup Diskpicker + */ +EAPI Evas_Object * +elm_diskpicker_add(Evas_Object *parent) +{ + Evas_Object *obj; + Widget_Data *wd; + + wd = ELM_NEW(Widget_Data); + wd->self = obj = elm_widget_add(evas_object_evas_get(parent)); + ELM_SET_WIDTYPE(widtype, "diskpicker"); + elm_widget_type_set(obj, "diskpicker"); + elm_widget_sub_object_add(parent, obj); + elm_widget_data_set(obj, wd); + elm_widget_del_hook_set(obj, _del_hook); + elm_widget_del_pre_hook_set(obj, _del_pre_hook); + elm_widget_theme_hook_set(obj, _theme_hook); + elm_widget_can_focus_set(obj, EINA_TRUE); + elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); + elm_widget_event_hook_set(obj, _event_hook); + + wd->item_count = 0; + wd->round = EINA_FALSE; + wd->init = EINA_FALSE; + wd->len_side = 3; + + wd->scroller = elm_smart_scroller_add(evas_object_evas_get(parent)); + elm_smart_scroller_widget_set(wd->scroller, obj); + _theme_hook(obj); + elm_widget_resize_object_set(obj, wd->scroller); + elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF, + ELM_SMART_SCROLLER_POLICY_OFF); + elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_TRUE, EINA_FALSE); + evas_object_smart_callback_add(wd->scroller, "scroll", _scroller_move_cb, + wd); + evas_object_smart_callback_add(wd->scroller, "animate,stop", + _scroller_stop_cb, wd); + _elm_theme_object_set(obj, wd->scroller, "diskpicker", "base", + "default"); + evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE, + _diskpicker_object_resize, obj); + + wd->main_box = elm_box_add(parent); + elm_box_horizontal_set(wd->main_box, EINA_TRUE); + elm_box_homogenous_set(wd->main_box, EINA_TRUE); + evas_object_size_hint_weight_set(wd->main_box, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(wd->main_box, EVAS_HINT_FILL, + EVAS_HINT_FILL); + _elm_theme_object_set(obj, wd->main_box, "diskpicker", "base", + "default"); + elm_widget_sub_object_add(obj, wd->main_box); + + elm_smart_scroller_child_set(wd->scroller, wd->main_box); + + wd->left_blank = edje_object_add(evas_object_evas_get(obj)); + _elm_theme_object_set(obj, wd->left_blank, "diskpicker", "item", + "default"); + evas_object_size_hint_weight_set(wd->left_blank, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(wd->left_blank, EVAS_HINT_FILL, + EVAS_HINT_FILL); + elm_box_pack_end(wd->main_box, wd->left_blank); + evas_object_show(wd->left_blank); + + wd->right_blank = edje_object_add(evas_object_evas_get(obj)); + _elm_theme_object_set(obj, wd->right_blank, "diskpicker", "item", + "default"); + evas_object_size_hint_weight_set(wd->right_blank, EVAS_HINT_EXPAND, + EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(wd->right_blank, EVAS_HINT_FILL, + EVAS_HINT_FILL); + elm_box_pack_end(wd->main_box, wd->right_blank); + evas_object_show(wd->right_blank); + + _theme_data_get(wd); + + evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); + evas_object_smart_callbacks_descriptions_set(obj, _signals); + _sizing_eval(obj); + return obj; +} + +/** + * Get round mode + * + * If round mode is activated the items list will work like a circle list, + * so when the user reaches the last item, the first one will popup. + * + * @param obj The diskpicker object + * @return if or not set round mode or false if not a valid diskpicker + * + * @ingroup Diskpicker + */ +EAPI Eina_Bool +elm_diskpicker_round_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return EINA_FALSE; + return wd->round; +} + +/** + * Set round mode + * + * If round mode is activated the items list will work like a circle list, + * so when the user reaches the last item, the first one will popup. + * + * @param it The item of diskpicker + * @param if or not set round mode + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_round_set(Evas_Object * obj, Eina_Bool round) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + + if (wd->round == round) + return; + + wd->round = round; + if (round) + { + wd->r_items = eina_list_clone(wd->items); + elm_box_unpack(wd->main_box, wd->left_blank); + evas_object_hide(wd->left_blank); + elm_box_unpack(wd->main_box, wd->right_blank); + evas_object_hide(wd->right_blank); + if (wd->items == NULL) + return; + + _round_items_add(wd); + + if (wd->last) + elm_box_pack_start(wd->main_box, wd->last->base.view); + if (wd->s_last) + elm_box_pack_start(wd->main_box, wd->s_last->base.view); + if (wd->first) + elm_box_pack_end(wd->main_box, wd->first->base.view); + if (wd->second) + elm_box_pack_end(wd->main_box, wd->second->base.view); + } + else + { + _round_items_del(wd); + elm_box_pack_start(wd->main_box, wd->left_blank); + elm_box_pack_end(wd->main_box, wd->right_blank); + eina_list_free(wd->r_items); + wd->r_items = NULL; + } + _sizing_eval(obj); +} + +/** + * Get the side labels max lenght + * + * @param obj The diskpicker object + * @return The max lenght defined for side labels, or 0 if not a valid + * diskpicker + * + * @ingroup Diskpicker + */ +EAPI int +elm_diskpicker_side_label_lenght_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) 0; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return 0; + return wd->len_side; +} + +/** + * Set the side labels max lenght + * + * @param obj The diskpicker object + * @param len The max lenght defined for side labels + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_side_label_lenght_set(Evas_Object *obj, int len) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + wd->len_side = len; +} + +/** + * Set bounce mode + * + * This will enable or disable the scroller bounce mode for the diskpicker. + * See elm_scroller_bounce_set() for details. Horizontal bounce is enabled by + * default. + * + * @param obj The diskpicker object + * @param h_bounce Allow bounce horizontally + * @param v_bounce Allow bounce vertically + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + if (wd->scroller) + elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce); +} + +/** + * Get the scrollbar policy + * + * This sets the scrollbar visibility policy for the given scroller. + * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollber is made visible if it + * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns + * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off. + * This applies respectively for the horizontal and vertical scrollbars. + * The both are disabled by default. + * + * @param obj The diskpicker object + * @param policy_h Horizontal scrollbar policy + * @param policy_v Vertical scrollbar policy + * + * @ingroup Diskpicker + */ + +EAPI void +elm_diskpicker_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Elm_Smart_Scroller_Policy s_policy_h, s_policy_v; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + if (wd->scroller) + elm_smart_scroller_policy_get(wd->scroller, &s_policy_h, &s_policy_v); + *policy_h = (Elm_Scroller_Policy) s_policy_h; + *policy_v = (Elm_Scroller_Policy) s_policy_v; +} + + +/** + * Set the scrollbar policy + * + * This sets the scrollbar visibility policy for the given scroller. + * ELM_SMART_SCROLLER_POLICY_AUTO means the scrollber is made visible if it + * is needed, and otherwise kept hidden. ELM_SMART_SCROLLER_POLICY_ON turns + * it on all the time, and ELM_SMART_SCROLLER_POLICY_OFF always keeps it off. + * This applies respectively for the horizontal and vertical scrollbars. + * The both are disabled by default. + * + * @param obj The diskpicker object + * @param policy_h Horizontal scrollbar policy + * @param policy_v Vertical scrollbar policy + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return; + if ((policy_h >= 3) || (policy_v >= 3)) return; + if (wd->scroller) + elm_smart_scroller_policy_set(wd->scroller, policy_h, policy_v); +} + +/** + * Clears a diskpicker of all items. + * + * @param obj The diskpicker object + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_clear(Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype); + Widget_Data *wd = elm_widget_data_get(obj); + Elm_Diskpicker_Item *it; + + if (!wd) return; + if (!wd->items) return; + + wd->selected_item = NULL; + EINA_LIST_FREE(wd->items, it) _item_del(it); + _round_items_del(wd); + _sizing_eval(obj); +} + +/** + * Returns a list of all the diskpicker items. + * + * @param obj The diskpicker object + * @return An Eina_List* of the diskpicker items, or NULL on failure + * + * @ingroup Diskpicker + */ +EAPI const Eina_List * +elm_diskpicker_items_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + return wd->items; +} + +/** + * Appends an item to the diskpicker object. + * + * @param obj The diskpicker object + * @param label The label of the diskpicker item + * @param icon The icon object to use for the left side of the item + * @param func The function to call when the item is selected + * @param data The data to associate with the item for related callbacks + * + * @return The created item or NULL upon failure + * + * @ingroup Diskpicker + */ +EAPI Elm_Diskpicker_Item * +elm_diskpicker_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) +{ + Elm_Diskpicker_Item *it; + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + + it = _item_new(obj, icon, label, func, data); + wd->items = eina_list_append(wd->items, it); + it->node = eina_list_last(wd->items); + wd->item_count++; + if (wd->round) + { + _round_items_del(wd); + wd->r_items = eina_list_append(wd->r_items, it); + _round_items_add(wd); + if (wd->last) + elm_box_pack_start(wd->main_box, wd->last->base.view); + if (wd->s_last) + elm_box_pack_start(wd->main_box, wd->s_last->base.view); + elm_box_pack_end(wd->main_box, it->base.view); + if (wd->first) + elm_box_pack_end(wd->main_box, wd->first->base.view); + if (wd->second) + elm_box_pack_end(wd->main_box, wd->second->base.view); + } + else + { + elm_box_unpack(wd->main_box, wd->right_blank); + elm_box_pack_end(wd->main_box, it->base.view); + elm_box_pack_end(wd->main_box, wd->right_blank); + } + if (!wd->selected_item) + wd->selected_item = it; + if (!wd->idler) + wd->idler = ecore_idler_add(_move_scroller, obj); + _sizing_eval(obj); + return it; +} + +/** + * Delete the item + * + * @param it The item of diskpicker + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_del(Elm_Diskpicker_Item * it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it); + Elm_Diskpicker_Item *dit; + Widget_Data *wd = elm_widget_data_get(it->base.widget); + if (!wd) return; + + elm_box_unpack(wd->main_box, it->base.view); + + if (wd->round) + wd->r_items = eina_list_remove(wd->r_items, it); + + wd->items = eina_list_remove(wd->items, it); + + if (wd->selected_item == it) + { + dit = (Elm_Diskpicker_Item *) eina_list_nth(wd->items, 0); + if (dit != it) + wd->selected_item = dit; + else + wd->selected_item = eina_list_nth(wd->items, 1); + } + + _item_del(it); + wd->item_count -= 1; + + if (wd->round) + { + if (wd->item_count == 0) + { + evas_object_hide(wd->first->base.view); + evas_object_hide(wd->second->base.view); + evas_object_hide(wd->last->base.view); + evas_object_hide(wd->s_last->base.view); + } + else + { + dit = eina_list_nth(wd->items, 0); + if (dit) + { + eina_stringshare_replace(&wd->first->label, dit->label); + edje_object_part_text_set(wd->first->base.view, "elm.text", + wd->first->label); + } + dit = eina_list_nth(wd->items, 1); + if (dit) + { + eina_stringshare_replace(&wd->second->label, dit->label); + edje_object_part_text_set(wd->second->base.view, "elm.text", + wd->second->label); + } + dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 1); + if (dit) + { + eina_stringshare_replace(&wd->last->label, dit->label); + edje_object_part_text_set(wd->last->base.view, "elm.text", + wd->last->label); + } + dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 2); + if (dit) + { + eina_stringshare_replace(&wd->s_last->label, dit->label); + edje_object_part_text_set(wd->s_last->base.view, "elm.text", + wd->s_last->label); + } + } + } + wd->check_idler = ecore_idler_add(_check_string, wd); + _sizing_eval(it->base.widget); +} + +/** + * Get the label of item + * + * @param it The item of diskpicker + * @return The label of item + * + * @ingroup Diskpicker + */ +EAPI const char * +elm_diskpicker_item_label_get(const Elm_Diskpicker_Item * it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, NULL); + return it->label; +} + +/** + * Set the label of item + * + * @param it The item of diskpicker + * @param label The label of item + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_label_set(Elm_Diskpicker_Item * it, const char *label) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it); + eina_stringshare_replace(&it->label, label); + edje_object_part_text_set(it->base.view, "elm.text", it->label); +} + +/** + * Get the selected item + * + * @param obj The diskpicker object + * @return The selected diskpicker item + * + * @ingroup Diskpicker + */ +EAPI Elm_Diskpicker_Item * +elm_diskpicker_item_selected_get(const Evas_Object *obj) +{ + ELM_CHECK_WIDTYPE(obj, widtype) NULL; + Widget_Data *wd = elm_widget_data_get(obj); + if (!wd) return NULL; + return wd->selected_item; +} + +/** + * Set the selected item + * + * @param it The item of diskpicker + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_selected_set(Elm_Diskpicker_Item * it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it); + Widget_Data *wd; + wd = elm_widget_data_get(it->base.widget); + if (!wd) return; + + wd->selected_item = it; + if (!wd->idler) + ecore_idler_add(_move_scroller, it->base.widget); +} + +/** + * Set the function called when a diskpicker item is freed. + * + * @param it The item to set the callback on + * @param func The function called + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_del_cb_set(Elm_Diskpicker_Item *it, Evas_Smart_Cb func) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it); + elm_widget_item_del_cb_set(it, func); +} + +/** + * Returns the data associated with the item. + * + * @param it The diskpicker item + * @return The data associated with @p it + * + * @ingroup Diskpicker + */ +EAPI void * +elm_diskpicker_item_data_get(const Elm_Diskpicker_Item *it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, NULL); + return elm_widget_item_data_get(it); +} + +/** + * Returns the icon associated with the item. + * + * @param it The diskpicker item + * @return The icon associated with @p it + * + * @ingroup Diskpicker + */ +EAPI Evas_Object * +elm_diskpicker_item_icon_get(const Elm_Diskpicker_Item *it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, NULL); + return it->icon; +} + +/** + * Sets the icon associated with the item. + * + * Once the icon object is set, a previously set one will be deleted. + * You probably don't want, then, to have the same icon object set + * for more than one item of the diskpicker. + * + * @param it The diskpicker item + * @param icon The icon object to associate with @p it + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_icon_set(Elm_Diskpicker_Item *it, Evas_Object *icon) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it); + if (it->icon == icon) return; + if (it->icon) + evas_object_del(it->icon); + it->icon = icon; + if (it->base.view) + edje_object_part_swallow(it->base.view, "elm.swallow.icon", icon); +} + +/** + * Gets the item before @p it in the list. + * + * @param it The diskpicker item + * @return The item before @p it, or NULL on failure + * + * @ingroup Diskpicker + */ +EAPI Elm_Diskpicker_Item * +elm_diskpicker_item_prev(const Elm_Diskpicker_Item *it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, NULL); + if (it->node->prev) return it->node->prev->data; + else return NULL; +} + +/** + * Gets the item after @p it in the list. + * + * @param it The diskpicker item + * @return The item after @p it, or NULL on failure + * + * @ingroup Diskpicker + */ +EAPI Elm_Diskpicker_Item * +elm_diskpicker_item_next(const Elm_Diskpicker_Item *it) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(it, NULL); + if (it->node->next) return it->node->next->data; + else return NULL; +} + +/** + * Set the text to be shown in the diskpicker item. + * + * @param item Target item + * @param text The text to set in the content + * + * Setup the text as tooltip to object. The item can have only one tooltip, + * so any previous tooltip data is removed. + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_tooltip_text_set(Elm_Diskpicker_Item *item, const char *text) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_tooltip_text_set(item, text); +} + +/** + * Set the content to be shown in the tooltip item + * + * Setup the tooltip to item. The item can have only one tooltip, + * so any previous tooltip data is removed. @p func(with @p data) will + * be called every time that need show the tooltip and it should + * return a valid Evas_Object. This object is then managed fully by + * tooltip system and is deleted when the tooltip is gone. + * + * @param item the diskpicker item being attached a tooltip. + * @param func the function used to create the tooltip contents. + * @param data what to provide to @a func as callback data/context. + * @param del_cb called when data is not needed anymore, either when + * another callback replaces @func, the tooltip is unset with + * elm_diskpicker_item_tooltip_unset() or the owner @a item + * dies. This callback receives as the first parameter the + * given @a data, and @c event_info is the item. + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_tooltip_content_cb_set(Elm_Diskpicker_Item *item, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb); +} + +/** + * Unset tooltip from item + * + * @param item diskpicker item to remove previously set tooltip. + * + * Remove tooltip from item. The callback provided as del_cb to + * elm_diskpicker_item_tooltip_content_cb_set() will be called to notify + * it is not used anymore. + * + * @see elm_diskpicker_item_tooltip_content_cb_set() + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_tooltip_unset(Elm_Diskpicker_Item *item) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_tooltip_unset(item); +} + +/** + * Sets a different style for this item tooltip. + * + * @note before you set a style you should define a tooltip with + * elm_diskpicker_item_tooltip_content_cb_set() or + * elm_diskpicker_item_tooltip_text_set() + * + * @param item diskpicker item with tooltip already set. + * @param style the theme style to use (default, transparent, ...) + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_tooltip_style_set(Elm_Diskpicker_Item *item, const char *style) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_tooltip_style_set(item, style); +} + +/** + * Get the style for this item tooltip. + * + * @param item diskpicker item with tooltip already set. + * @return style the theme style in use, defaults to "default". If the + * object does not have a tooltip set, then NULL is returned. + * + * @ingroup Diskpicker + */ +EAPI const char * +elm_diskpicker_item_tooltip_style_get(const Elm_Diskpicker_Item *item) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item, NULL); + return elm_widget_item_tooltip_style_get(item); +} + +/** + * Set the cursor to be shown when mouse is over the diskpicker item + * + * @param item Target item + * @param cursor the cursor name to be used. + * + * @see elm_object_cursor_set() + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_cursor_set(Elm_Diskpicker_Item *item, const char *cursor) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_cursor_set(item, cursor); +} + +/** + * Unset the cursor to be shown when mouse is over the diskpicker item + * + * @param item Target item + * + * @see elm_object_cursor_unset() + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_cursor_unset(Elm_Diskpicker_Item *item) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_cursor_unset(item); +} + +/** + * Sets a different style for this item cursor. + * + * @note before you set a style you should define a cursor with + * elm_diskpicker_item_cursor_set() + * + * @param item diskpicker item with cursor already set. + * @param style the theme style to use (default, transparent, ...) + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_cursor_style_set(Elm_Diskpicker_Item *item, const char *style) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_cursor_style_set(item, style); +} + +/** + * Get the style for this item cursor. + * + * @param item diskpicker item with cursor already set. + * @return style the theme style in use, defaults to "default". If the + * object does not have a cursor set, then NULL is returned. + * + * @ingroup Diskpicker + */ +EAPI const char * +elm_diskpicker_item_cursor_style_get(const Elm_Diskpicker_Item *item) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item, NULL); + return elm_widget_item_cursor_style_get(item); +} + +/** + * Set if the cursor set should be searched on the theme or should use + * the provided by the engine, only. + * + * @note before you set if should look on theme you should define a cursor + * with elm_object_cursor_set(). By default it will only look for cursors + * provided by the engine. + * + * @param item widget item with cursor already set. + * @param engine_only boolean to define it cursors should be looked only + * between the provided by the engine or searched on widget's theme as well. + * + * @ingroup Diskpicker + */ +EAPI void +elm_diskpicker_item_cursor_engine_only_set(Elm_Diskpicker_Item *item, Eina_Bool engine_only) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item); + elm_widget_item_cursor_engine_only_set(item, engine_only); +} + +/** + * Get the cursor engine only usage for this item cursor. + * + * @param item widget item with cursor already set. + * @return engine_only boolean to define it cursors should be looked only + * between the provided by the engine or searched on widget's theme as well. If + * the object does not have a cursor set, then EINA_FALSE is returned. + * + * @ingroup Diskpicker + */ +EAPI Eina_Bool +elm_diskpicker_item_cursor_engine_only_get(const Elm_Diskpicker_Item *item) +{ + ELM_DISKPICKER_ITEM_CHECK_OR_RETURN(item, EINA_FALSE); + return elm_widget_item_cursor_engine_only_get(item); +}