cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=6c04755a922d396356a561b85e010105e6ff61ae

commit 6c04755a922d396356a561b85e010105e6ff61ae
Author: Woochan Lee <wc0917....@samsung.com>
Date:   Mon Nov 28 10:58:57 2016 -0800

    elm/calendar: apply focus UI feature.
    
    Summary:
    elm_calendar is not subject to current automated focus policies due to 
internal implementation issues.
    (Each date in the calendar is an edje part. )
    
    For the above reasons, I have implemented the focus policy support manually.
    
    Test Plan: elementary_test - calendar sample.
    
    Reviewers: bu5hm4n, woohyun
    
    Subscribers: cedric, jpeg
    
    Differential Revision: https://phab.enlightenment.org/D4421
    
    Signed-off-by: Cedric BAIL <ced...@osg.samsung.com>
---
 config/default/base.src.in                  |  18 ++
 config/mobile/base.src.in                   |  18 ++
 config/standard/base.src.in                 |  18 ++
 data/elementary/themes/edc/elm/calendar.edc |  62 +++++++
 src/lib/elementary/elm_calendar.c           | 266 +++++++++++++++++++++++++++-
 src/lib/elementary/elm_calendar.eo          |   1 +
 src/lib/elementary/elm_widget_calendar.h    |   2 +-
 7 files changed, 378 insertions(+), 7 deletions(-)

diff --git a/config/default/base.src.in b/config/default/base.src.in
index dfecc90..9128b98 100644
--- a/config/default/base.src.in
+++ b/config/default/base.src.in
@@ -727,6 +727,24 @@ group "Elm_Config" struct {
               value "action" string: "move";
               value "params" string: "down";
            }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "Return";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "KP_Enter";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "space";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
         }
      }
      group "Elm_Config_Bindings_Widget" struct {
diff --git a/config/mobile/base.src.in b/config/mobile/base.src.in
index ebc5070..f1a357b 100644
--- a/config/mobile/base.src.in
+++ b/config/mobile/base.src.in
@@ -731,6 +731,24 @@ group "Elm_Config" struct {
               value "action" string: "move";
               value "params" string: "down";
            }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "Return";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "KP_Enter";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "space";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
         }
      }
      group "Elm_Config_Bindings_Widget" struct {
diff --git a/config/standard/base.src.in b/config/standard/base.src.in
index d5cd732..678e274 100644
--- a/config/standard/base.src.in
+++ b/config/standard/base.src.in
@@ -728,6 +728,24 @@ group "Elm_Config" struct {
               value "action" string: "move";
               value "params" string: "down";
            }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "Return";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "KP_Enter";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
+           group "Elm_Config_Binding_Key" struct {
+              value "context" int: 0;
+              value "key" string: "space";
+              value "action" string: "activate";
+              value "params" string: "";
+           }
         }
      }
      group "Elm_Config_Bindings_Widget" struct {
diff --git a/data/elementary/themes/edc/elm/calendar.edc 
b/data/elementary/themes/edc/elm/calendar.edc
index 662bd51..8dfffc1 100644
--- a/data/elementary/themes/edc/elm/calendar.edc
+++ b/data/elementary/themes/edc/elm/calendar.edc
@@ -200,6 +200,21 @@
          visible: 1; \
       } \
    } \
+   part { name: "cit_"#_pos".glow"; mouse_events: 0; \
+      description { state: "default" 0.0; \
+         rel1.to: "cit_"#_pos".rect"; \
+         rel2.to: "cit_"#_pos".rect"; \
+         image.normal: "box_glow.png"; \
+         image.border: 12 12 12 12; \
+         image.middle: 0; \
+         fill.smooth: 0; \
+         visible: 0; \
+      } \
+      description { state: "focused" 0.0; \
+         inherit: "default" 0.0; \
+         visible: 1; \
+      } \
+   } \
    part { name: "cit_"#_pos".text"; type: TEXTBLOCK; mouse_events: 0; \
       scale: 1; \
       description { state: "default" 0.0; \
@@ -280,6 +295,26 @@
          target:  "cit_"#_pos".selected"; \
       } \
       program { \
+         name:    "cit_"#_pos".focus_highlighted"; \
+         signal:  "cit_"#_pos",focused"; \
+         source:  "elm"; \
+         script { \
+            set_int(item_focus_enabled, 1); \
+            set_int(last_focused_item, _pos); \
+            if (get_int(win_focus_enabled) == 1) \
+               set_state(PART:"cit_"#_pos".glow", "focused", 0.0); \
+         } \
+      } \
+      program { \
+         name:    "cit_"#_pos".focus_unhighlighed"; \
+         signal:  "cit_"#_pos",unfocused"; \
+         source:  "elm"; \
+         script { \
+            set_int(item_focus_enabled, 0); \
+            set_state(PART:"cit_"#_pos".glow", "default", 0.0); \
+         } \
+      } \
+      program { \
          name:    "cit_"#_pos".is_today"; \
          signal:  "cit_"#_pos",today"; \
          source:  "elm"; \
@@ -413,9 +448,14 @@ group { name: "elm/calendar/base/default";
    images.image: "sym_right_glow_normal.png" COMP;
    images.image: "icon_border_remember.png" COMP;
    images.image: "outline_glow.png" COMP;
+   images.image: "box_glow.png" COMP;
    images.image: "diagonal_stripes.png" COMP;
+   data.item: "focus_highlight" "on";
    script {
       public rtl;
+      public win_focus_enabled;
+      public item_focus_enabled;
+      public last_focused_item;
    }
    styles {
       CIT_STYLES
@@ -493,6 +533,28 @@ group { name: "elm/calendar/base/default";
       CIT(21) CIT(22) CIT(23) CIT(24) CIT(25) CIT(26) CIT(27)
       CIT(28) CIT(29) CIT(30) CIT(31) CIT(32) CIT(33) CIT(34)
       CIT(35) CIT(36) CIT(37) CIT(38) CIT(39) CIT(40) CIT(41)
+
+   }
+   programs {
+      program {
+         signal: "elm,action,focus_highlight,show";
+         source: "elm";
+         script {
+            set_int(win_focus_enabled, 1);
+            if (get_int(item_focus_enabled) == 1) {
+               new value[32];
+               snprintf(value, 32, "cit_%d,focused", 
get_int(last_focused_item));
+               emit(value, "elm");
+            }
+         }
+      }
+      program {
+         signal: "elm,action,focus_highlight,hide";
+         source: "elm";
+         script {
+            set_int(win_focus_enabled, 0);
+         }
+      }
    }
 }
 
diff --git a/src/lib/elementary/elm_calendar.c 
b/src/lib/elementary/elm_calendar.c
index b0fcc58..6e57c26 100644
--- a/src/lib/elementary/elm_calendar.c
+++ b/src/lib/elementary/elm_calendar.c
@@ -125,9 +125,11 @@ _eina_tmpstr_steal(Eina_Tmpstr *s)
 #endif
 
 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
+static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
 
 static const Elm_Action key_actions[] = {
    {"move", _key_action_move},
+   {"activate", _key_action_activate},
    {NULL, NULL}
 };
 
@@ -218,7 +220,7 @@ _select(Evas_Object *obj,
 
    ELM_CALENDAR_DATA_GET(obj, sd);
 
-   sd->selected_it = selected;
+   sd->focused_it = sd->selected_it = selected;
    snprintf(emission, sizeof(emission), "cit_%i,selected", selected);
    elm_layout_signal_emit(obj, emission, "elm");
 }
@@ -1276,6 +1278,47 @@ _get_item_day(Evas_Object *obj,
 }
 
 static void
+_update_unfocused_it(Evas_Object *obj, int unfocused_it)
+{
+   int day;
+   char emission[32];
+
+   ELM_CALENDAR_DATA_GET(obj, sd);
+
+   day = _get_item_day(obj, unfocused_it);
+   if (!day)
+     return;
+
+   sd->focused_it = -1;
+
+   snprintf(emission, sizeof(emission), "cit_%i,unfocused", unfocused_it);
+   elm_layout_signal_emit(obj, emission, "elm");
+}
+
+static Eina_Bool
+_update_focused_it(Evas_Object *obj, int focused_it)
+{
+   int day;
+   char emission[32];
+
+   ELM_CALENDAR_DATA_GET(obj, sd);
+
+   day = _get_item_day(obj, focused_it);
+   if (!day)
+     return EINA_FALSE;
+
+   snprintf(emission, sizeof(emission), "cit_%i,unfocused", sd->focused_it);
+   elm_layout_signal_emit(obj, emission, "elm");
+
+   sd->focused_it = focused_it;
+
+   snprintf(emission, sizeof(emission), "cit_%i,focused", sd->focused_it);
+   elm_layout_signal_emit(obj, emission, "elm");
+
+   return EINA_TRUE;
+}
+
+static void
 _update_sel_it(Evas_Object *obj,
                int sel_it)
 {
@@ -1293,6 +1336,8 @@ _update_sel_it(Evas_Object *obj,
    _unselect(obj, sd->selected_it);
    if (!sd->selected)
      sd->selected = EINA_TRUE;
+   if (sd->focused_it)
+     _update_unfocused_it(obj, sd->focused_it);
 
    sd->selected_time.tm_mday = day;
    _fix_selected_time(sd);
@@ -1349,10 +1394,23 @@ _update_cur_date(void *data)
 }
 
 static Eina_Bool
+_key_action_activate(Evas_Object *obj, const char *params EINA_UNUSED)
+{
+   ELM_CALENDAR_DATA_GET(obj, sd);
+
+   _update_sel_it(obj, sd->focused_it);
+
+   return EINA_TRUE;
+}
+
+static Eina_Bool
 _key_action_move(Evas_Object *obj, const char *params)
 {
    ELM_CALENDAR_DATA_GET(obj, sd);
    const char *dir = params;
+   Eina_Bool ret, double_spinner = EINA_FALSE;
+
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
 
    _elm_widget_focus_auto_show(obj);
    if (!strcmp(dir, "prior"))
@@ -1367,33 +1425,212 @@ _key_action_move(Evas_Object *obj, const char *params)
             && ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
                 || (sd->selected)))
      {
+        if (edje_object_part_exists(wd->resize_obj, 
ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+          double_spinner = EINA_TRUE;
+
         if (!strcmp(dir, "left"))
           {
              if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
                  || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
                      && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
-               _update_sel_it(obj, sd->selected_it - 1);
+               {
+                  //Double spinner case.
+                  if (double_spinner)
+                    {
+                       if (elm_object_focus_get(sd->inc_btn_year))
+                         {
+                            elm_object_focus_set(sd->dec_btn_year, EINA_TRUE);
+                            return EINA_TRUE;
+                         }
+                       else if (elm_object_focus_get(sd->dec_btn_year))
+                         {
+                            elm_object_focus_set(sd->inc_btn_month, EINA_TRUE);
+                            return EINA_TRUE;
+                         }
+                    }
+
+                  //Give focus to dec_btn_month when left key down on the 
inc_btn_month.
+                  //Leave focus, if key down on dec_btn_month.
+                  if (elm_object_focus_get(sd->inc_btn_month))
+                    {
+                       elm_object_focus_set(sd->dec_btn_month, EINA_TRUE);
+                       return EINA_TRUE;
+                    }
+                  else if (elm_object_focus_get(sd->dec_btn_month)) return 
EINA_FALSE;
+
+                  //If key move from the left edge of the calendar,
+                  //Leave the focus policy on window.
+                  if (sd->focused_it % ELM_DAY_LAST == 0)
+                    return EINA_FALSE;
+
+                  //Focus on the day before the day.
+                  ret = _update_focused_it(obj, sd->focused_it - 1);
+                  if (!ret) return EINA_FALSE;
+               }
           }
         else if (!strcmp(dir, "right"))
           {
              if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
                  || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
                      && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
-               _update_sel_it(obj, sd->selected_it + 1);
+               {
+                  //Double spinner case.
+                  if (double_spinner)
+                    {
+                       if (elm_object_focus_get(sd->inc_btn_year)) return 
EINA_FALSE;
+                       else if (elm_object_focus_get(sd->dec_btn_year))
+                         {
+                            elm_object_focus_set(sd->inc_btn_year, EINA_TRUE);
+                            return EINA_TRUE;
+                         }
+                       else if (elm_object_focus_get(sd->inc_btn_month))
+                         {
+                            elm_object_focus_set(sd->dec_btn_year, EINA_TRUE);
+                            return EINA_TRUE;
+                         }
+                    }
+
+                  //Give focus to inc_btn_month when right key down on the 
dec_btn_month.
+                  if (elm_object_focus_get(sd->dec_btn_month))
+                    {
+                       elm_object_focus_set(sd->inc_btn_month, EINA_TRUE);
+                       return EINA_TRUE;
+                    }
+                  else if (elm_object_focus_get(sd->inc_btn_month)) return 
EINA_FALSE;
+
+                  //If key move from the right edge of the calendar,
+                  //Leave the focus policy on window.
+                  if (sd->focused_it % ELM_DAY_LAST == ELM_DAY_LAST - 1)
+                    return EINA_FALSE;
+
+                  //Focus on the day after the day.
+                  ret = _update_focused_it(obj, sd->focused_it + 1);
+                  if (!ret) return EINA_FALSE;
+               }
           }
         else if (!strcmp(dir, "up"))
           {
              if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
                  || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
                      && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
-               _update_sel_it(obj, sd->selected_it - ELM_DAY_LAST);
+               {
+                  //double spinner case.
+                  if (double_spinner)
+                    {
+                       if (elm_object_focus_get(sd->inc_btn_year))
+                         {
+                            elm_object_focus_set(sd->inc_btn_year, EINA_FALSE);
+                            return EINA_FALSE;
+                         }
+                       else if (elm_object_focus_get(sd->dec_btn_year))
+                         {
+                            elm_object_focus_set(sd->dec_btn_year, EINA_FALSE);
+                            return EINA_FALSE;
+                         }
+                    }
+
+                  //If the dec_btn_month, or inc_btn_month has focus.
+                  //Focus unset and leave the focus policy on window.
+                  if (elm_object_focus_get(sd->dec_btn_month))
+                    {
+                       elm_object_focus_set(sd->dec_btn_month, EINA_FALSE);
+                       return EINA_FALSE;
+                    }
+                  else if (elm_object_focus_get(sd->inc_btn_month))
+                    {
+                       elm_object_focus_set(sd->inc_btn_month, EINA_FALSE);
+                       return EINA_FALSE;
+                    }
+
+                  //If the focus item is the first week of month.
+                  if ((sd->focused_it >= 0) && (sd->focused_it < ELM_DAY_LAST))
+                    {
+                       //Give focus to inc_btn_month(right side located button)
+                       //If the focused item is smaller than 4.
+                       //Otherwise, give focus to dec_btn_month.
+                       if (sd->focused_it > (ELM_DAY_LAST / 2))
+                         //Double spinner case.
+                         if (edje_object_part_exists(wd->resize_obj, 
ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                           elm_object_focus_set(sd->inc_btn_year, EINA_TRUE);
+                         else
+                           elm_object_focus_set(sd->inc_btn_month, EINA_TRUE);
+                       else
+                         elm_object_focus_set(sd->dec_btn_month, EINA_TRUE);
+
+                       _update_unfocused_it(obj, sd->focused_it);
+                       return EINA_TRUE;
+                    }
+
+                  //Focus on the last week day.
+                  ret = _update_focused_it(obj, sd->focused_it - ELM_DAY_LAST);
+                  if (!ret)
+                    {
+                       //If focused day is not available(not belongs to 
current month)
+                       //Take a focus from item and give the focus to suitable 
button.
+                       if (sd->focused_it >= ELM_DAY_LAST && sd->focused_it < 
(ELM_DAY_LAST * 2))
+                         {
+                            if (sd->focused_it > (ELM_DAY_LAST + (ELM_DAY_LAST 
/ 2)))
+                              //Double spinner case.
+                              if (edje_object_part_exists(wd->resize_obj, 
ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                                elm_object_focus_set(sd->inc_btn_year, 
EINA_TRUE);
+                              else
+                                elm_object_focus_set(sd->inc_btn_month, 
EINA_TRUE);
+                            else
+                              elm_object_focus_set(sd->dec_btn_month, 
EINA_TRUE);
+
+                            _update_unfocused_it(obj, sd->focused_it);
+                            return EINA_TRUE;
+                         }
+                    }
+               }
           }
         else if (!strcmp(dir, "down"))
           {
              if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
                  || ((sd->shown_time.tm_year == sd->selected_time.tm_year)
                      && (sd->shown_time.tm_mon == sd->selected_time.tm_mon)))
-               _update_sel_it(obj, sd->selected_it + ELM_DAY_LAST);
+               {
+                  //double spinner case.
+                  if (double_spinner)
+                    {
+                       if (elm_object_focus_get(sd->inc_btn_year))
+                         {
+                            elm_object_focus_set(sd->inc_btn_year, EINA_FALSE);
+                            evas_object_focus_set(obj, EINA_TRUE);
+                            _update_focused_it(obj, (ELM_DAY_LAST - 1));
+                            return EINA_TRUE;
+                         }
+                       else if (elm_object_focus_get(sd->dec_btn_year))
+                         {
+                            elm_object_focus_set(sd->dec_btn_year, EINA_FALSE);
+                            evas_object_focus_set(obj, EINA_TRUE);
+                            _update_focused_it(obj, sd->first_day_it);
+                            return EINA_TRUE;
+                         }
+                    }
+
+                  //If the XXX_btn_month has focus.
+                  //Set as false to button focus and give to focus to first 
item of the calendar.
+                  //Otherwise, Give the focus to last day of first week of 
calendar.
+                  if (elm_object_focus_get(sd->dec_btn_month))
+                    {
+                       elm_object_focus_set(sd->dec_btn_month, EINA_FALSE);
+                       evas_object_focus_set(obj, EINA_TRUE);
+                       _update_focused_it(obj, sd->first_day_it);
+                       return EINA_TRUE;
+                    }
+                  else if(elm_object_focus_get(sd->inc_btn_month))
+                    {
+                       elm_object_focus_set(sd->inc_btn_month, EINA_FALSE);
+                       evas_object_focus_set(obj, EINA_TRUE);
+                       _update_focused_it(obj, (ELM_DAY_LAST - 1));
+                       return EINA_TRUE;
+                    }
+
+                  //Focus on the next week day.
+                  ret = _update_focused_it(obj, sd->focused_it + ELM_DAY_LAST);
+                  if (!ret) return EINA_FALSE;
+               }
           }
         else return EINA_FALSE;
      }
@@ -1403,6 +1640,22 @@ _key_action_move(Evas_Object *obj, const char *params)
 }
 
 EOLIAN static Eina_Bool
+_elm_calendar_elm_widget_on_focus(Eo *obj, Elm_Calendar_Data *sd, 
Elm_Object_Item *item EINA_UNUSED)
+{
+   Eina_Bool int_ret = EINA_FALSE;
+
+   int_ret = elm_obj_widget_on_focus(efl_super(obj, MY_CLASS), NULL);
+   if (!int_ret) return EINA_FALSE;
+
+   if (elm_widget_focus_get(obj))
+     sd->focused_it = sd->selected_it;
+   else
+     _update_unfocused_it(obj, sd->focused_it);
+
+   return EINA_TRUE;
+}
+
+EOLIAN static Eina_Bool
 _elm_calendar_elm_widget_event(Eo *obj, Elm_Calendar_Data *sd EINA_UNUSED, 
Evas_Object *src, Evas_Callback_Type type, void *event_info)
 {
    (void) src;
@@ -1545,7 +1798,7 @@ static Eina_Bool _elm_calendar_smart_focus_next_enable = 
EINA_FALSE;
 EOLIAN static Eina_Bool
 _elm_calendar_elm_widget_focus_next_manager_is(Eo *obj EINA_UNUSED, 
Elm_Calendar_Data *_pd EINA_UNUSED)
 {
-   return EINA_TRUE;
+   return EINA_FALSE;
 }
 
 EOLIAN static Eina_Bool
@@ -2080,6 +2333,7 @@ 
_elm_calendar_elm_interface_atspi_widget_action_elm_actions_get(Eo *obj EINA_UNU
           { "move,right", "move", "right", _key_action_move},
           { "move,up", "move", "up", _key_action_move},
           { "move,down", "move", "down", _key_action_move},
+          { "activate", "activate", NULL, _key_action_activate},
           { NULL, NULL, NULL, NULL }
    };
    return &atspi_actions[0];
diff --git a/src/lib/elementary/elm_calendar.eo 
b/src/lib/elementary/elm_calendar.eo
index b312f48..9890b2f 100644
--- a/src/lib/elementary/elm_calendar.eo
+++ b/src/lib/elementary/elm_calendar.eo
@@ -419,6 +419,7 @@ class Elm.Calendar (Elm.Layout, 
Elm.Interface.Atspi_Widget_Action)
       Elm.Widget.focus_direction_manager_is;
       Elm.Widget.access;
       Elm.Widget.focus_next;
+      Elm.Widget.on_focus;
       Elm.Widget.event;
       Elm.Layout.sizing_eval;
       Elm.Interface.Atspi_Widget_Action.elm_actions.get;
diff --git a/src/lib/elementary/elm_widget_calendar.h 
b/src/lib/elementary/elm_widget_calendar.h
index 18d3cf7..b8f7bdf 100644
--- a/src/lib/elementary/elm_widget_calendar.h
+++ b/src/lib/elementary/elm_widget_calendar.h
@@ -38,7 +38,7 @@ struct _Elm_Calendar_Data
    Eina_List               *marks;
    double                   interval, first_interval;
    int                      spin_speed;
-   int                      today_it, selected_it, first_day_it;
+   int                      today_it, selected_it, first_day_it, focused_it;
    Ecore_Timer             *spin_month, *spin_year, *update_timer;
    Elm_Calendar_Format_Cb   format_func;
    const char              *weekdays[ELM_DAY_LAST];

-- 


Reply via email to