diff options
Diffstat (limited to 'libraries/elementary/src/lib/elm_factory.c')
-rw-r--r-- | libraries/elementary/src/lib/elm_factory.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_factory.c b/libraries/elementary/src/lib/elm_factory.c new file mode 100644 index 0000000..25a3d37 --- /dev/null +++ b/libraries/elementary/src/lib/elm_factory.c | |||
@@ -0,0 +1,338 @@ | |||
1 | #include <Elementary.h> | ||
2 | #include "elm_priv.h" | ||
3 | |||
4 | // FIXME: handle if canvas resizes | ||
5 | |||
6 | typedef struct _Widget_Data Widget_Data; | ||
7 | |||
8 | struct _Widget_Data | ||
9 | { | ||
10 | Evas_Object *obj; | ||
11 | Evas_Object *content; | ||
12 | int last_calc_count; | ||
13 | Evas_Coord maxminw, maxminh; | ||
14 | Eina_Bool eval : 1; | ||
15 | Eina_Bool szeval : 1; | ||
16 | Eina_Bool maxmin : 1; | ||
17 | }; | ||
18 | |||
19 | static const char *widtype = NULL; | ||
20 | static void _del_hook(Evas_Object *obj); | ||
21 | static Eina_Bool _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next); | ||
22 | static void _sizing_eval(Evas_Object *obj); | ||
23 | static void _eval(Evas_Object *obj); | ||
24 | static void _changed(Evas_Object *obj); | ||
25 | static void _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__); | ||
26 | static void _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__); | ||
27 | static void _child_change(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__); | ||
28 | static void _child_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__); | ||
29 | static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content); | ||
30 | static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part); | ||
31 | static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part); | ||
32 | |||
33 | static const char SIG_REALIZE[] = "realize"; | ||
34 | static const char SIG_UNREALIZE[] = "unrealize"; | ||
35 | |||
36 | static const Evas_Smart_Cb_Description _signals[] = { | ||
37 | {SIG_REALIZE, ""}, | ||
38 | {SIG_UNREALIZE, ""}, | ||
39 | {NULL, NULL} | ||
40 | }; | ||
41 | |||
42 | static int fac = 0; | ||
43 | |||
44 | static void | ||
45 | _del_hook(Evas_Object *obj) | ||
46 | { | ||
47 | Widget_Data *wd = elm_widget_data_get(obj); | ||
48 | if (!wd) return; | ||
49 | if (wd->content) | ||
50 | { | ||
51 | Evas_Object *o = wd->content; | ||
52 | |||
53 | evas_object_event_callback_del_full(o, | ||
54 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
55 | _child_change, obj); | ||
56 | evas_object_event_callback_del_full(o, | ||
57 | EVAS_CALLBACK_DEL, | ||
58 | _child_del, obj); | ||
59 | wd->content = NULL; | ||
60 | evas_object_del(o); | ||
61 | fac--; | ||
62 | // printf("FAC-- = %i\n", fac); | ||
63 | } | ||
64 | free(wd); | ||
65 | } | ||
66 | |||
67 | static Eina_Bool | ||
68 | _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next) | ||
69 | { | ||
70 | Widget_Data *wd = elm_widget_data_get(obj); | ||
71 | Evas_Object *cur; | ||
72 | |||
73 | if ((!wd) || (!wd->content)) return EINA_FALSE; | ||
74 | cur = wd->content; | ||
75 | return elm_widget_focus_next_get(cur, dir, next); | ||
76 | } | ||
77 | |||
78 | static void | ||
79 | _sizing_eval(Evas_Object *obj) | ||
80 | { | ||
81 | Widget_Data *wd = elm_widget_data_get(obj); | ||
82 | Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1; | ||
83 | |||
84 | if (!wd) return; | ||
85 | if (!wd->content) return; | ||
86 | evas_object_size_hint_min_get(wd->content, &minw, &minh); | ||
87 | evas_object_size_hint_max_get(wd->content, &maxw, &maxh); | ||
88 | if (wd->maxmin) | ||
89 | { | ||
90 | if (minw > wd->maxminw) wd->maxminw = minw; | ||
91 | if (minh > wd->maxminh) wd->maxminh = minh; | ||
92 | evas_object_size_hint_min_set(obj, wd->maxminw, wd->maxminh); | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | evas_object_size_hint_min_set(obj, minw, minh); | ||
97 | } | ||
98 | evas_object_size_hint_max_set(obj, maxw, maxh); | ||
99 | // printf("FAC SZ: %i %i | %i %i\n", minw, minh, maxw, maxh); | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | _eval(Evas_Object *obj) | ||
104 | { | ||
105 | Evas_Coord x, y, w, h, cvx, cvy, cvw, cvh; | ||
106 | Widget_Data *wd = elm_widget_data_get(obj); | ||
107 | if (!wd) return; | ||
108 | |||
109 | evas_event_freeze(evas_object_evas_get(obj)); | ||
110 | evas_object_geometry_get(obj, &x, &y, &w, &h); | ||
111 | if (w < 1) w = 1; | ||
112 | if (h < 1) h = 1; | ||
113 | evas_output_viewport_get(evas_object_evas_get(obj), | ||
114 | &cvx, &cvy, &cvw, &cvh); | ||
115 | if ((cvw < 1) || (cvh < 1)) return; | ||
116 | // need some fuzz value thats beyond the current viewport | ||
117 | // for now just make it the viewport * 3 in size (so 1 vp in each direction) | ||
118 | /* | ||
119 | cvx -= cvw; | ||
120 | cvy -= cvh; | ||
121 | cvw *= 3; | ||
122 | cvh *= 3; | ||
123 | */ | ||
124 | if (ELM_RECTS_INTERSECT(x, y, w, h, cvx, cvy, cvw, cvh)) | ||
125 | { | ||
126 | if (!wd->content) | ||
127 | { | ||
128 | // printf(" + %i %i %ix%i <> %i %i %ix%i\n", x, y, w, h, cvx, cvy, cvw, cvh); | ||
129 | evas_object_smart_callback_call(obj, SIG_REALIZE, NULL); | ||
130 | if (wd->content) | ||
131 | { | ||
132 | if (evas_object_smart_data_get(wd->content)) | ||
133 | evas_object_smart_calculate(wd->content); | ||
134 | } | ||
135 | wd->last_calc_count = | ||
136 | evas_smart_objects_calculate_count_get(evas_object_evas_get(obj)); | ||
137 | } | ||
138 | } | ||
139 | else | ||
140 | { | ||
141 | if (wd->content) | ||
142 | { | ||
143 | if (wd->last_calc_count != | ||
144 | evas_smart_objects_calculate_count_get(evas_object_evas_get(obj))) | ||
145 | evas_object_smart_callback_call(obj, SIG_UNREALIZE, NULL); | ||
146 | } | ||
147 | } | ||
148 | evas_event_thaw(evas_object_evas_get(obj)); | ||
149 | evas_event_thaw_eval(evas_object_evas_get(obj)); | ||
150 | } | ||
151 | |||
152 | static void | ||
153 | _changed(Evas_Object *obj) | ||
154 | { | ||
155 | Widget_Data *wd = elm_widget_data_get(obj); | ||
156 | if (!wd) return; | ||
157 | if (wd->eval) | ||
158 | { | ||
159 | _eval(obj); | ||
160 | wd->eval = EINA_FALSE; | ||
161 | } | ||
162 | if (wd->szeval) | ||
163 | { | ||
164 | _sizing_eval(obj); | ||
165 | wd->szeval = EINA_FALSE; | ||
166 | } | ||
167 | } | ||
168 | |||
169 | static void | ||
170 | _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
171 | { | ||
172 | Widget_Data *wd = elm_widget_data_get(obj); | ||
173 | if (!wd) return; | ||
174 | wd->eval = EINA_TRUE; | ||
175 | evas_object_smart_changed(obj); | ||
176 | } | ||
177 | |||
178 | static void | ||
179 | _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
180 | { | ||
181 | Widget_Data *wd = elm_widget_data_get(obj); | ||
182 | if (!wd) return; | ||
183 | wd->eval = EINA_TRUE; | ||
184 | evas_object_smart_changed(obj); | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | _child_change(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__) | ||
189 | { | ||
190 | Widget_Data *wd = elm_widget_data_get(data); | ||
191 | if (!wd) return; | ||
192 | wd->eval = EINA_TRUE; | ||
193 | wd->szeval = EINA_TRUE; | ||
194 | evas_object_smart_changed(data); | ||
195 | } | ||
196 | |||
197 | static void | ||
198 | _child_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__) | ||
199 | { | ||
200 | Evas_Object *fobj = data; | ||
201 | Widget_Data *wd = elm_widget_data_get(fobj); | ||
202 | if (!wd) return; | ||
203 | if (wd->content != obj) return; | ||
204 | evas_object_event_callback_del_full(wd->content, | ||
205 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
206 | _child_change, obj); | ||
207 | evas_object_event_callback_del_full(wd->content, | ||
208 | EVAS_CALLBACK_DEL, | ||
209 | _child_del, obj); | ||
210 | wd->content = NULL; | ||
211 | fac--; | ||
212 | // printf("FAC-- = %i\n", fac); | ||
213 | } | ||
214 | |||
215 | static Evas_Object * | ||
216 | _content_unset_hook(Evas_Object *obj, const char *part) | ||
217 | { | ||
218 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
219 | Widget_Data *wd; | ||
220 | Evas_Object *content; | ||
221 | |||
222 | if (part && strcmp(part, "default")) return NULL; | ||
223 | wd = elm_widget_data_get(obj); | ||
224 | if (!wd || !wd->content) return NULL; | ||
225 | |||
226 | content = wd->content; | ||
227 | evas_object_event_callback_del_full(content, | ||
228 | EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
229 | _child_change, obj); | ||
230 | evas_object_event_callback_del_full(content, | ||
231 | EVAS_CALLBACK_DEL, | ||
232 | _child_del, obj); | ||
233 | wd->content = NULL; | ||
234 | fac--; | ||
235 | // printf("FAC-- = %i\n", fac); | ||
236 | return content; | ||
237 | } | ||
238 | |||
239 | static void | ||
240 | _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content) | ||
241 | { | ||
242 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
243 | Widget_Data *wd; | ||
244 | Evas_Object *prev_content; | ||
245 | |||
246 | if (part && strcmp(part, "default")) return; | ||
247 | wd = elm_widget_data_get(obj); | ||
248 | if (!wd) return; | ||
249 | if (wd->content == content) return; | ||
250 | |||
251 | prev_content = _content_unset_hook(obj, part); | ||
252 | if (prev_content) evas_object_del(prev_content); | ||
253 | |||
254 | wd->content = content; | ||
255 | if (!content) return; | ||
256 | |||
257 | elm_widget_resize_object_set(obj, content); | ||
258 | evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _child_del, obj); | ||
259 | evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS, | ||
260 | _child_change, obj); | ||
261 | wd->eval = EINA_TRUE; | ||
262 | wd->szeval = EINA_TRUE; | ||
263 | evas_object_smart_changed(obj); | ||
264 | fac++; | ||
265 | } | ||
266 | |||
267 | static Evas_Object * | ||
268 | _content_get_hook(const Evas_Object *obj, const char *part) | ||
269 | { | ||
270 | ELM_CHECK_WIDTYPE(obj, widtype) NULL; | ||
271 | Widget_Data *wd; | ||
272 | if (part && strcmp(part, "default")) return NULL; | ||
273 | wd = elm_widget_data_get(obj); | ||
274 | if (!wd) return NULL; | ||
275 | return wd->content; | ||
276 | } | ||
277 | |||
278 | EAPI Evas_Object * | ||
279 | elm_factory_add(Evas_Object *parent) | ||
280 | { | ||
281 | Evas_Object *obj; | ||
282 | Evas *e; | ||
283 | Widget_Data *wd; | ||
284 | |||
285 | ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL); | ||
286 | |||
287 | ELM_SET_WIDTYPE(widtype, "factory"); | ||
288 | elm_widget_type_set(obj, "factory"); | ||
289 | elm_widget_sub_object_add(parent, obj); | ||
290 | elm_widget_data_set(obj, wd); | ||
291 | elm_widget_del_hook_set(obj, _del_hook); | ||
292 | elm_widget_focus_next_hook_set(obj, _focus_next_hook); | ||
293 | elm_widget_content_set_hook_set(obj, _content_set_hook); | ||
294 | elm_widget_content_get_hook_set(obj, _content_get_hook); | ||
295 | elm_widget_content_unset_hook_set(obj, _content_unset_hook); | ||
296 | elm_widget_can_focus_set(obj, EINA_FALSE); | ||
297 | elm_widget_changed_hook_set(obj, _changed); | ||
298 | |||
299 | evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL); | ||
300 | evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL); | ||
301 | |||
302 | evas_object_smart_callbacks_descriptions_set(obj, _signals); | ||
303 | |||
304 | wd->obj = obj; | ||
305 | wd->last_calc_count = -1; | ||
306 | return obj; | ||
307 | } | ||
308 | |||
309 | EAPI void | ||
310 | elm_factory_maxmin_mode_set(Evas_Object *obj, Eina_Bool enabled) | ||
311 | { | ||
312 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
313 | Widget_Data *wd = elm_widget_data_get(obj); | ||
314 | if (!wd) return; | ||
315 | wd->maxmin = !!enabled; | ||
316 | } | ||
317 | |||
318 | EAPI Eina_Bool | ||
319 | elm_factory_maxmin_mode_get(const Evas_Object *obj) | ||
320 | { | ||
321 | ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE; | ||
322 | Widget_Data *wd = elm_widget_data_get(obj); | ||
323 | if (!wd) return EINA_FALSE; | ||
324 | return wd->maxmin; | ||
325 | } | ||
326 | |||
327 | EAPI void | ||
328 | elm_factory_maxmin_reset_set(Evas_Object *obj) | ||
329 | { | ||
330 | ELM_CHECK_WIDTYPE(obj, widtype); | ||
331 | Widget_Data *wd = elm_widget_data_get(obj); | ||
332 | if (!wd) return; | ||
333 | wd->maxminw = 0; | ||
334 | wd->maxminh = 0; | ||
335 | wd->eval = EINA_TRUE; | ||
336 | wd->szeval = EINA_TRUE; | ||
337 | evas_object_smart_changed(obj); | ||
338 | } | ||