calendar: Add focus UI feature.
authorWoochan Lee <wc0917.lee@samsung.com>
Wed, 23 Nov 2016 07:46:23 +0000 (16:46 +0900)
committerTaehyub Kim <taehyub.kim@samsung.com>
Tue, 29 Nov 2016 12:32:35 +0000 (21:32 +0900)
Change-Id: I570d915e599da102c99c8f39154b054b32e502f2

src/lib/elm_calendar.c
src/lib/elm_calendar.eo
src/lib/elm_widget_calendar.h

index 085383e40ffb22a6833059fa5c2b9bcb53869b5f..b2769a4063963d5cc3afb74cb3ed187185f2c420 100644 (file)
@@ -263,9 +263,15 @@ _eina_tmpstr_steal(Eina_Tmpstr *s)
 }
 
 static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
+//TIZEN_ONLY(20161123): Support Focused UI.
+static Eina_Bool _key_action_activate(Evas_Object *obj, const char *params);
+//
 
 static const Elm_Action key_actions[] = {
    {"move", _key_action_move},
+   //TIZEN_ONLY(20161123): Support Focused UI.
+   {"activate", _key_action_activate},
+   //
    {NULL, NULL}
 };
 
@@ -356,7 +362,10 @@ _select(Evas_Object *obj,
 
    ELM_CALENDAR_DATA_GET(obj, sd);
 
-   sd->selected_it = selected;
+   //TIZEN_ONLY(20161123): Support Focused UI.
+   //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");
 }
@@ -961,6 +970,9 @@ _spinner_buttons_add(Evas_Object *obj, Elm_Calendar_Data *sd)
         if (!sd->dec_btn_month)
           {
              sd->dec_btn_month = elm_button_add(obj);
+             //TIZEN_ONLY(20161123): Support Focused UI.
+             elm_widget_can_focus_set(sd->dec_btn_month, EINA_TRUE);
+             //
              /* TIZEN_ONLY(20161031): apply color_class parent-child relationship to all widgets */
              _elm_widget_color_class_parent_set(sd->dec_btn_month, obj);
              /* END */
@@ -992,6 +1004,9 @@ _spinner_buttons_add(Evas_Object *obj, Elm_Calendar_Data *sd)
         if (!sd->inc_btn_month)
           {
              sd->inc_btn_month = elm_button_add(obj);
+             //TIZEN_ONLY(20161123): Support Focused UI.
+             elm_widget_can_focus_set(sd->inc_btn_month, EINA_TRUE);
+             //
              /* TIZEN_ONLY(20161031): apply color_class parent-child relationship to all widgets */
              _elm_widget_color_class_parent_set(sd->inc_btn_month, obj);
              /* END */
@@ -1023,6 +1038,9 @@ _spinner_buttons_add(Evas_Object *obj, Elm_Calendar_Data *sd)
         if (!sd->dec_btn_year)
           {
              sd->dec_btn_year = elm_button_add(obj);
+             //TIZEN_ONLY(20161123): Support Focused UI.
+             elm_widget_can_focus_set(sd->dec_btn_year, EINA_TRUE);
+             //
              /* TIZEN_ONLY(20161031): apply color_class parent-child relationship to all widgets */
              _elm_widget_color_class_parent_set(sd->dec_btn_year, obj);
              /* END */
@@ -1054,6 +1072,9 @@ _spinner_buttons_add(Evas_Object *obj, Elm_Calendar_Data *sd)
         if (!sd->inc_btn_year)
           {
              sd->inc_btn_year = elm_button_add(obj);
+             //TIZEN_ONLY(20161123): Support Focused UI.
+             elm_widget_can_focus_set(sd->inc_btn_year, EINA_TRUE);
+             //
              /* TIZEN_ONLY(20161031): apply color_class parent-child relationship to all widgets */
              _elm_widget_color_class_parent_set(sd->inc_btn_year, obj);
              /* END */
@@ -1423,6 +1444,49 @@ _get_item_day(Evas_Object *obj,
    return day;
 }
 
+//TIZEN_ONLY(20161123): Support Focused UI.
+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)
@@ -1441,6 +1505,10 @@ _update_sel_it(Evas_Object *obj,
    _unselect(obj, sd->selected_it);
    if (!sd->selected)
      sd->selected = EINA_TRUE;
+   //TIZEN_ONLY(20161123): Support Focused UI.
+   if (sd->focused_it)
+     _update_unfocused_it(obj, sd->focused_it);
+   //
 
    sd->selected_time.tm_mday = day;
    _fix_selected_time(sd);
@@ -1496,6 +1564,267 @@ _update_cur_date(void *data)
    return ECORE_CALLBACK_RENEW;
 }
 
+//TIZEN_ONLY(20161123): Support Focused UI.
+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;
+
+   ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
+
+   _elm_widget_focus_auto_show(obj);
+   if (!strcmp(dir, "prior"))
+     {
+        if (_update_data(obj, EINA_TRUE, -1)) _populate(obj);
+     }
+   else if (!strcmp(dir, "next"))
+     {
+        if (_update_data(obj, EINA_TRUE, 1)) _populate(obj);
+     }
+   else if ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE)
+            && ((sd->select_mode != ELM_CALENDAR_SELECT_MODE_ONDEMAND)
+                || (sd->selected)))
+     {
+        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)))
+               {
+                  //Double spinner case.
+                  if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                    {
+                       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)))
+               {
+                  //Double spinner case.
+                  if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                    {
+                       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)))
+               {
+                  //double spinner case.
+                  if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                    {
+                       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)))
+               {
+                  //double spinner case.
+                  if (edje_object_part_exists(wd->resize_obj, ELM_CALENDAR_BUTTON_YEAR_RIGHT))
+                    {
+                       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;
+     }
+   else return EINA_FALSE;
+
+   return EINA_TRUE;
+}
+
+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;
+
+   eo_do_super(obj, MY_CLASS, int_ret = elm_obj_widget_on_focus(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;
+}
+
+/*
 static Eina_Bool
 _key_action_move(Evas_Object *obj, const char *params)
 {
@@ -1549,6 +1878,8 @@ _key_action_move(Evas_Object *obj, const char *params)
 
    return EINA_TRUE;
 }
+*/
+//END TIZEN_ONLY(20161123): Support Focused UI.
 
 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)
@@ -1717,7 +2048,10 @@ 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;
+   //TIZEN_ONLY(20161123): Support Focused UI.
+   //return EINA_TRUE;
+   return EINA_FALSE;
+   //
 }
 
 EOLIAN static Eina_Bool
@@ -2131,6 +2465,9 @@ _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},
+          //TIZEN_ONLY(20161123): Support Focused UI.
+          { "activate", "activate", NULL, _key_action_activate},
+          //
           { NULL, NULL, NULL, NULL }
    };
    return &atspi_actions[0];
index 66421fa1a0a4a0ca9de56f0969c70002f4ddea75..871a1ebe1256d219283bc869613ecd1b44af35cc 100644 (file)
@@ -524,6 +524,9 @@ class Elm.Calendar (Elm.Layout, Elm_Interface_Atspi_Widget_Action)
       Elm.Widget.mirrored;
       //
       Elm.Widget.focus_next;
+      //TIZEN_ONLY(20161123): Support Focused UI.
+      Elm.Widget.on_focus;
+      //
       Elm.Widget.event;
       Elm.Layout.sizing_eval;
       Elm_Interface_Atspi_Widget_Action.elm_actions.get;
index 425860f2c1e8e79d0b2e7a6a68c1ae22c7008928..36ec378e57c7f195d01dc09b57ecc95d1dd002b7 100644 (file)
@@ -39,6 +39,9 @@ struct _Elm_Calendar_Data
    Eina_List               *marks;
    double                   interval, first_interval;
    int                      year_min, year_max, spin_speed;
+   //TIZEN_ONLY(20161123): Support Focused UI.
+   int                     focused_it;
+   //
    int                      today_it, selected_it, first_day_it;
    Ecore_Timer             *spin_month, *spin_year, *update_timer;
    Elm_Calendar_Format_Cb   format_func;