diff options
Diffstat (limited to 'src/lib/elementary/efl_ui_scroller.c')
-rw-r--r-- | src/lib/elementary/efl_ui_scroller.c | 171 |
1 files changed, 168 insertions, 3 deletions
diff --git a/src/lib/elementary/efl_ui_scroller.c b/src/lib/elementary/efl_ui_scroller.c index a4f6545..5891e42 100644 --- a/src/lib/elementary/efl_ui_scroller.c +++ b/src/lib/elementary/efl_ui_scroller.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #define ELM_LAYOUT_PROTECTED | 5 | #define ELM_LAYOUT_PROTECTED |
6 | #define EFL_UI_SCROLL_MANAGER_PROTECTED | 6 | #define EFL_UI_SCROLL_MANAGER_PROTECTED |
7 | #define EFL_UI_SCROLLBAR_PROTECTED | 7 | #define EFL_UI_SCROLLBAR_PROTECTED |
8 | #define EFL_UI_WIDGET_FOCUS_MANAGER_PROTECTED | ||
8 | 9 | ||
9 | #include <Elementary.h> | 10 | #include <Elementary.h> |
10 | #include "elm_priv.h" | 11 | #include "elm_priv.h" |
@@ -27,6 +28,126 @@ | |||
27 | o, evas_object_type_get(o)); \ | 28 | o, evas_object_type_get(o)); \ |
28 | return __VA_ARGS__; \ | 29 | return __VA_ARGS__; \ |
29 | } | 30 | } |
31 | |||
32 | static Eina_Bool _key_action_move(Evas_Object *obj, const char *params); | ||
33 | |||
34 | static const Elm_Action key_actions[] = { | ||
35 | {"move", _key_action_move}, | ||
36 | {NULL, NULL} | ||
37 | }; | ||
38 | |||
39 | static Eina_Bool | ||
40 | _key_action_move(Eo *obj, const char *params) | ||
41 | { | ||
42 | EFL_UI_SCROLLER_DATA_GET_OR_RETURN(obj, sd, EINA_FALSE); | ||
43 | |||
44 | const char *dir = params; | ||
45 | Efl_Ui_Focus_Direction focus_dir = 0; | ||
46 | Efl_Ui_Focus_Object *focused, *next_target; | ||
47 | Eina_Rect focused_geom, viewport; | ||
48 | Eina_Position2D pos; | ||
49 | Eina_Size2D max; | ||
50 | Eina_Bool scroller_adjustment = EINA_FALSE; | ||
51 | |||
52 | pos = efl_ui_scrollable_content_pos_get(obj); | ||
53 | viewport = efl_ui_scrollable_viewport_geometry_get(obj); | ||
54 | max = efl_gfx_entity_size_get(sd->content); | ||
55 | if (!strcmp(dir, "prior")) | ||
56 | focus_dir = EFL_UI_FOCUS_DIRECTION_PREVIOUS; | ||
57 | else if (!strcmp(dir, "next")) | ||
58 | focus_dir = EFL_UI_FOCUS_DIRECTION_NEXT; | ||
59 | else if (!strcmp(dir, "left")) | ||
60 | focus_dir = EFL_UI_FOCUS_DIRECTION_LEFT; | ||
61 | else if (!strcmp(dir, "right")) | ||
62 | focus_dir = EFL_UI_FOCUS_DIRECTION_RIGHT; | ||
63 | else if (!strcmp(dir, "up")) | ||
64 | focus_dir = EFL_UI_FOCUS_DIRECTION_UP; | ||
65 | else if (!strcmp(dir, "down")) | ||
66 | focus_dir = EFL_UI_FOCUS_DIRECTION_DOWN; | ||
67 | else return EINA_FALSE; | ||
68 | |||
69 | focused = efl_ui_focus_manager_focus_get(obj); | ||
70 | next_target = efl_ui_focus_manager_request_move(obj, focus_dir, focused, EINA_FALSE); | ||
71 | |||
72 | //logical movement is handled by focus directly | ||
73 | if (focused && | ||
74 | (focus_dir == EFL_UI_FOCUS_DIRECTION_NEXT || | ||
75 | focus_dir == EFL_UI_FOCUS_DIRECTION_PREVIOUS)) | ||
76 | return EINA_FALSE; | ||
77 | //check if a object that is focused is lapping out of the viewport | ||
78 | // if this is the case, and the object is lapping out of the viewport in | ||
79 | // the direction we want to move, then move the scroller | ||
80 | if (focused) | ||
81 | { | ||
82 | Eina_Rectangle_Outside relative; | ||
83 | |||
84 | focused_geom = efl_gfx_entity_geometry_get(focused); | ||
85 | |||
86 | relative = eina_rectangle_outside_position(&viewport.rect, &focused_geom.rect); | ||
87 | |||
88 | //now precisly check if the direction is also lapping out | ||
89 | if ((focus_dir == EFL_UI_FOCUS_DIRECTION_UP && (relative & EINA_RECTANGLE_OUTSIDE_TOP)) || | ||
90 | (focus_dir == EFL_UI_FOCUS_DIRECTION_LEFT && (relative & EINA_RECTANGLE_OUTSIDE_LEFT)) || | ||
91 | (focus_dir == EFL_UI_FOCUS_DIRECTION_DOWN && (relative & EINA_RECTANGLE_OUTSIDE_BOTTOM)) || | ||
92 | (focus_dir == EFL_UI_FOCUS_DIRECTION_RIGHT && (relative & EINA_RECTANGLE_OUTSIDE_RIGHT))) | ||
93 | { | ||
94 | scroller_adjustment = EINA_TRUE; | ||
95 | } | ||
96 | } | ||
97 | //check if there is a next target in the direction where we want to move | ||
98 | //if not, and the scroller is not at its max in that relation, | ||
99 | //then move the scroller instead of the focus | ||
100 | if (!next_target) | ||
101 | { | ||
102 | if ((focus_dir == EFL_UI_FOCUS_DIRECTION_UP && (pos.y != 0)) || | ||
103 | (focus_dir == EFL_UI_FOCUS_DIRECTION_LEFT && (pos.x != 0)) || | ||
104 | (focus_dir == EFL_UI_FOCUS_DIRECTION_DOWN && (pos.y != max.h)) || | ||
105 | (focus_dir == EFL_UI_FOCUS_DIRECTION_RIGHT && (pos.x != max.w))) | ||
106 | { | ||
107 | scroller_adjustment = EINA_TRUE; | ||
108 | } | ||
109 | } | ||
110 | if (!scroller_adjustment) | ||
111 | return EINA_FALSE; | ||
112 | |||
113 | Eina_Position2D step = efl_ui_scrollable_step_size_get(obj); | ||
114 | |||
115 | if (!strcmp(dir, "left")) | ||
116 | { | ||
117 | if (pos.x <= 0) return EINA_FALSE; | ||
118 | pos.x -= step.x; | ||
119 | } | ||
120 | else if (!strcmp(dir, "right")) | ||
121 | { | ||
122 | if (pos.x >= (max.w - viewport.w)) return EINA_FALSE; | ||
123 | pos.x += step.x; | ||
124 | } | ||
125 | else if (!strcmp(dir, "up")) | ||
126 | { | ||
127 | if (pos.y <= 0) return EINA_FALSE; | ||
128 | pos.y -= step.y; | ||
129 | } | ||
130 | else if (!strcmp(dir, "down")) | ||
131 | { | ||
132 | if (pos.y >= (max.h - viewport.h)) return EINA_FALSE; | ||
133 | pos.y += step.y; | ||
134 | } | ||
135 | else if (!strcmp(dir, "first")) | ||
136 | { | ||
137 | pos.y = 0; | ||
138 | } | ||
139 | else if (!strcmp(dir, "last")) | ||
140 | { | ||
141 | pos.y = max.h - viewport.h; | ||
142 | } | ||
143 | else return EINA_FALSE; | ||
144 | |||
145 | efl_ui_scrollable_scroll(obj, EINA_RECT(pos.x, pos.y, viewport.w, viewport.h), EINA_FALSE); | ||
146 | |||
147 | return EINA_TRUE; | ||
148 | } | ||
149 | |||
150 | |||
30 | static void | 151 | static void |
31 | _efl_ui_scroller_content_del_cb(void *data, | 152 | _efl_ui_scroller_content_del_cb(void *data, |
32 | const Efl_Event *event EINA_UNUSED) | 153 | const Efl_Event *event EINA_UNUSED) |
@@ -406,6 +527,25 @@ _efl_ui_scroller_size_hint_changed_cb(void *data, const Efl_Event *ev EINA_UNUSE | |||
406 | elm_layout_sizing_eval(data); | 527 | elm_layout_sizing_eval(data); |
407 | } | 528 | } |
408 | 529 | ||
530 | static void | ||
531 | _focused_element(void *data, const Efl_Event *event) | ||
532 | { | ||
533 | Eina_Rect geom; | ||
534 | Efl_Ui_Focus_Object *obj = data; | ||
535 | Efl_Ui_Focus_Object *focus = efl_ui_focus_manager_focus_get(event->object); | ||
536 | Eina_Position2D pos, pan; | ||
537 | |||
538 | if (!focus) return; | ||
539 | |||
540 | geom = efl_ui_focus_object_focus_geometry_get(focus); | ||
541 | pos = efl_gfx_entity_position_get(obj); | ||
542 | pan = efl_ui_scrollable_content_pos_get(obj); | ||
543 | geom.x += pan.x - pos.x; | ||
544 | geom.y += pan.y - pos.y; | ||
545 | |||
546 | efl_ui_scrollable_scroll(obj, geom, EINA_TRUE); | ||
547 | } | ||
548 | |||
409 | EOLIAN static Eo * | 549 | EOLIAN static Eo * |
410 | _efl_ui_scroller_efl_object_constructor(Eo *obj, | 550 | _efl_ui_scroller_efl_object_constructor(Eo *obj, |
411 | Efl_Ui_Scroller_Data *sd EINA_UNUSED) | 551 | Efl_Ui_Scroller_Data *sd EINA_UNUSED) |
@@ -434,6 +574,8 @@ _efl_ui_scroller_efl_object_finalize(Eo *obj, | |||
434 | efl_ui_scroll_manager_pan_set(sd->smanager, sd->pan_obj); | 574 | efl_ui_scroll_manager_pan_set(sd->smanager, sd->pan_obj); |
435 | edje_object_part_swallow(wd->resize_obj, "efl.content", sd->pan_obj); | 575 | edje_object_part_swallow(wd->resize_obj, "efl.content", sd->pan_obj); |
436 | 576 | ||
577 | elm_widget_can_focus_set(obj, EINA_TRUE); | ||
578 | |||
437 | _scroll_edje_object_attach(obj); | 579 | _scroll_edje_object_attach(obj); |
438 | 580 | ||
439 | efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, | 581 | efl_event_callback_add(obj, EFL_UI_SCROLLBAR_EVENT_BAR_SIZE_CHANGED, |
@@ -451,6 +593,7 @@ _efl_ui_scroller_efl_object_finalize(Eo *obj, | |||
451 | efl_event_callback_add(sd->pan_obj, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, | 593 | efl_event_callback_add(sd->pan_obj, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, |
452 | _efl_ui_scroller_pan_resized_cb, obj); | 594 | _efl_ui_scroller_pan_resized_cb, obj); |
453 | 595 | ||
596 | efl_event_callback_add(obj, EFL_UI_FOCUS_MANAGER_EVENT_MANAGER_FOCUS_CHANGED, _focused_element, obj); | ||
454 | return obj; | 597 | return obj; |
455 | } | 598 | } |
456 | 599 | ||
@@ -535,12 +678,12 @@ _efl_ui_scroller_elm_layout_sizing_eval(Eo *obj, Efl_Ui_Scroller_Data *sd) | |||
535 | efl_gfx_hint_size_min_set(obj, size); | 678 | efl_gfx_hint_size_min_set(obj, size); |
536 | } | 679 | } |
537 | 680 | ||
538 | EOLIAN static Efl_Ui_Theme_Apply_Result | 681 | EOLIAN static Eina_Error |
539 | _efl_ui_scroller_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Scroller_Data *sd) | 682 | _efl_ui_scroller_efl_ui_widget_theme_apply(Eo *obj, Efl_Ui_Scroller_Data *sd) |
540 | { | 683 | { |
541 | Efl_Ui_Theme_Apply_Result int_ret = EFL_UI_THEME_APPLY_RESULT_FAIL; | 684 | Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC; |
542 | int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); | 685 | int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS)); |
543 | if (!int_ret) return EFL_UI_THEME_APPLY_RESULT_FAIL; | 686 | if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret; |
544 | 687 | ||
545 | efl_ui_mirrored_set(sd->smanager, efl_ui_mirrored_get(obj)); | 688 | efl_ui_mirrored_set(sd->smanager, efl_ui_mirrored_get(obj)); |
546 | 689 | ||
@@ -563,6 +706,28 @@ _efl_ui_scroller_efl_ui_scrollable_interactive_match_content_set(Eo *obj EINA_UN | |||
563 | elm_layout_sizing_eval(obj); | 706 | elm_layout_sizing_eval(obj); |
564 | } | 707 | } |
565 | 708 | ||
709 | EOLIAN static Eina_Bool | ||
710 | _efl_ui_scroller_efl_ui_widget_focus_state_apply(Eo *obj, Efl_Ui_Scroller_Data *pd EINA_UNUSED, Efl_Ui_Widget_Focus_State current_state, Efl_Ui_Widget_Focus_State *configured_state, Efl_Ui_Widget *redirect EINA_UNUSED) | ||
711 | { | ||
712 | //undepended from logical or not we always reigster as full with ourself as redirect | ||
713 | configured_state->logical = EINA_TRUE; | ||
714 | return efl_ui_widget_focus_state_apply(efl_super(obj, MY_CLASS), current_state, configured_state, obj); | ||
715 | } | ||
716 | |||
717 | EOLIAN static Efl_Ui_Focus_Manager* | ||
718 | _efl_ui_scroller_efl_ui_widget_focus_manager_focus_manager_create(Eo *obj, Efl_Ui_Scroller_Data *pd EINA_UNUSED, Efl_Ui_Focus_Object *root) | ||
719 | { | ||
720 | Efl_Ui_Focus_Manager *manager; | ||
721 | manager = efl_add(EFL_UI_FOCUS_MANAGER_ROOT_FOCUS_CLASS, obj, | ||
722 | efl_ui_focus_manager_root_set(efl_added, root)); | ||
723 | |||
724 | return manager; | ||
725 | } | ||
726 | |||
727 | /* Standard widget overrides */ | ||
728 | |||
729 | ELM_WIDGET_KEY_DOWN_DEFAULT_IMPLEMENT(efl_ui_scroller, Efl_Ui_Scroller_Data) | ||
730 | |||
566 | /* Internal EO APIs and hidden overrides */ | 731 | /* Internal EO APIs and hidden overrides */ |
567 | 732 | ||
568 | #define EFL_UI_SCROLLER_EXTRA_OPS \ | 733 | #define EFL_UI_SCROLLER_EXTRA_OPS \ |