elm_hoversel: add elm_hoversel_scroll_enabled_set/get() API
authorJee-Yong Um <jc9.um@samsung.com>
Tue, 4 Aug 2015 13:51:36 +0000 (15:51 +0200)
committerCedric BAIL <cedric@osg.samsung.com>
Tue, 4 Aug 2015 13:51:39 +0000 (15:51 +0200)
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 <cedric@osg.samsung.com>
data/themes/edc/elm/hover.edc
src/bin/test_hoversel.c
src/lib/elc_hoversel.c
src/lib/elm_hoversel.eo
src/lib/elm_widget_hoversel.h

index 19c3bd5..43fd5c5 100644 (file)
@@ -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";
index 9e35332..26977dd 100644 (file)
@@ -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);
index 9be75c2..a8bb528 100644 (file)
@@ -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"
index 5e7d05b..24e6a24 100644 (file)
@@ -81,6 +81,25 @@ class Elm.Hoversel (Elm.Button, Evas.Selectable_Interface,
             return: const(list<Elm_Object_Item *>)*;
          }
       }
+      @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
index 7e77bb0..ff62512 100644 (file)
@@ -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;