From e8264becb8f6f36e3c62c5fc5e4a46bbdbb9cf1f Mon Sep 17 00:00:00 2001 From: Jee-Yong Um Date: Tue, 4 Aug 2015 15:51:36 +0200 Subject: [PATCH] elm_hoversel: add elm_hoversel_scroll_enabled_set/get() API Summary: Currently, hoversel shows all items at the same time, but to limit the size of contents and make it scrollable is neccesary to some users. elm_hoversel_scroll_enabled_set/get() API makes the contents of hoversel scrollable or not. Test Plan: The newly added scroll function is enabled for the second hoversel in "hoversel" sample of elementary_test. Reviewers: Hermet, raster, herdsman, cedric, tasn Subscribers: JackDanielZ, cedric, Hermet Differential Revision: https://phab.enlightenment.org/D2603 Signed-off-by: Cedric BAIL --- data/themes/edc/elm/hover.edc | 10 +-- src/bin/test_hoversel.c | 1 + src/lib/elc_hoversel.c | 146 ++++++++++++++++++++++++++++++++++++++++-- src/lib/elm_hoversel.eo | 19 ++++++ src/lib/elm_widget_hoversel.h | 9 ++- 5 files changed, 174 insertions(+), 11 deletions(-) diff --git a/data/themes/edc/elm/hover.edc b/data/themes/edc/elm/hover.edc index 19c3bd5..43fd5c5 100644 --- a/data/themes/edc/elm/hover.edc +++ b/data/themes/edc/elm/hover.edc @@ -427,6 +427,7 @@ group { name: "elm/hover/base/hoversel_vertical/default"; alias: "elm/hover/base/hoversel_vertical/entry"; images.image: "button_normal.png" COMP; images.image: "vertical_separated_bar_glow.png" COMP; + data.item: "max_size" "60"; parts { part { name: "elm.swallow.offset"; type: SWALLOW; description { state: "default" 0.0; @@ -644,6 +645,7 @@ group { name: "elm/hover/base/hoversel_vertical/default"; group { name: "elm/hover/base/hoversel_horizontal/default"; alias: "elm/hover/base/hoversel_horizontal/entry"; images.image: "button_normal.png" COMP; + data.item: "max_size" "120"; parts { part { name: "elm.swallow.offset"; type: SWALLOW; description { state: "default" 0.0; @@ -673,10 +675,10 @@ group { name: "elm/hover/base/hoversel_horizontal/default"; part { name: "button_image"; mouse_events: 0; description { state: "default" 0.0; rel1.to_x: "elm.swallow.slot.left"; - rel1.to_y: "elm.swallow.slot.middle"; + rel1.to_y: "elm.swallow.slot.left"; rel1.offset: -6 0; rel2.to_x: "elm.swallow.slot.middle"; - rel2.to_y: "elm.swallow.slot.middle"; + rel2.to_y: "elm.swallow.slot.left"; rel2.relative: 0.0 1.0; rel2.offset: 4 1; image { @@ -687,11 +689,11 @@ group { name: "elm/hover/base/hoversel_horizontal/default"; } description { state: "right" 0.0; rel1.to_x: "elm.swallow.slot.middle"; - rel1.to_y: "elm.swallow.slot.middle"; + rel1.to_y: "elm.swallow.slot.right"; rel1.relative: 1.0 0.0; rel1.offset: -5 0; rel2.to_x: "elm.swallow.slot.right"; - rel2.to_y: "elm.swallow.slot.middle"; + rel2.to_y: "elm.swallow.slot.right"; rel2.offset: 5 1; image { normal: "button_normal.png"; diff --git a/src/bin/test_hoversel.c b/src/bin/test_hoversel.c index 9e35332..26977dd 100644 --- a/src/bin/test_hoversel.c +++ b/src/bin/test_hoversel.c @@ -181,6 +181,7 @@ test_hoversel(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_ evas_object_show(hoversel); hoversel = elm_hoversel_add(win); + elm_hoversel_scroll_enabled_set(hoversel, EINA_TRUE); elm_hoversel_hover_parent_set(hoversel, win); elm_object_text_set(hoversel, "Some Icons"); elm_hoversel_item_add(hoversel, "Item 1", NULL, ELM_ICON_NONE, NULL, NULL); diff --git a/src/lib/elc_hoversel.c b/src/lib/elc_hoversel.c index 9be75c2..a8bb528 100644 --- a/src/lib/elc_hoversel.c +++ b/src/lib/elc_hoversel.c @@ -148,6 +148,9 @@ _activate(Evas_Object *obj) Evas_Object *bt, *bx, *ic; const Eina_List *l; char buf[4096]; + const char *max_size_str; + int max_size = 0; + Evas_Coord box_w = -1, box_h = -1; ELM_HOVERSEL_DATA_GET(obj, sd); @@ -218,12 +221,48 @@ _activate(Evas_Object *obj) eo_event_callback_add(ELM_WIDGET_EVENT_UNFOCUSED, _item_unfocused_cb, item)); } - if (sd->horizontal) - elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get - (sd->hover, ELM_HOVER_AXIS_HORIZONTAL), bx); + elm_box_recalculate(bx); + + if (sd->scroll_enabled) + { + max_size_str = edje_object_data_get(elm_layout_edje_get(sd->hover), "max_size"); + if (max_size_str) + max_size = (int)(atoi(max_size_str) + * elm_config_scale_get() * elm_object_scale_get(obj)); + + elm_object_content_set(sd->scr, bx); + evas_object_show(sd->scr); + + if (sd->horizontal) + { + evas_object_size_hint_min_get(bx, &box_w, NULL); + + evas_object_size_hint_min_set(sd->spacer, MIN(box_w, max_size), 0); + evas_object_size_hint_max_set(sd->spacer, max_size, -1); + + sd->last_location = elm_hover_best_content_location_get(sd->hover, ELM_HOVER_AXIS_HORIZONTAL); + elm_object_part_content_set(sd->hover, sd->last_location, sd->tbl); + } + else + { + evas_object_size_hint_min_get(bx, NULL, &box_h); + + evas_object_size_hint_min_set(sd->spacer, 0, MIN(box_h, max_size)); + evas_object_size_hint_max_set(sd->spacer, -1, max_size); + + sd->last_location = elm_hover_best_content_location_get(sd->hover, ELM_HOVER_AXIS_VERTICAL); + elm_object_part_content_set(sd->hover, sd->last_location, sd->tbl); + } + } else - elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get - (sd->hover, ELM_HOVER_AXIS_VERTICAL), bx); + { + if (sd->horizontal) + elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get + (sd->hover, ELM_HOVER_AXIS_HORIZONTAL), bx); + else + elm_object_part_content_set(sd->hover, elm_hover_best_content_location_get + (sd->hover, ELM_HOVER_AXIS_VERTICAL), bx); + } eo_do(obj, eo_event_callback_call(ELM_HOVERSEL_EVENT_EXPANDED, NULL)); evas_object_show(sd->hover); @@ -248,6 +287,29 @@ _on_parent_del(void *data, elm_hoversel_hover_parent_set(data, NULL); } +static void +_on_table_del(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + ELM_HOVERSEL_DATA_GET(data, sd); + + sd->tbl = NULL; + sd->spacer = NULL; + sd->scr = NULL; + elm_layout_sizing_eval(data); +} + +static void +_size_hints_changed_cb(void *data, + Evas *e EINA_UNUSED, + Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + elm_layout_sizing_eval(data); +} + static const char * _elm_hoversel_item_elm_widget_item_part_text_get(Eo *eo_it EINA_UNUSED, Elm_Hoversel_Item_Data *it, @@ -310,6 +372,44 @@ _elm_hoversel_item_eo_base_destructor(Eo *eo_item, Elm_Hoversel_Item_Data *item) eo_do_super(eo_item, ELM_HOVERSEL_ITEM_CLASS, eo_destructor()); } +static void +_create_scroller(Evas_Object *obj) +{ + ELM_HOVERSEL_DATA_GET(obj, sd); + + //table + sd->tbl = elm_table_add(obj); + evas_object_event_callback_add(sd->tbl, EVAS_CALLBACK_DEL, + _on_table_del, obj); + + //spacer + sd->spacer = evas_object_rectangle_add(evas_object_evas_get(obj)); + evas_object_color_set(sd->spacer, 0, 0, 0, 0); + elm_table_pack(sd->tbl, sd->spacer, 0, 0, 1, 1); + + //Scroller + sd->scr = elm_scroller_add(sd->tbl); + elm_object_style_set(sd->scr, "popup/no_inset_shadow"); + evas_object_size_hint_weight_set(sd->scr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(sd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL); + if (sd->horizontal) + { + elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF); + elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_TRUE); + elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE); + } + else + { + elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); + elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_FALSE); + elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE); + } + evas_object_event_callback_add(sd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, + _size_hints_changed_cb, obj); + elm_table_pack(sd->tbl, sd->scr, 0, 0, 1, 1); + evas_object_show(sd->scr); +} + EOLIAN static void _elm_hoversel_evas_object_smart_add(Eo *obj, Elm_Hoversel_Data *_pd EINA_UNUSED) { @@ -319,6 +419,8 @@ _elm_hoversel_evas_object_smart_add(Eo *obj, Elm_Hoversel_Data *_pd EINA_UNUSED) eo_do(obj, eo_event_callback_add( EVAS_CLICKABLE_INTERFACE_EVENT_CLICKED, _on_clicked, obj)); + _create_scroller(obj); + //What are you doing here? eo_do(obj, elm_obj_widget_theme_apply()); } @@ -414,6 +516,19 @@ _elm_hoversel_horizontal_set(Eo *obj, Elm_Hoversel_Data *sd, Eina_Bool horizonta { sd->horizontal = !!horizontal; + if (sd->horizontal) + { + elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF); + elm_scroller_content_min_limit(sd->scr, EINA_FALSE, EINA_TRUE); + elm_scroller_bounce_set(sd->scr, EINA_TRUE, EINA_FALSE); + } + else + { + elm_scroller_policy_set(sd->scr, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); + elm_scroller_content_min_limit(sd->scr, EINA_TRUE, EINA_FALSE); + elm_scroller_bounce_set(sd->scr, EINA_FALSE, EINA_TRUE); + } + eo_do(obj, elm_obj_widget_theme_apply()); } @@ -434,6 +549,7 @@ _elm_hoversel_hover_begin(Eo *obj, Elm_Hoversel_Data *sd) EOLIAN static void _elm_hoversel_hover_end(Eo *obj, Elm_Hoversel_Data *sd) { + Evas_Object *bx; Elm_Object_Item *eo_item; Eina_List *l; @@ -441,6 +557,14 @@ _elm_hoversel_hover_end(Eo *obj, Elm_Hoversel_Data *sd) sd->expanded = EINA_FALSE; + if (sd->scroll_enabled) + { + bx = elm_object_content_unset(sd->scr); + evas_object_hide(sd->scr); + elm_object_part_content_unset(sd->hover, sd->last_location); + elm_object_part_content_set(sd->hover, sd->last_location, bx); + } + EINA_LIST_FOREACH(sd->items, l, eo_item) { ELM_HOVERSEL_ITEM_DATA_GET(eo_item, it); @@ -652,5 +776,17 @@ _elm_hoversel_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNU return &atspi_actions[0]; } +EOLIAN void +_elm_hoversel_scroll_enabled_set(Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd, Eina_Bool scroll_enabled) +{ + sd->scroll_enabled = !!scroll_enabled; +} + +EOLIAN Eina_Bool +_elm_hoversel_scroll_enabled_get(Eo *obj EINA_UNUSED, Elm_Hoversel_Data *sd) +{ + return sd->scroll_enabled; +} + #include "elm_hoversel_item.eo.c" #include "elm_hoversel.eo.c" diff --git a/src/lib/elm_hoversel.eo b/src/lib/elm_hoversel.eo index 5e7d05b..24e6a24 100644 --- a/src/lib/elm_hoversel.eo +++ b/src/lib/elm_hoversel.eo @@ -81,6 +81,25 @@ class Elm.Hoversel (Elm.Button, Evas.Selectable_Interface, return: const(list)*; } } + @property scroll_enabled { + get { + /*@ + @brief Limit the size of contents and make them scrollable. + + @ingroup Hoversel */ + } + set { + /*@ + @brief Returns whether the contents of hoversel are scrollable or not. + + @return @c EINA_TRUE scrollable. @c EINA_FALSE otherwise. + + @ingroup Hoversel */ + } + values { + scroll_enabled: bool; + } + } hover_begin { /*@ @brief This triggers the hoversel popup from code, the same as if the user diff --git a/src/lib/elm_widget_hoversel.h b/src/lib/elm_widget_hoversel.h index 7e77bb0..ff62512 100644 --- a/src/lib/elm_widget_hoversel.h +++ b/src/lib/elm_widget_hoversel.h @@ -32,11 +32,16 @@ struct _Elm_Hoversel_Data /* aggregates a hover */ Evas_Object *hover; Evas_Object *hover_parent; + Evas_Object *spacer; + Evas_Object *tbl; + Evas_Object *scr; + const char *last_location; Eina_List *items; - Eina_Bool horizontal : 1; - Eina_Bool expanded : 1; + Eina_Bool horizontal : 1; + Eina_Bool expanded : 1; + Eina_Bool scroll_enabled: 1; }; typedef struct _Elm_Hoversel_Item_Data Elm_Hoversel_Item_Data; -- 2.7.4