summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWoochan Lee <wc0917.lee@samsung.com>2016-11-28 10:58:57 -0800
committerCedric BAIL <cedric@osg.samsung.com>2016-11-28 11:35:27 -0800
commit6c04755a922d396356a561b85e010105e6ff61ae (patch)
tree2d681d32c258d671485a99cd069c442bc555b9e4
parent05246782dc9c94eeb24bb29e1489ced512259cca (diff)
downloadefl-6c04755a922d396356a561b85e010105e6ff61ae.tar.gz
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 <cedric@osg.samsung.com>
-rw-r--r--config/default/base.src.in18
-rw-r--r--config/mobile/base.src.in18
-rw-r--r--config/standard/base.src.in18
-rw-r--r--data/elementary/themes/edc/elm/calendar.edc62
-rw-r--r--src/lib/elementary/elm_calendar.c266
-rw-r--r--src/lib/elementary/elm_calendar.eo1
-rw-r--r--src/lib/elementary/elm_widget_calendar.h2
7 files changed, 378 insertions, 7 deletions
diff --git a/config/default/base.src.in b/config/default/base.src.in
index dfecc901d8..9128b98d97 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 ebc5070ae6..f1a357b22e 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 d5cd732f3f..678e274515 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 662bd51def..8dfffc169c 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 b0fcc580b7..6e57c26346 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 b312f486be..9890b2f1c9 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 18d3cf7546..b8f7bdf78f 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];