diff options
Diffstat (limited to '')
-rw-r--r-- | libraries/elementary/src/lib/elm_layout.c | 967 |
1 files changed, 967 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_layout.c b/libraries/elementary/src/lib/elm_layout.c new file mode 100644 index 0000000..6f14484 --- /dev/null +++ b/libraries/elementary/src/lib/elm_layout.c | |||
@@ -0,0 +1,967 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | |||
4 | typedef struct _Widget_Data Widget_Data; | ||
5 | typedef struct _Subinfo Subinfo; | ||
6 | typedef struct _Part_Cursor Part_Cursor; | ||
7 | |||
8 | struct _Widget_Data | ||
9 | { | ||
10 | Evas_Object *obj; | ||
11 | Evas_Object *lay; | ||
12 | Eina_List *subs; | ||
13 | Eina_List *parts_cursors; | ||
14 | Eina_Bool needs_size_calc:1; | ||
15 | const char *clas, *group, *style; | ||
16 | }; | ||
17 | |||
18 | struct _Subinfo | ||
19 | { | ||
20 | const char *part; | ||
21 | Evas_Object *obj; | ||
22 | enum | ||
23 | { | ||
24 | SWALLOW, | ||
25 | BOX_APPEND, | ||
26 | BOX_PREPEND, | ||
27 | BOX_INSERT_BEFORE, | ||
28 | BOX_INSERT_AT, | ||
29 | TABLE_PACK, | ||
30 | TEXT | ||
31 | } type; | ||
32 | union | ||
33 | { | ||
34 | union | ||
35 | { | ||
36 | const Evas_Object *reference; | ||
37 | unsigned int pos; | ||
38 | } box; | ||
39 | struct | ||
40 | { | ||
41 | unsigned short col, row, colspan, rowspan; | ||
42 | } table; | ||
43 | struct | ||
44 | { | ||
45 | const char *text; | ||
46 | } text; | ||
47 | } p; | ||
48 | }; | ||
49 | |||
50 | struct _Part_Cursor | ||
51 | { | ||
52 | Evas_Object *obj; | ||
53 | const char *part; | ||
54 | const char *cursor; | ||
55 | const char *style; | ||
56 | Eina_Bool engine_only:1; | ||
57 | }; | ||
58 | |||
59 | static const char *widtype = NULL; | ||
60 | static void _del_hook(Evas_Object *obj); | ||
61 | static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl); | ||
62 | static void _theme_hook(Evas_Object *obj); | ||
63 | static void _sizing_eval(Widget_Data *wd); | ||
64 | static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info); | ||
65 | static void _sub_del(void *data, Evas_Object *obj, void *event_info); | ||
66 | static void _part_cursor_free(Part_Cursor *pc); | ||
67 | |||
68 | static const char SIG_THEME_CHANGED[] = "theme,changed"; | ||
69 | |||
70 | static const Evas_Smart_Cb_Description _signals[] = { | ||
71 | {SIG_THEME_CHANGED, ""}, | ||
72 | {NULL, NULL} | ||
73 | }; | ||
74 | |||
75 | static void | ||
76 | _del_hook(Evas_Object *obj) | ||
77 | { | ||
78 | Widget_Data *wd = elm_widget_data_get(obj); | ||
79 | Subinfo *si; | ||
80 | Part_Cursor *pc; | ||
81 | |||
82 | if (!wd) return; | ||
83 | EINA_LIST_FREE(wd->subs, si) | ||
84 | { | ||
85 | eina_stringshare_del(si->part); | ||
86 | if (si->type == TEXT) | ||
87 | eina_stringshare_del(si->p.text.text); | ||
88 | free(si); | ||
89 | } | ||
90 | EINA_LIST_FREE(wd->parts_cursors, pc) _part_cursor_free(pc); | ||
91 | free(wd); | ||
92 | } | ||
93 | |||
94 | static void | ||
95 | _mirrored_set(Evas_Object *obj, Eina_Bool rtl) | ||
96 | { | ||
97 | Widget_Data *wd = elm_widget_data_get(obj); | ||
98 | if (!wd) return; | ||
99 | edje_object_mirrored_set(wd->lay, rtl); | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | _theme_hook(Evas_Object *obj) | ||
104 | { | ||
105 | Widget_Data *wd = elm_widget_data_get(obj); | ||
106 | if (!wd) return; | ||
107 | _elm_widget_mirrored_reload(obj); | ||
108 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
109 | _elm_theme_object_set(obj, wd->lay, wd->clas, wd->group, wd->style); | ||
110 | edje_object_scale_set(wd->lay, elm_widget_scale_get(obj) * | ||
111 | _elm_config->scale); | ||
112 | evas_object_smart_callback_call(obj, SIG_THEME_CHANGED, NULL); | ||
113 | _sizing_eval(wd); | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | _changed_hook(Evas_Object *obj) | ||
118 | { | ||
119 | Widget_Data *wd = elm_widget_data_get(obj); | ||
120 | if (!wd) return; | ||
121 | if (wd->needs_size_calc) | ||
122 | { | ||
123 | _sizing_eval(wd); | ||
124 | wd->needs_size_calc = 0; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | static void | ||
129 | _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source) | ||
130 | { | ||
131 | Widget_Data *wd = elm_widget_data_get(obj); | ||
132 | edje_object_signal_emit(wd->lay, emission, source); | ||
133 | } | ||
134 | |||
135 | static void | ||
136 | _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
137 | { | ||
138 | Widget_Data *wd = elm_widget_data_get(obj); | ||
139 | edje_object_signal_callback_add(wd->lay, emission, source, func_cb, data); | ||
140 | } | ||
141 | |||
142 | static void | ||
143 | _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data) | ||
144 | { | ||
145 | Widget_Data *wd = elm_widget_data_get(obj); | ||
146 | edje_object_signal_callback_del_full(wd->lay, emission, source, func_cb, | ||
147 | data); | ||
148 | } | ||
149 | |||
150 | |||
151 | static void * | ||
152 | _elm_layout_list_data_get(const Eina_List *list) | ||
153 | { | ||
154 | Subinfo *si = eina_list_data_get(list); | ||
155 | return si->obj; | ||
156 | } | ||
157 | |||
158 | static Eina_Bool | ||
159 | _elm_layout_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) | ||
160 | { | ||
161 | Widget_Data *wd = elm_widget_data_get(obj); | ||
162 | const Eina_List *items; | ||
163 | void *(*list_data_get) (const Eina_List *list); | ||
164 | |||
165 | if ((!wd) || (!wd->subs)) | ||
166 | return EINA_FALSE; | ||
167 | |||
168 | /* Focus chain (This block is diferent of elm_win cycle)*/ | ||
169 | if ((items = elm_widget_focus_custom_chain_get(obj))) | ||
170 | list_data_get = eina_list_data_get; | ||
171 | else | ||
172 | { | ||
173 | items = wd->subs; | ||
174 | list_data_get = _elm_layout_list_data_get; | ||
175 | |||
176 | if (!items) return EINA_FALSE; | ||
177 | } | ||
178 | |||
179 | return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, | ||
180 | next); | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | _sizing_eval(Widget_Data *wd) | ||
185 | { | ||
186 | Evas_Coord minw = -1, minh = -1; | ||
187 | edje_object_size_min_calc(wd->lay, &minw, &minh); | ||
188 | evas_object_size_hint_min_set(wd->obj, minw, minh); | ||
189 | evas_object_size_hint_max_set(wd->obj, -1, -1); | ||
190 | } | ||
191 | |||
192 | static void | ||
193 | _request_sizing_eval(Widget_Data *wd) | ||
194 | { | ||
195 | if (wd->needs_size_calc) return; | ||
196 | wd->needs_size_calc = 1; | ||
197 | evas_object_smart_changed(wd->obj); | ||
198 | } | ||
199 | |||
200 | static void | ||
201 | _part_cursor_free(Part_Cursor *pc) | ||
202 | { | ||
203 | eina_stringshare_del(pc->part); | ||
204 | eina_stringshare_del(pc->style); | ||
205 | eina_stringshare_del(pc->cursor); | ||
206 | free(pc); | ||
207 | } | ||
208 | |||
209 | static void | ||
210 | _part_cursor_part_apply(const Part_Cursor *pc) | ||
211 | { | ||
212 | elm_object_cursor_set(pc->obj, pc->cursor); | ||
213 | elm_object_cursor_style_set(pc->obj, pc->style); | ||
214 | elm_object_cursor_theme_search_enabled_set(pc->obj, pc->engine_only); | ||
215 | } | ||
216 | |||
217 | static Part_Cursor * | ||
218 | _parts_cursors_find(Widget_Data *wd, const char *part) | ||
219 | { | ||
220 | const Eina_List *l; | ||
221 | Part_Cursor *pc; | ||
222 | EINA_LIST_FOREACH(wd->parts_cursors, l, pc) | ||
223 | { | ||
224 | if (!strcmp(pc->part, part)) | ||
225 | return pc; | ||
226 | } | ||
227 | return NULL; | ||
228 | } | ||
229 | |||
230 | static void | ||
231 | _parts_cursors_apply(Widget_Data *wd) | ||
232 | { | ||
233 | const char *file, *group; | ||
234 | const Eina_List *l; | ||
235 | Part_Cursor *pc; | ||
236 | |||
237 | edje_object_file_get(wd->lay, &file, &group); | ||
238 | |||
239 | EINA_LIST_FOREACH(wd->parts_cursors, l, pc) | ||
240 | { | ||
241 | Evas_Object *obj = (Evas_Object *)edje_object_part_object_get | ||
242 | (wd->lay, pc->part); | ||
243 | |||
244 | if (!obj) | ||
245 | { | ||
246 | pc->obj = NULL; | ||
247 | WRN("no part '%s' in group '%s' of file '%s'. " | ||
248 | "Cannot set cursor '%s'", | ||
249 | pc->part, group, file, pc->cursor); | ||
250 | continue; | ||
251 | } | ||
252 | else if (evas_object_pass_events_get(obj)) | ||
253 | { | ||
254 | pc->obj = NULL; | ||
255 | WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. " | ||
256 | "Cannot set cursor '%s'", | ||
257 | pc->part, group, file, pc->cursor); | ||
258 | continue; | ||
259 | } | ||
260 | |||
261 | pc->obj = obj; | ||
262 | _part_cursor_part_apply(pc); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static void | ||
267 | _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
268 | { | ||
269 | _request_sizing_eval(data); | ||
270 | } | ||
271 | |||
272 | static void | ||
273 | _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info) | ||
274 | { | ||
275 | Widget_Data *wd = elm_widget_data_get(obj); | ||
276 | Evas_Object *sub = event_info; | ||
277 | Eina_List *l; | ||
278 | Subinfo *si; | ||
279 | if (!wd) return; | ||
280 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
281 | { | ||
282 | if (si->obj == sub) | ||
283 | { | ||
284 | evas_object_event_callback_del_full(sub, | ||
285 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
286 | _changed_size_hints, | ||
287 | wd); | ||
288 | wd->subs = eina_list_remove_list(wd->subs, l); | ||
289 | eina_stringshare_del(si->part); | ||
290 | free(si); | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | static void | ||
297 | _signal_size_eval(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__) | ||
298 | { | ||
299 | _request_sizing_eval(data); | ||
300 | } | ||
301 | |||
302 | static void | ||
303 | _parts_text_fix(Widget_Data *wd) | ||
304 | { | ||
305 | const Eina_List *l; | ||
306 | Subinfo *si; | ||
307 | |||
308 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
309 | { | ||
310 | if (si->type == TEXT) | ||
311 | edje_object_part_text_escaped_set(wd->lay, si->part, si->p.text.text); | ||
312 | } | ||
313 | } | ||
314 | |||
315 | static void | ||
316 | _elm_layout_label_set(Evas_Object *obj, const char *part, const char *text) | ||
317 | { | ||
318 | Widget_Data *wd = elm_widget_data_get(obj); | ||
319 | Subinfo *si = NULL; | ||
320 | Eina_List *l; | ||
321 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
322 | if (!part) part = "elm.text"; | ||
323 | |||
324 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
325 | { | ||
326 | if ((si->type == TEXT) && (!strcmp(part, si->part))) | ||
327 | { | ||
328 | if (!text) | ||
329 | { | ||
330 | eina_stringshare_del(si->part); | ||
331 | eina_stringshare_del(si->p.text.text); | ||
332 | free(si); | ||
333 | edje_object_part_text_escaped_set(wd->lay, part, NULL); | ||
334 | wd->subs = eina_list_remove_list(wd->subs, l); | ||
335 | return; | ||
336 | } | ||
337 | else | ||
338 | break; | ||
339 | } | ||
340 | si = NULL; | ||
341 | } | ||
342 | |||
343 | if (!si) | ||
344 | { | ||
345 | si = ELM_NEW(Subinfo); | ||
346 | if (!si) return; | ||
347 | si->type = TEXT; | ||
348 | si->part = eina_stringshare_add(part); | ||
349 | wd->subs = eina_list_append(wd->subs, si); | ||
350 | } | ||
351 | |||
352 | eina_stringshare_replace(&si->p.text.text, text); | ||
353 | edje_object_part_text_escaped_set(wd->lay, part, text); | ||
354 | _request_sizing_eval(wd); | ||
355 | } | ||
356 | |||
357 | static const char * | ||
358 | _elm_layout_label_get(const Evas_Object *obj, const char *part) | ||
359 | { | ||
360 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
361 | Widget_Data *wd = elm_widget_data_get(obj); | ||
362 | if (!part) part = "elm.text"; | ||
363 | return edje_object_part_text_get(wd->lay, part); | ||
364 | } | ||
365 | |||
366 | static void | ||
367 | _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) | ||
368 | { | ||
369 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
370 | Widget_Data *wd = elm_widget_data_get(obj); | ||
371 | Subinfo *si; | ||
372 | const Eina_List *l; | ||
373 | if (!wd) return; | ||
374 | EINA_SAFETY_ON_NULL_RETURN(part); | ||
375 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
376 | { | ||
377 | if ((si->type == SWALLOW) && (!strcmp(part, si->part))) | ||
378 | { | ||
379 | if (content == si->obj) return; | ||
380 | evas_object_del(si->obj); | ||
381 | break; | ||
382 | } | ||
383 | } | ||
384 | if (content) | ||
385 | { | ||
386 | elm_widget_sub_object_add(obj, content); | ||
387 | evas_object_event_callback_add(content, | ||
388 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
389 | _changed_size_hints, wd); | ||
390 | if (!edje_object_part_swallow(wd->lay, part, content)) | ||
391 | WRN("could not swallow %p into part '%s'", content, part); | ||
392 | si = ELM_NEW(Subinfo); | ||
393 | si->type = SWALLOW; | ||
394 | si->part = eina_stringshare_add(part); | ||
395 | si->obj = content; | ||
396 | wd->subs = eina_list_append(wd->subs, si); | ||
397 | } | ||
398 | _request_sizing_eval(wd); | ||
399 | } | ||
400 | |||
401 | static Evas_Object * | ||
402 | _content_get_hook(const Evas_Object *obj, const char *part) | ||
403 | { | ||
404 | Widget_Data *wd = elm_widget_data_get(obj); | ||
405 | const Eina_List *l; | ||
406 | Subinfo *si; | ||
407 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
408 | |||
409 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
410 | { | ||
411 | if ((si->type == SWALLOW) && !strcmp(part, si->part)) | ||
412 | return si->obj; | ||
413 | } | ||
414 | return NULL; | ||
415 | } | ||
416 | |||
417 | static Evas_Object * | ||
418 | _content_unset_hook(Evas_Object *obj, const char *part) | ||
419 | { | ||
420 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
421 | Widget_Data *wd = elm_widget_data_get(obj); | ||
422 | Subinfo *si; | ||
423 | const Eina_List *l; | ||
424 | if (!wd) return NULL; | ||
425 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
426 | { | ||
427 | if ((si->type == SWALLOW) && (!strcmp(part, si->part))) | ||
428 | { | ||
429 | Evas_Object *content; | ||
430 | if (!si->obj) return NULL; | ||
431 | content = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */ | ||
432 | elm_widget_sub_object_del(obj, content); | ||
433 | evas_object_event_callback_del_full(content, | ||
434 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
435 | _changed_size_hints, wd); | ||
436 | edje_object_part_unswallow(wd->lay, content); | ||
437 | return content; | ||
438 | } | ||
439 | } | ||
440 | return NULL; | ||
441 | } | ||
442 | |||
443 | EAPI Evas_Object * | ||
444 | elm_layout_add(Evas_Object *parent) | ||
445 | { | ||
446 | Evas_Object *obj; | ||
447 | Evas *e; | ||
448 | Widget_Data *wd; | ||
449 | |||
450 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
451 | |||
452 | ELM_SET_WIDTYPE(widtype, "layout"); | ||
453 | elm_widget_type_set(obj, "layout"); | ||
454 | elm_widget_sub_object_add(parent, obj); | ||
455 | elm_widget_data_set(obj, wd); | ||
456 | elm_widget_del_hook_set(obj, _del_hook); | ||
457 | elm_widget_theme_hook_set(obj, _theme_hook); | ||
458 | elm_widget_changed_hook_set(obj, _changed_hook); | ||
459 | elm_widget_can_focus_set(obj, EINA_FALSE); | ||
460 | elm_widget_focus_next_hook_set(obj, _elm_layout_focus_next_hook); | ||
461 | elm_widget_signal_emit_hook_set(obj, _signal_emit_hook); | ||
462 | elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook); | ||
463 | elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook); | ||
464 | elm_widget_text_set_hook_set(obj, _elm_layout_label_set); | ||
465 | elm_widget_text_get_hook_set(obj, _elm_layout_label_get); | ||
466 | elm_widget_content_set_hook_set(obj, _content_set_hook); | ||
467 | elm_widget_content_get_hook_set(obj, _content_get_hook); | ||
468 | elm_widget_content_unset_hook_set(obj, _content_unset_hook); | ||
469 | |||
470 | wd->obj = obj; | ||
471 | wd->lay = edje_object_add(e); | ||
472 | elm_widget_resize_object_set(obj, wd->lay); | ||
473 | edje_object_signal_callback_add(wd->lay, "size,eval", "elm", | ||
474 | _signal_size_eval, wd); | ||
475 | |||
476 | evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj); | ||
477 | evas_object_smart_callbacks_descriptions_set(obj, _signals); | ||
478 | |||
479 | _mirrored_set(obj, elm_widget_mirrored_get(obj)); | ||
480 | _request_sizing_eval(wd); | ||
481 | return obj; | ||
482 | } | ||
483 | |||
484 | EAPI Eina_Bool | ||
485 | elm_layout_file_set(Evas_Object *obj, const char *file, const char *group) | ||
486 | { | ||
487 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
488 | Widget_Data *wd = elm_widget_data_get(obj); | ||
489 | if (!wd) return EINA_FALSE; | ||
490 | Eina_Bool ret = edje_object_file_set(wd->lay, file, group); | ||
491 | if (ret) | ||
492 | { | ||
493 | _parts_text_fix(wd); | ||
494 | _request_sizing_eval(wd); | ||
495 | _parts_cursors_apply(wd); | ||
496 | } | ||
497 | else DBG("failed to set edje file '%s', group '%s': %s", | ||
498 | file, group, | ||
499 | edje_load_error_str(edje_object_load_error_get(wd->lay))); | ||
500 | return ret; | ||
501 | } | ||
502 | |||
503 | EAPI Eina_Bool | ||
504 | elm_layout_theme_set(Evas_Object *obj, const char *clas, const char *group, const char *style) | ||
505 | { | ||
506 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
507 | Widget_Data *wd = elm_widget_data_get(obj); | ||
508 | if (!wd) return EINA_FALSE; | ||
509 | Eina_Bool ret = _elm_theme_object_set(obj, wd->lay, clas, group, style); | ||
510 | wd->clas = clas; | ||
511 | wd->group = group; | ||
512 | wd->style = style; | ||
513 | if (ret) | ||
514 | { | ||
515 | _parts_text_fix(wd); | ||
516 | _request_sizing_eval(wd); | ||
517 | _parts_cursors_apply(wd); | ||
518 | } | ||
519 | return ret; | ||
520 | } | ||
521 | |||
522 | EAPI Eina_Bool | ||
523 | elm_layout_box_append(Evas_Object *obj, const char *part, Evas_Object *child) | ||
524 | { | ||
525 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
526 | Widget_Data *wd = elm_widget_data_get(obj); | ||
527 | Subinfo *si; | ||
528 | if (!wd) return EINA_FALSE; | ||
529 | |||
530 | if (!edje_object_part_box_append(wd->lay, part, child)) | ||
531 | WRN("child %p could not be appended to box part '%s'", child, part); | ||
532 | elm_widget_sub_object_add(obj, child); | ||
533 | evas_object_event_callback_add | ||
534 | (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd); | ||
535 | |||
536 | si = ELM_NEW(Subinfo); | ||
537 | si->type = BOX_APPEND; | ||
538 | si->part = eina_stringshare_add(part); | ||
539 | si->obj = child; | ||
540 | wd->subs = eina_list_append(wd->subs, si); | ||
541 | _request_sizing_eval(wd); | ||
542 | |||
543 | return EINA_TRUE; | ||
544 | } | ||
545 | |||
546 | EAPI Eina_Bool | ||
547 | elm_layout_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child) | ||
548 | { | ||
549 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
550 | Widget_Data *wd = elm_widget_data_get(obj); | ||
551 | Subinfo *si; | ||
552 | if (!wd) return EINA_FALSE; | ||
553 | |||
554 | if (!edje_object_part_box_prepend(wd->lay, part, child)) | ||
555 | WRN("child %p could not be prepended to box part '%s'", child, part); | ||
556 | elm_widget_sub_object_add(obj, child); | ||
557 | evas_object_event_callback_add | ||
558 | (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd); | ||
559 | |||
560 | si = ELM_NEW(Subinfo); | ||
561 | si->type = BOX_PREPEND; | ||
562 | si->part = eina_stringshare_add(part); | ||
563 | si->obj = child; | ||
564 | wd->subs = eina_list_prepend(wd->subs, si); | ||
565 | _request_sizing_eval(wd); | ||
566 | |||
567 | return EINA_TRUE; | ||
568 | } | ||
569 | |||
570 | static void | ||
571 | _box_reference_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
572 | { | ||
573 | Subinfo *si = data; | ||
574 | si->p.box.reference = NULL; | ||
575 | } | ||
576 | |||
577 | EAPI Eina_Bool | ||
578 | elm_layout_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference) | ||
579 | { | ||
580 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
581 | Widget_Data *wd = elm_widget_data_get(obj); | ||
582 | Subinfo *si; | ||
583 | if (!wd) return EINA_FALSE; | ||
584 | |||
585 | if (!edje_object_part_box_insert_before(wd->lay, part, child, reference)) | ||
586 | WRN("child %p could not be inserted before %p inf box part '%s'", | ||
587 | child, reference, part); | ||
588 | |||
589 | si = ELM_NEW(Subinfo); | ||
590 | si->type = BOX_INSERT_BEFORE; | ||
591 | si->part = eina_stringshare_add(part); | ||
592 | si->obj = child; | ||
593 | si->p.box.reference = reference; | ||
594 | |||
595 | elm_widget_sub_object_add(obj, child); | ||
596 | evas_object_event_callback_add | ||
597 | (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd); | ||
598 | evas_object_event_callback_add | ||
599 | ((Evas_Object *)reference, EVAS_CALLBACK_DEL, _box_reference_del, si); | ||
600 | |||
601 | wd->subs = eina_list_append(wd->subs, si); | ||
602 | _request_sizing_eval(wd); | ||
603 | |||
604 | return EINA_TRUE; | ||
605 | } | ||
606 | |||
607 | EAPI Eina_Bool | ||
608 | elm_layout_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos) | ||
609 | { | ||
610 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
611 | Widget_Data *wd = elm_widget_data_get(obj); | ||
612 | Subinfo *si; | ||
613 | if (!wd) return EINA_FALSE; | ||
614 | |||
615 | if (!edje_object_part_box_insert_at(wd->lay, part, child, pos)) | ||
616 | WRN("child %p could not be inserted at %u to box part '%s'", | ||
617 | child, pos, part); | ||
618 | |||
619 | elm_widget_sub_object_add(obj, child); | ||
620 | evas_object_event_callback_add | ||
621 | (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd); | ||
622 | |||
623 | si = ELM_NEW(Subinfo); | ||
624 | si->type = BOX_INSERT_AT; | ||
625 | si->part = eina_stringshare_add(part); | ||
626 | si->obj = child; | ||
627 | si->p.box.pos = pos; | ||
628 | wd->subs = eina_list_append(wd->subs, si); | ||
629 | _request_sizing_eval(wd); | ||
630 | |||
631 | return EINA_TRUE; | ||
632 | } | ||
633 | |||
634 | static Evas_Object * | ||
635 | _sub_box_remove(Widget_Data *wd, Subinfo *si) | ||
636 | { | ||
637 | Evas_Object *child; | ||
638 | |||
639 | if (si->type == BOX_INSERT_BEFORE) | ||
640 | evas_object_event_callback_del_full | ||
641 | ((Evas_Object *)si->p.box.reference, | ||
642 | EVAS_CALLBACK_DEL, _box_reference_del, si); | ||
643 | |||
644 | child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */ | ||
645 | edje_object_part_box_remove(wd->lay, si->part, child); | ||
646 | elm_widget_sub_object_del(wd->obj, child); | ||
647 | return child; | ||
648 | } | ||
649 | |||
650 | static Evas_Object * | ||
651 | _sub_table_remove(Widget_Data *wd, Subinfo *si) | ||
652 | { | ||
653 | Evas_Object *child; | ||
654 | |||
655 | child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */ | ||
656 | edje_object_part_table_unpack(wd->lay, si->part, child); | ||
657 | elm_widget_sub_object_del(wd->obj, child); | ||
658 | return child; | ||
659 | } | ||
660 | |||
661 | static Eina_Bool | ||
662 | _sub_box_is(const Subinfo *si) | ||
663 | { | ||
664 | switch (si->type) | ||
665 | { | ||
666 | case BOX_APPEND: | ||
667 | case BOX_PREPEND: | ||
668 | case BOX_INSERT_BEFORE: | ||
669 | case BOX_INSERT_AT: | ||
670 | return EINA_TRUE; | ||
671 | default: | ||
672 | return EINA_FALSE; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | EAPI Evas_Object * | ||
677 | elm_layout_box_remove(Evas_Object *obj, const char *part, Evas_Object *child) | ||
678 | { | ||
679 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
680 | Widget_Data *wd = elm_widget_data_get(obj); | ||
681 | const Eina_List *l; | ||
682 | Subinfo *si; | ||
683 | |||
684 | if (!wd) return NULL; | ||
685 | |||
686 | EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); | ||
687 | EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL); | ||
688 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
689 | { | ||
690 | if (!_sub_box_is(si)) continue; | ||
691 | if ((si->obj == child) && (!strcmp(si->part, part))) | ||
692 | return _sub_box_remove(wd, si); | ||
693 | } | ||
694 | return NULL; | ||
695 | } | ||
696 | |||
697 | EAPI Eina_Bool | ||
698 | elm_layout_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear) | ||
699 | { | ||
700 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
701 | Widget_Data *wd = elm_widget_data_get(obj); | ||
702 | Subinfo *si; | ||
703 | Eina_List *lst; | ||
704 | |||
705 | if (!wd) return EINA_FALSE; | ||
706 | EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE); | ||
707 | |||
708 | lst = eina_list_clone(wd->subs); | ||
709 | EINA_LIST_FREE(lst, si) | ||
710 | { | ||
711 | if (!_sub_box_is(si)) continue; | ||
712 | if (!strcmp(si->part, part)) | ||
713 | { | ||
714 | Evas_Object *child = _sub_box_remove(wd, si); | ||
715 | if ((clear) && (child)) evas_object_del(child); | ||
716 | } | ||
717 | } | ||
718 | /* eventually something may not be added with layout, del them as well */ | ||
719 | edje_object_part_box_remove_all(wd->lay, part, clear); | ||
720 | |||
721 | return EINA_TRUE; | ||
722 | } | ||
723 | |||
724 | EAPI Eina_Bool | ||
725 | elm_layout_table_pack(Evas_Object *obj, const char *part, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan) | ||
726 | { | ||
727 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
728 | Widget_Data *wd = elm_widget_data_get(obj); | ||
729 | Subinfo *si; | ||
730 | if (!wd) return EINA_FALSE; | ||
731 | |||
732 | if (!edje_object_part_table_pack | ||
733 | (wd->lay, part, child, col, row, colspan, rowspan)) | ||
734 | WRN("child %p could not be packed into box part '%s' col=%uh, row=%hu, " | ||
735 | "colspan=%hu, rowspan=%hu", child, part, col, row, colspan, rowspan); | ||
736 | |||
737 | elm_widget_sub_object_add(obj, child); | ||
738 | evas_object_event_callback_add | ||
739 | (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd); | ||
740 | |||
741 | si = ELM_NEW(Subinfo); | ||
742 | si->type = TABLE_PACK; | ||
743 | si->part = eina_stringshare_add(part); | ||
744 | si->obj = child; | ||
745 | si->p.table.col = col; | ||
746 | si->p.table.row = row; | ||
747 | si->p.table.colspan = colspan; | ||
748 | si->p.table.rowspan = rowspan; | ||
749 | wd->subs = eina_list_append(wd->subs, si); | ||
750 | _request_sizing_eval(wd); | ||
751 | |||
752 | return EINA_TRUE; | ||
753 | } | ||
754 | |||
755 | EAPI Evas_Object * | ||
756 | elm_layout_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child) | ||
757 | { | ||
758 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
759 | Widget_Data *wd = elm_widget_data_get(obj); | ||
760 | const Eina_List *l; | ||
761 | Subinfo *si; | ||
762 | |||
763 | if (!wd) return NULL; | ||
764 | |||
765 | EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL); | ||
766 | EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL); | ||
767 | EINA_LIST_FOREACH(wd->subs, l, si) | ||
768 | { | ||
769 | if (si->type != TABLE_PACK) continue; | ||
770 | if ((si->obj == child) && (!strcmp(si->part, part))) | ||
771 | return _sub_table_remove(wd, si); | ||
772 | } | ||
773 | return NULL; | ||
774 | } | ||
775 | |||
776 | EAPI Eina_Bool | ||
777 | elm_layout_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear) | ||
778 | { | ||
779 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
780 | Widget_Data *wd = elm_widget_data_get(obj); | ||
781 | Subinfo *si; | ||
782 | Eina_List *lst; | ||
783 | |||
784 | if (!wd) return EINA_FALSE; | ||
785 | EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE); | ||
786 | |||
787 | lst = eina_list_clone(wd->subs); | ||
788 | EINA_LIST_FREE(lst, si) | ||
789 | { | ||
790 | if (si->type != TABLE_PACK) continue; | ||
791 | if (!strcmp(si->part, part)) | ||
792 | { | ||
793 | Evas_Object *child = _sub_table_remove(wd, si); | ||
794 | if ((clear) && (child)) evas_object_del(child); | ||
795 | } | ||
796 | } | ||
797 | /* eventually something may not be added with layout, del them as well */ | ||
798 | edje_object_part_table_clear(wd->lay, part, clear); | ||
799 | |||
800 | return EINA_TRUE; | ||
801 | } | ||
802 | |||
803 | EAPI Evas_Object * | ||
804 | elm_layout_edje_get(const Evas_Object *obj) | ||
805 | { | ||
806 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
807 | Widget_Data *wd = elm_widget_data_get(obj); | ||
808 | if (!wd) return NULL; | ||
809 | return wd->lay; | ||
810 | } | ||
811 | |||
812 | EAPI const char * | ||
813 | elm_layout_data_get(const Evas_Object *obj, const char *key) | ||
814 | { | ||
815 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
816 | Widget_Data *wd = elm_widget_data_get(obj); | ||
817 | return edje_object_data_get(wd->lay, key); | ||
818 | } | ||
819 | |||
820 | EAPI void | ||
821 | elm_layout_sizing_eval(Evas_Object *obj) | ||
822 | { | ||
823 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
824 | Widget_Data *wd = elm_widget_data_get(obj); | ||
825 | EINA_SAFETY_ON_NULL_RETURN(wd); | ||
826 | _request_sizing_eval(wd); | ||
827 | } | ||
828 | |||
829 | EAPI Eina_Bool | ||
830 | elm_layout_part_cursor_set(Evas_Object *obj, const char *part_name, const char *cursor) | ||
831 | { | ||
832 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
833 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE); | ||
834 | Widget_Data *wd = elm_widget_data_get(obj); | ||
835 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); | ||
836 | Evas_Object *part_obj; | ||
837 | Part_Cursor *pc; | ||
838 | |||
839 | part_obj = (Evas_Object *)edje_object_part_object_get(wd->lay, part_name); | ||
840 | if (!part_obj) | ||
841 | { | ||
842 | const char *group, *file; | ||
843 | edje_object_file_get(wd->lay, &file, &group); | ||
844 | WRN("no part '%s' in group '%s' of file '%s'. Cannot set cursor '%s'", | ||
845 | part_name, group, file, cursor); | ||
846 | return EINA_FALSE; | ||
847 | } | ||
848 | if (evas_object_pass_events_get(part_obj)) | ||
849 | { | ||
850 | const char *group, *file; | ||
851 | edje_object_file_get(wd->lay, &file, &group); | ||
852 | WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. " | ||
853 | "Cannot set cursor '%s'", | ||
854 | part_name, group, file, cursor); | ||
855 | return EINA_FALSE; | ||
856 | } | ||
857 | |||
858 | pc = _parts_cursors_find(wd, part_name); | ||
859 | if (pc) eina_stringshare_replace(&pc->cursor, cursor); | ||
860 | else | ||
861 | { | ||
862 | pc = calloc(1, sizeof(*pc)); | ||
863 | pc->part = eina_stringshare_add(part_name); | ||
864 | pc->cursor = eina_stringshare_add(cursor); | ||
865 | pc->style = eina_stringshare_add("default"); | ||
866 | wd->parts_cursors = eina_list_append(wd->parts_cursors, pc); | ||
867 | } | ||
868 | |||
869 | pc->obj = part_obj; | ||
870 | elm_object_sub_cursor_set(part_obj, obj, pc->cursor); | ||
871 | return EINA_TRUE; | ||
872 | } | ||
873 | |||
874 | EAPI const char * | ||
875 | elm_layout_part_cursor_get(const Evas_Object *obj, const char *part_name) | ||
876 | { | ||
877 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
878 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL); | ||
879 | Widget_Data *wd = elm_widget_data_get(obj); | ||
880 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); | ||
881 | Part_Cursor *pc = _parts_cursors_find(wd, part_name); | ||
882 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL); | ||
883 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL); | ||
884 | return elm_object_cursor_get(pc->obj); | ||
885 | } | ||
886 | |||
887 | EAPI Eina_Bool | ||
888 | elm_layout_part_cursor_unset(Evas_Object *obj, const char *part_name) | ||
889 | { | ||
890 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
891 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE); | ||
892 | Widget_Data *wd = elm_widget_data_get(obj); | ||
893 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); | ||
894 | Eina_List *l; | ||
895 | Part_Cursor *pc; | ||
896 | |||
897 | EINA_LIST_FOREACH(wd->parts_cursors, l, pc) | ||
898 | { | ||
899 | if (!strcmp(part_name, pc->part)) | ||
900 | { | ||
901 | if (pc->obj) elm_object_cursor_unset(pc->obj); | ||
902 | _part_cursor_free(pc); | ||
903 | wd->parts_cursors = eina_list_remove_list(wd->parts_cursors, l); | ||
904 | return EINA_TRUE; | ||
905 | } | ||
906 | } | ||
907 | |||
908 | return EINA_FALSE; | ||
909 | } | ||
910 | |||
911 | EAPI Eina_Bool | ||
912 | elm_layout_part_cursor_style_set(Evas_Object *obj, const char *part_name, const char *style) | ||
913 | { | ||
914 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
915 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE); | ||
916 | Widget_Data *wd = elm_widget_data_get(obj); | ||
917 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); | ||
918 | Part_Cursor *pc = _parts_cursors_find(wd, part_name); | ||
919 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE); | ||
920 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE); | ||
921 | |||
922 | eina_stringshare_replace(&pc->style, style); | ||
923 | elm_object_cursor_style_set(pc->obj, pc->style); | ||
924 | return EINA_TRUE; | ||
925 | } | ||
926 | |||
927 | EAPI const char * | ||
928 | elm_layout_part_cursor_style_get(const Evas_Object *obj, const char *part_name) | ||
929 | { | ||
930 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
931 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL); | ||
932 | Widget_Data *wd = elm_widget_data_get(obj); | ||
933 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL); | ||
934 | Part_Cursor *pc = _parts_cursors_find(wd, part_name); | ||
935 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL); | ||
936 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL); | ||
937 | return elm_object_cursor_style_get(pc->obj); | ||
938 | } | ||
939 | |||
940 | EAPI Eina_Bool | ||
941 | elm_layout_part_cursor_engine_only_set(Evas_Object *obj, const char *part_name, Eina_Bool engine_only) | ||
942 | { | ||
943 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
944 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE); | ||
945 | Widget_Data *wd = elm_widget_data_get(obj); | ||
946 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); | ||
947 | Part_Cursor *pc = _parts_cursors_find(wd, part_name); | ||
948 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE); | ||
949 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE); | ||
950 | |||
951 | pc->engine_only = !!engine_only; | ||
952 | elm_object_cursor_theme_search_enabled_set(pc->obj, pc->engine_only); | ||
953 | return EINA_TRUE; | ||
954 | } | ||
955 | |||
956 | EAPI Eina_Bool | ||
957 | elm_layout_part_cursor_engine_only_get(const Evas_Object *obj, const char *part_name) | ||
958 | { | ||
959 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
960 | EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE); | ||
961 | Widget_Data *wd = elm_widget_data_get(obj); | ||
962 | EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE); | ||
963 | Part_Cursor *pc = _parts_cursors_find(wd, part_name); | ||
964 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE); | ||
965 | EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE); | ||
966 | return elm_object_cursor_theme_search_enabled_get(pc->obj); | ||
967 | } | ||