diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/elementary/src/lib/elm_scroller.c | 765 |
1 files changed, 765 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_scroller.c b/libraries/elementary/src/lib/elm_scroller.c new file mode 100644 index 0000000..49959b2 --- /dev/null +++ b/libraries/elementary/src/lib/elm_scroller.c | |||
@@ -0,0 +1,765 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | #include "els_scroller.h" | ||
4 | |||
5 | typedef struct _Widget_Data Widget_Data; | ||
6 | |||
7 | struct _Widget_Data | ||
8 | { | ||
9 | Evas_Object *scr; | ||
10 | Evas_Object *content; | ||
11 | const char *widget_name, *widget_base; | ||
12 | Eina_Bool min_w : 1; | ||
13 | Eina_Bool min_h : 1; | ||
14 | double pagerel_h, pagerel_v; | ||
15 | Evas_Coord pagesize_h, pagesize_v; | ||
16 | }; | ||
17 | |||
18 | static const char *widtype = NULL; | ||
19 | static void _del_hook(Evas_Object *obj); | ||
20 | static void _theme_hook(Evas_Object *obj); | ||
21 | static void _show_region_hook(void *data, Evas_Object *obj); | ||
22 | static void _sizing_eval(Evas_Object *obj); | ||
23 | static void _sub_del(void *data, Evas_Object *obj, void *event_info); | ||
24 | static void _on_focus_hook(void *data, Evas_Object *obj); | ||
25 | static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, | ||
26 | Evas_Callback_Type type, void *event_info); | ||
27 | |||
28 | |||
29 | static const char SIG_SCROLL[] = "scroll"; | ||
30 | static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start"; | ||
31 | static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop"; | ||
32 | static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start"; | ||
33 | static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop"; | ||
34 | static const char SIG_EDGE_LEFT[] = "edge,left"; | ||
35 | static const char SIG_EDGE_RIGHT[] = "edge,right"; | ||
36 | static const char SIG_EDGE_TOP[] = "edge,top"; | ||
37 | static const char SIG_EDGE_BOTTOM[] = "edge,bottom"; | ||
38 | static const Evas_Smart_Cb_Description _signals[] = { | ||
39 | {SIG_SCROLL, ""}, | ||
40 | {SIG_SCROLL_ANIM_START, ""}, | ||
41 | {SIG_SCROLL_ANIM_STOP, ""}, | ||
42 | {SIG_SCROLL_DRAG_START, ""}, | ||
43 | {SIG_SCROLL_DRAG_STOP, ""}, | ||
44 | {SIG_EDGE_LEFT, ""}, | ||
45 | {SIG_EDGE_RIGHT, ""}, | ||
46 | {SIG_EDGE_TOP, ""}, | ||
47 | {SIG_EDGE_BOTTOM, ""}, | ||
48 | {NULL, NULL} | ||
49 | }; | ||
50 | |||
51 | static Eina_Bool | ||
52 | _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info) | ||
53 | { | ||
54 | if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE; | ||
55 | Evas_Event_Key_Down *ev = event_info; | ||
56 | Widget_Data *wd = elm_widget_data_get(obj); | ||
57 | if (!wd) return EINA_FALSE; | ||
58 | if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE; | ||
59 | if (elm_widget_disabled_get(obj)) return EINA_FALSE; | ||
60 | |||
61 | Evas_Coord x = 0; | ||
62 | Evas_Coord y = 0; | ||
63 | Evas_Coord step_x = 0; | ||
64 | Evas_Coord step_y = 0; | ||
65 | Evas_Coord max_x = 0; | ||
66 | Evas_Coord max_y = 0; | ||
67 | Evas_Coord v_w = 0; | ||
68 | Evas_Coord v_h = 0; | ||
69 | Evas_Coord page_x = 0; | ||
70 | Evas_Coord page_y = 0; | ||
71 | |||
72 | elm_smart_scroller_child_pos_get(wd->scr, &x, &y); | ||
73 | elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y); | ||
74 | elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y); | ||
75 | elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h); | ||
76 | elm_scroller_child_size_get(obj, &max_x, &max_y); | ||
77 | |||
78 | if ((!strcmp(ev->keyname, "Left")) || | ||
79 | ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string))) | ||
80 | { | ||
81 | x -= step_x; | ||
82 | } | ||
83 | else if ((!strcmp(ev->keyname, "Right")) || | ||
84 | ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string))) | ||
85 | { | ||
86 | x += step_x; | ||
87 | } | ||
88 | else if ((!strcmp(ev->keyname, "Up")) || | ||
89 | ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string))) | ||
90 | { | ||
91 | y -= step_y; | ||
92 | } | ||
93 | else if ((!strcmp(ev->keyname, "Down")) || | ||
94 | ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string))) | ||
95 | { | ||
96 | y += step_y; | ||
97 | } | ||
98 | else if ((!strcmp(ev->keyname, "Home")) || | ||
99 | ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string))) | ||
100 | { | ||
101 | y = 0; | ||
102 | } | ||
103 | else if ((!strcmp(ev->keyname, "End")) || | ||
104 | ((!strcmp(ev->keyname, "KP_End")) && (!ev->string))) | ||
105 | { | ||
106 | y = max_y - v_h; | ||
107 | } | ||
108 | else if ((!strcmp(ev->keyname, "Prior")) || | ||
109 | ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string))) | ||
110 | { | ||
111 | if (page_y < 0) | ||
112 | y -= -(page_y * v_h) / 100; | ||
113 | else | ||
114 | y -= page_y; | ||
115 | } | ||
116 | else if ((!strcmp(ev->keyname, "Next")) || | ||
117 | ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string))) | ||
118 | { | ||
119 | if (page_y < 0) | ||
120 | y += -(page_y * v_h) / 100; | ||
121 | else | ||
122 | y += page_y; | ||
123 | } | ||
124 | else return EINA_FALSE; | ||
125 | |||
126 | ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; | ||
127 | elm_smart_scroller_child_pos_set(wd->scr, x, y); | ||
128 | return EINA_TRUE; | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | _on_focus_hook(void *data __UNUSED__, Evas_Object *obj) | ||
133 | { | ||
134 | Widget_Data *wd = elm_widget_data_get(obj); | ||
135 | if (!wd) return; | ||
136 | if (elm_widget_focus_get(obj)) | ||
137 | { | ||
138 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm"); | ||
139 | evas_object_focus_set(wd->scr, EINA_TRUE); | ||
140 | } | ||
141 | else | ||
142 | { | ||
143 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm"); | ||
144 | evas_object_focus_set(wd->scr, EINA_FALSE); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static void | ||
149 | _del_hook(Evas_Object *obj) | ||
150 | { | ||
151 | Widget_Data *wd = elm_widget_data_get(obj); | ||
152 | if (!wd) return; | ||
153 | free(wd); | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | _mirrored_set(Evas_Object *obj, Eina_Bool mirrored) | ||
158 | { | ||
159 | Widget_Data *wd = elm_widget_data_get(obj); | ||
160 | if (!wd) return; | ||
161 | if (wd->scr) | ||
162 | elm_smart_scroller_mirrored_set(wd->scr, mirrored); | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | _theme_hook(Evas_Object *obj) | ||
167 | { | ||
168 | Widget_Data *wd = elm_widget_data_get(obj); | ||
169 | if (!wd) return; | ||
170 | _elm_widget_mirrored_reload(obj); | ||
171 | if (wd->scr) | ||
172 | { | ||
173 | Evas_Object *edj; | ||
174 | const char *str; | ||
175 | |||
176 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
177 | elm_smart_scroller_object_theme_set(obj, wd->scr, | ||
178 | wd->widget_name, wd->widget_base, | ||
179 | elm_widget_style_get(obj)); | ||
180 | // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale); | ||
181 | edj = elm_smart_scroller_edje_object_get(wd->scr); | ||
182 | str = edje_object_data_get(edj, "focus_highlight"); | ||
183 | if ((str) && (!strcmp(str, "on"))) | ||
184 | elm_widget_highlight_in_theme_set(obj, EINA_TRUE); | ||
185 | else | ||
186 | elm_widget_highlight_in_theme_set(obj, EINA_FALSE); | ||
187 | } | ||
188 | _sizing_eval(obj); | ||
189 | } | ||
190 | |||
191 | static Eina_Bool | ||
192 | _elm_scroller_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) | ||
193 | { | ||
194 | Widget_Data *wd = elm_widget_data_get(obj); | ||
195 | Evas_Object *cur; | ||
196 | |||
197 | if ((!wd) || (!wd->content)) | ||
198 | return EINA_FALSE; | ||
199 | |||
200 | cur = wd->content; | ||
201 | |||
202 | /* Try Focus cycle in subitem */ | ||
203 | if (elm_widget_focus_get(obj)) | ||
204 | { | ||
205 | if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur))) | ||
206 | return elm_widget_focus_next_get(cur, dir, next); | ||
207 | } | ||
208 | |||
209 | /* Return */ | ||
210 | *next = (Evas_Object *)obj; | ||
211 | return !elm_widget_focus_get(obj); | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source) | ||
216 | { | ||
217 | Widget_Data *wd = elm_widget_data_get(obj); | ||
218 | if (!wd) return; | ||
219 | edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), | ||
220 | emission, source); | ||
221 | } | ||
222 | |||
223 | static void | ||
224 | _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
225 | { | ||
226 | Widget_Data *wd = elm_widget_data_get(obj); | ||
227 | if (!wd) return; | ||
228 | edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr), | ||
229 | emission, source, func_cb, data); | ||
230 | } | ||
231 | |||
232 | static void | ||
233 | _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
234 | { | ||
235 | Widget_Data *wd = elm_widget_data_get(obj); | ||
236 | edje_object_signal_callback_del_full( | ||
237 | elm_smart_scroller_edje_object_get(wd->scr), emission, source, | ||
238 | func_cb, data); | ||
239 | } | ||
240 | |||
241 | static void | ||
242 | _show_region_hook(void *data, Evas_Object *obj) | ||
243 | { | ||
244 | Widget_Data *wd = elm_widget_data_get(data); | ||
245 | Evas_Coord x, y, w, h; | ||
246 | if (!wd) return; | ||
247 | elm_widget_show_region_get(obj, &x, &y, &w, &h); | ||
248 | if (wd->scr) | ||
249 | elm_smart_scroller_child_region_show(wd->scr, x, y, w, h); | ||
250 | } | ||
251 | |||
252 | static void | ||
253 | _focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) | ||
254 | { | ||
255 | Widget_Data *wd = elm_widget_data_get(obj); | ||
256 | if (wd->scr) | ||
257 | elm_smart_scroller_child_region_show(wd->scr, x, y, w, h); | ||
258 | } | ||
259 | |||
260 | static void | ||
261 | _sizing_eval(Evas_Object *obj) | ||
262 | { | ||
263 | Widget_Data *wd = elm_widget_data_get(obj); | ||
264 | Evas_Coord vw = 0, vh = 0, minw = 0, minh = 0, maxw = 0, maxh = 0, w, h, vmw, vmh; | ||
265 | double xw = 0.0, yw = 0.0; | ||
266 | |||
267 | if (!wd) return; | ||
268 | if (wd->content) | ||
269 | { | ||
270 | evas_object_size_hint_min_get(wd->content, &minw, &minh); | ||
271 | evas_object_size_hint_max_get(wd->content, &maxw, &maxh); | ||
272 | evas_object_size_hint_weight_get(wd->content, &xw, &yw); | ||
273 | } | ||
274 | if (wd->scr) | ||
275 | { | ||
276 | elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh); | ||
277 | if (xw > 0.0) | ||
278 | { | ||
279 | if ((minw > 0) && (vw < minw)) vw = minw; | ||
280 | else if ((maxw > 0) && (vw > maxw)) vw = maxw; | ||
281 | } | ||
282 | else if (minw > 0) vw = minw; | ||
283 | if (yw > 0.0) | ||
284 | { | ||
285 | if ((minh > 0) && (vh < minh)) vh = minh; | ||
286 | else if ((maxh > 0) && (vh > maxh)) vh = maxh; | ||
287 | } | ||
288 | else if (minh > 0) vh = minh; | ||
289 | if (wd->content) evas_object_resize(wd->content, vw, vh); | ||
290 | w = -1; | ||
291 | h = -1; | ||
292 | edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh); | ||
293 | if (wd->min_w) w = vmw + minw; | ||
294 | if (wd->min_h) h = vmh + minh; | ||
295 | evas_object_size_hint_max_get(obj, &maxw, &maxh); | ||
296 | if ((maxw > 0) && (w > maxw)) w = maxw; | ||
297 | if ((maxh > 0) && (h > maxh)) h = maxh; | ||
298 | evas_object_size_hint_min_set(obj, w, h); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | static void | ||
303 | _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
304 | { | ||
305 | _sizing_eval(data); | ||
306 | } | ||
307 | |||
308 | static void | ||
309 | _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info) | ||
310 | { | ||
311 | Widget_Data *wd = elm_widget_data_get(obj); | ||
312 | Evas_Object *sub = event_info; | ||
313 | |||
314 | if (!wd) return; | ||
315 | if (sub == wd->content) | ||
316 | { | ||
317 | elm_widget_on_show_region_hook_set(wd->content, NULL, NULL); | ||
318 | evas_object_event_callback_del_full (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
319 | _changed_size_hints, obj); | ||
320 | wd->content = NULL; | ||
321 | _sizing_eval(obj); | ||
322 | } | ||
323 | else if (sub == wd->scr) | ||
324 | wd->scr = NULL; | ||
325 | } | ||
326 | |||
327 | static void | ||
328 | _hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
329 | { | ||
330 | Widget_Data *wd = elm_widget_data_get(obj); | ||
331 | |||
332 | if (!wd) return; | ||
333 | if (wd->scr) | ||
334 | elm_smart_scroller_hold_set(wd->scr, 1); | ||
335 | } | ||
336 | |||
337 | static void | ||
338 | _hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
339 | { | ||
340 | Widget_Data *wd = elm_widget_data_get(obj); | ||
341 | |||
342 | if (!wd) return; | ||
343 | if (wd->scr) | ||
344 | elm_smart_scroller_hold_set(wd->scr, 0); | ||
345 | } | ||
346 | |||
347 | static void | ||
348 | _freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
349 | { | ||
350 | Widget_Data *wd = elm_widget_data_get(obj); | ||
351 | |||
352 | if (!wd) return; | ||
353 | if (wd->scr) | ||
354 | elm_smart_scroller_freeze_set(wd->scr, 1); | ||
355 | } | ||
356 | |||
357 | static void | ||
358 | _freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
359 | { | ||
360 | Widget_Data *wd = elm_widget_data_get(obj); | ||
361 | |||
362 | if (!wd) return; | ||
363 | if (wd->scr) | ||
364 | elm_smart_scroller_freeze_set(wd->scr, 0); | ||
365 | } | ||
366 | |||
367 | static void | ||
368 | _resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
369 | { | ||
370 | _sizing_eval(data); | ||
371 | } | ||
372 | |||
373 | static void | ||
374 | _edge_left(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
375 | { | ||
376 | evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL); | ||
377 | } | ||
378 | |||
379 | static void | ||
380 | _edge_right(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
381 | { | ||
382 | evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL); | ||
383 | } | ||
384 | |||
385 | static void | ||
386 | _edge_top(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
387 | { | ||
388 | evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL); | ||
389 | } | ||
390 | |||
391 | static void | ||
392 | _edge_bottom(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
393 | { | ||
394 | evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL); | ||
395 | } | ||
396 | |||
397 | static void | ||
398 | _scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
399 | { | ||
400 | evas_object_smart_callback_call(data, SIG_SCROLL, NULL); | ||
401 | } | ||
402 | |||
403 | static void | ||
404 | _scroll_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
405 | { | ||
406 | evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL); | ||
407 | } | ||
408 | |||
409 | static void | ||
410 | _scroll_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
411 | { | ||
412 | evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL); | ||
413 | } | ||
414 | |||
415 | static void | ||
416 | _scroll_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
417 | { | ||
418 | evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL); | ||
419 | } | ||
420 | |||
421 | static void | ||
422 | _scroll_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
423 | { | ||
424 | evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL); | ||
425 | } | ||
426 | |||
427 | Evas_Object * | ||
428 | _elm_scroller_edje_object_get(Evas_Object *obj) | ||
429 | { | ||
430 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
431 | Widget_Data *wd = elm_widget_data_get(obj); | ||
432 | if (!wd) return NULL; | ||
433 | return elm_smart_scroller_edje_object_get(wd->scr); | ||
434 | } | ||
435 | |||
436 | static void | ||
437 | _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) | ||
438 | { | ||
439 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
440 | Widget_Data *wd; | ||
441 | if (part && strcmp(part, "default")) return; | ||
442 | wd = elm_widget_data_get(obj); | ||
443 | if (!wd) return; | ||
444 | if (wd->content == content) return; | ||
445 | if (wd->content) evas_object_del(wd->content); | ||
446 | wd->content = content; | ||
447 | if (content) | ||
448 | { | ||
449 | elm_widget_on_show_region_hook_set(content, _show_region_hook, obj); | ||
450 | elm_widget_sub_object_add(obj, content); | ||
451 | if (wd->scr) | ||
452 | elm_smart_scroller_child_set(wd->scr, content); | ||
453 | evas_object_event_callback_add(content, | ||
454 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
455 | _changed_size_hints, obj); | ||
456 | } | ||
457 | _sizing_eval(obj); | ||
458 | } | ||
459 | |||
460 | static Evas_Object * | ||
461 | _content_get_hook(const Evas_Object *obj, const char *part) | ||
462 | { | ||
463 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
464 | Widget_Data *wd; | ||
465 | if (part && strcmp(part, "default")) return NULL; | ||
466 | wd = elm_widget_data_get(obj); | ||
467 | if (!wd) return NULL; | ||
468 | return wd->content; | ||
469 | } | ||
470 | |||
471 | static Evas_Object * | ||
472 | _content_unset_hook(Evas_Object *obj, const char *part) | ||
473 | { | ||
474 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
475 | Widget_Data *wd; | ||
476 | Evas_Object *content; | ||
477 | if (part && strcmp(part, "default")) return NULL; | ||
478 | wd = elm_widget_data_get(obj); | ||
479 | if (!wd) return NULL; | ||
480 | if (!wd->content) return NULL; | ||
481 | content = wd->content; | ||
482 | elm_widget_sub_object_del(obj, wd->content); | ||
483 | evas_object_event_callback_del_full(wd->content, | ||
484 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
485 | _changed_size_hints, obj); | ||
486 | edje_object_part_unswallow(elm_smart_scroller_edje_object_get(wd->scr), | ||
487 | wd->content); | ||
488 | wd->content = NULL; | ||
489 | return content; | ||
490 | } | ||
491 | |||
492 | EAPI Evas_Object * | ||
493 | elm_scroller_add(Evas_Object *parent) | ||
494 | { | ||
495 | Evas_Object *obj; | ||
496 | Evas *e; | ||
497 | Widget_Data *wd; | ||
498 | Evas_Coord minw, minh; | ||
499 | |||
500 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
501 | |||
502 | ELM_SET_WIDTYPE(widtype, "scroller"); | ||
503 | elm_widget_type_set(obj, "scroller"); | ||
504 | elm_widget_sub_object_add(parent, obj); | ||
505 | elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL); | ||
506 | elm_widget_data_set(obj, wd); | ||
507 | elm_widget_del_hook_set(obj, _del_hook); | ||
508 | elm_widget_theme_hook_set(obj, _theme_hook); | ||
509 | elm_widget_signal_emit_hook_set(obj, _signal_emit_hook); | ||
510 | elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); | ||
511 | elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); | ||
512 | elm_widget_focus_next_hook_set(obj, _elm_scroller_focus_next_hook); | ||
513 | elm_widget_can_focus_set(obj, EINA_TRUE); | ||
514 | elm_widget_event_hook_set(obj, _event_hook); | ||
515 | elm_widget_focus_region_hook_set(obj, _focus_region_hook); | ||
516 | elm_widget_content_set_hook_set(obj, _content_set_hook); | ||
517 | elm_widget_content_get_hook_set(obj, _content_get_hook); | ||
518 | elm_widget_content_unset_hook_set(obj, _content_unset_hook); | ||
519 | |||
520 | wd->widget_name = eina_stringshare_add("scroller"); | ||
521 | wd->widget_base = eina_stringshare_add("base"); | ||
522 | |||
523 | wd->scr = elm_smart_scroller_add(e); | ||
524 | elm_smart_scroller_widget_set(wd->scr, obj); | ||
525 | _theme_hook(obj); | ||
526 | elm_widget_resize_object_set(obj, wd->scr); | ||
527 | evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
528 | _changed_size_hints, obj); | ||
529 | |||
530 | edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh); | ||
531 | evas_object_size_hint_min_set(obj, minw, minh); | ||
532 | evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj); | ||
533 | |||
534 | evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); | ||
535 | evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj); | ||
536 | evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj); | ||
537 | evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj); | ||
538 | evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj); | ||
539 | |||
540 | evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj); | ||
541 | evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj); | ||
542 | evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj); | ||
543 | evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj); | ||
544 | evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj); | ||
545 | evas_object_smart_callback_add(wd->scr, "animate,start", _scroll_anim_start, obj); | ||
546 | evas_object_smart_callback_add(wd->scr, "animate,stop", _scroll_anim_stop, obj); | ||
547 | evas_object_smart_callback_add(wd->scr, "drag,start", _scroll_drag_start, obj); | ||
548 | evas_object_smart_callback_add(wd->scr, "drag,stop", _scroll_drag_stop, obj); | ||
549 | |||
550 | _sizing_eval(obj); | ||
551 | |||
552 | // TODO: convert Elementary to subclassing of Evas_Smart_Class | ||
553 | // TODO: and save some bytes, making descriptions per-class and not instance! | ||
554 | evas_object_smart_callbacks_descriptions_set(obj, _signals); | ||
555 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
556 | return obj; | ||
557 | } | ||
558 | |||
559 | EAPI void | ||
560 | elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base) | ||
561 | { | ||
562 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
563 | Widget_Data *wd = elm_widget_data_get(obj); | ||
564 | if (!wd) return; | ||
565 | EINA_SAFETY_ON_NULL_RETURN(widget); | ||
566 | EINA_SAFETY_ON_NULL_RETURN(base); | ||
567 | if (eina_stringshare_replace(&wd->widget_name, widget) | | ||
568 | eina_stringshare_replace(&wd->widget_base, base)) | ||
569 | _theme_hook(obj); | ||
570 | } | ||
571 | |||
572 | EAPI void | ||
573 | elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h) | ||
574 | { | ||
575 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
576 | Widget_Data *wd = elm_widget_data_get(obj); | ||
577 | if (!wd) return; | ||
578 | wd->min_w = w; | ||
579 | wd->min_h = h; | ||
580 | _sizing_eval(obj); | ||
581 | } | ||
582 | |||
583 | EAPI void | ||
584 | elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) | ||
585 | { | ||
586 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
587 | Widget_Data *wd = elm_widget_data_get(obj); | ||
588 | if ((!wd) || (!wd->scr)) return; | ||
589 | elm_smart_scroller_child_region_show(wd->scr, x, y, w, h); | ||
590 | } | ||
591 | |||
592 | EAPI void | ||
593 | elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v) | ||
594 | { | ||
595 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
596 | Widget_Data *wd = elm_widget_data_get(obj); | ||
597 | if ((!wd) || (!wd->scr)) return; | ||
598 | if ((policy_h >= ELM_SCROLLER_POLICY_LAST) || | ||
599 | (policy_v >= ELM_SCROLLER_POLICY_LAST)) | ||
600 | return; | ||
601 | elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v); | ||
602 | } | ||
603 | |||
604 | EAPI void | ||
605 | elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v) | ||
606 | { | ||
607 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
608 | Widget_Data *wd = elm_widget_data_get(obj); | ||
609 | if ((!wd) || (!wd->scr)) return; | ||
610 | elm_smart_scroller_policy_get(wd->scr, | ||
611 | (Elm_Smart_Scroller_Policy *) policy_h, | ||
612 | (Elm_Smart_Scroller_Policy *) policy_v); | ||
613 | } | ||
614 | |||
615 | EAPI void | ||
616 | elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h) | ||
617 | { | ||
618 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
619 | Widget_Data *wd = elm_widget_data_get(obj); | ||
620 | if ((!wd) || (!wd->scr)) return; | ||
621 | if ((x) || (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y); | ||
622 | if ((w) || (h)) elm_smart_scroller_child_viewport_size_get(wd->scr, w, h); | ||
623 | } | ||
624 | |||
625 | EAPI void | ||
626 | elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h) | ||
627 | { | ||
628 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
629 | Widget_Data *wd = elm_widget_data_get(obj); | ||
630 | if (!wd) return; | ||
631 | evas_object_geometry_get(wd->content, NULL, NULL, w, h); | ||
632 | } | ||
633 | |||
634 | EAPI void | ||
635 | elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce) | ||
636 | { | ||
637 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
638 | Widget_Data *wd = elm_widget_data_get(obj); | ||
639 | if ((!wd) || (!wd->scr)) return; | ||
640 | elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce); | ||
641 | } | ||
642 | |||
643 | EAPI void | ||
644 | elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce) | ||
645 | { | ||
646 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
647 | Widget_Data *wd = elm_widget_data_get(obj); | ||
648 | if (!wd) return; | ||
649 | elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce); | ||
650 | } | ||
651 | |||
652 | EAPI void | ||
653 | elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel) | ||
654 | { | ||
655 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
656 | Widget_Data *wd = elm_widget_data_get(obj); | ||
657 | if (!wd) return; | ||
658 | wd->pagerel_h = h_pagerel; | ||
659 | wd->pagerel_v = v_pagerel; | ||
660 | if (wd->scr) | ||
661 | elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v, | ||
662 | wd->pagesize_h, wd->pagesize_v); | ||
663 | } | ||
664 | |||
665 | EAPI void | ||
666 | elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize) | ||
667 | { | ||
668 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
669 | Widget_Data *wd = elm_widget_data_get(obj); | ||
670 | if (!wd) return; | ||
671 | wd->pagesize_h = h_pagesize; | ||
672 | wd->pagesize_v = v_pagesize; | ||
673 | if (wd->scr) | ||
674 | elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v, | ||
675 | wd->pagesize_h, wd->pagesize_v); | ||
676 | } | ||
677 | |||
678 | EAPI void | ||
679 | elm_scroller_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber) | ||
680 | { | ||
681 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
682 | Widget_Data *wd = elm_widget_data_get(obj); | ||
683 | if (!wd) return; | ||
684 | if (wd->scr) | ||
685 | elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber); | ||
686 | } | ||
687 | |||
688 | EAPI void | ||
689 | elm_scroller_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber) | ||
690 | { | ||
691 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
692 | Widget_Data *wd = elm_widget_data_get(obj); | ||
693 | if (!wd) return; | ||
694 | if (wd->scr) | ||
695 | elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber); | ||
696 | } | ||
697 | |||
698 | EAPI void | ||
699 | elm_scroller_page_show(Evas_Object *obj, int h_pagenumber, int v_pagenumber) | ||
700 | { | ||
701 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
702 | Widget_Data *wd = elm_widget_data_get(obj); | ||
703 | if (!wd) return; | ||
704 | if (wd->scr) | ||
705 | elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber); | ||
706 | } | ||
707 | |||
708 | EAPI void | ||
709 | elm_scroller_page_bring_in(Evas_Object *obj, int h_pagenumber, int v_pagenumber) | ||
710 | { | ||
711 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
712 | Widget_Data *wd = elm_widget_data_get(obj); | ||
713 | if (!wd) return; | ||
714 | if (wd->scr) | ||
715 | elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber); | ||
716 | } | ||
717 | |||
718 | EAPI void | ||
719 | elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h) | ||
720 | { | ||
721 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
722 | Widget_Data *wd = elm_widget_data_get(obj); | ||
723 | if ((!wd) || (!wd->scr)) return; | ||
724 | elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h); | ||
725 | } | ||
726 | |||
727 | EAPI void | ||
728 | elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation) | ||
729 | { | ||
730 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
731 | Widget_Data *wd = elm_widget_data_get(obj); | ||
732 | if (!wd) return; | ||
733 | |||
734 | evas_object_propagate_events_set(wd->scr, propagation); | ||
735 | } | ||
736 | |||
737 | EAPI Eina_Bool | ||
738 | elm_scroller_propagate_events_get(const Evas_Object *obj) | ||
739 | { | ||
740 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
741 | Widget_Data *wd = elm_widget_data_get(obj); | ||
742 | if (!wd) return EINA_FALSE; | ||
743 | |||
744 | return evas_object_propagate_events_get(wd->scr); | ||
745 | } | ||
746 | |||
747 | EAPI void | ||
748 | elm_scroller_gravity_set(Evas_Object *obj, double x, double y) | ||
749 | { | ||
750 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
751 | Widget_Data *wd = elm_widget_data_get(obj); | ||
752 | if (!wd) return; | ||
753 | |||
754 | elm_smart_scroller_gravity_set(wd->scr, x, y); | ||
755 | } | ||
756 | |||
757 | EAPI void | ||
758 | elm_scroller_gravity_get(const Evas_Object *obj, double *x, double *y) | ||
759 | { | ||
760 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
761 | Widget_Data *wd = elm_widget_data_get(obj); | ||
762 | if (!wd) return; | ||
763 | |||
764 | elm_smart_scroller_gravity_get(wd->scr, x, y); | ||
765 | } | ||