summaryrefslogtreecommitdiff
path: root/src/lib/elementary/efl_ui_scroller.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/elementary/efl_ui_scroller.c')
-rw-r--r--src/lib/elementary/efl_ui_scroller.c171
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
32static Eina_Bool _key_action_move(Evas_Object *obj, const char *params);
33
34static const Elm_Action key_actions[] = {
35 {"move", _key_action_move},
36 {NULL, NULL}
37};
38
39static 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
30static void 151static 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
530static 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
409EOLIAN static Eo * 549EOLIAN 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
538EOLIAN static Efl_Ui_Theme_Apply_Result 681EOLIAN 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
709EOLIAN 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
717EOLIAN 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
729ELM_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 \