Initialize Tizen 2.3
[framework/uifw/elementary.git] / mobile / src / lib / elm_mapbuf.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include "elm_widget_mapbuf.h"
4
5 EAPI const char ELM_MAPBUF_SMART_NAME[] = "elm_mapbuf";
6
7 EVAS_SMART_SUBCLASS_NEW
8   (ELM_MAPBUF_SMART_NAME, _elm_mapbuf, Elm_Mapbuf_Smart_Class,
9   Elm_Container_Smart_Class, elm_container_smart_class_get, NULL);
10
11 static void
12 _sizing_eval(Evas_Object *obj)
13 {
14    Evas_Coord minw = -1, minh = -1;
15    Evas_Coord maxw = -1, maxh = -1;
16
17    ELM_MAPBUF_DATA_GET(obj, sd);
18    if (sd->content)
19      {
20         evas_object_size_hint_min_get(sd->content, &minw, &minh);
21         evas_object_size_hint_max_get(sd->content, &maxw, &maxh);
22      }
23    evas_object_size_hint_min_set(obj, minw, minh);
24    evas_object_size_hint_max_set(obj, maxw, maxh);
25 }
26
27 static Eina_Bool
28 _elm_mapbuf_smart_theme(Evas_Object *obj)
29 {
30    if (!ELM_WIDGET_CLASS(_elm_mapbuf_parent_sc)->theme(obj)) return EINA_FALSE;
31
32    _sizing_eval(obj);
33
34    return EINA_TRUE;
35 }
36
37 static void
38 _changed_size_hints_cb(void *data,
39                        Evas *e __UNUSED__,
40                        Evas_Object *obj __UNUSED__,
41                        void *event_info __UNUSED__)
42 {
43    _sizing_eval(data);
44 }
45
46 static Eina_Bool
47 _elm_mapbuf_smart_sub_object_del(Evas_Object *obj,
48                                  Evas_Object *sobj)
49 {
50    ELM_MAPBUF_DATA_GET(obj, sd);
51
52    if (!ELM_WIDGET_CLASS(_elm_mapbuf_parent_sc)->sub_object_del(obj, sobj))
53      return EINA_FALSE;
54
55    if (sobj == sd->content)
56      {
57         evas_object_data_del(sobj, "_elm_leaveme");
58         evas_object_smart_member_del(sobj);
59         evas_object_clip_unset(sobj);
60         evas_object_event_callback_del_full
61           (sobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb,
62           obj);
63         sd->content = NULL;
64         _sizing_eval(obj);
65      }
66
67    return EINA_TRUE;
68 }
69
70 static void
71 _mapbuf(Evas_Object *obj)
72 {
73    Evas_Coord x, y, w, h;
74
75    ELM_MAPBUF_DATA_GET(obj, sd);
76
77    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, &h);
78    evas_object_resize(sd->content, w, h);
79
80    if (sd->enabled)
81      {
82         Evas_Map *m;
83
84         m = evas_map_new(4);
85         evas_map_util_points_populate_from_geometry(m, x, y, w, h, 0);
86         evas_map_smooth_set(m, sd->smooth);
87         evas_map_alpha_set(m, sd->alpha);
88         evas_object_map_set(sd->content, m);
89         evas_object_map_enable_set(sd->content, EINA_TRUE);
90         evas_map_free(m);
91      }
92    else
93      {
94         evas_object_map_set(sd->content, NULL);
95         evas_object_map_enable_set(sd->content, EINA_FALSE);
96         evas_object_move(sd->content, x, y);
97      }
98 }
99
100 static void
101 _configure(Evas_Object *obj, Eina_Bool update_force)
102 {
103    ELM_MAPBUF_DATA_GET(obj, sd);
104
105    if (!sd->content) return;
106    Eina_Bool inside_all = EINA_FALSE;
107    Evas_Coord x, y, w, h, x2, y2, w2, h2, vx, vy, vw, vh;
108    evas_object_geometry_get(ELM_WIDGET_DATA(sd)->resize_obj, &x, &y, &w, &h);
109    evas_object_geometry_get(sd->content, &x2, &y2, &w2, &h2);
110
111    if ((update_force) || ((x != x2) || (y != y2) || (w != w2) || (h != h2)))
112      {
113         Evas *e = evas_object_evas_get(obj);
114         evas_output_viewport_get(e, &vx, &vy, &vw, &vh);
115
116         /* Apply no changes once the content is rendered fully one time. We
117            aren't sure that the content is updated correctly if the content was
118            outside of the viewport, especially it has many child members. Some
119            type of children will do the lazy updated (ie, textblock) on right
120            before the rendering. It means they lose the update time cause
121            of the mapbuf since the mapbuf tries nochange forcefully. */
122         if (!sd->inside_view[0] && ((x >= vx) && (x <= (vx + vw))))
123           sd->inside_view[0] = EINA_TRUE;
124         if (!sd->inside_view[1] && ((y >= vy) && (y <= (vy + vh))))
125           sd->inside_view[1] = EINA_TRUE;
126
127         if (!sd->inside_view[2] && (((x + w) >= vx) && ((x + w) <= (vx + vw))))
128           sd->inside_view[2] = EINA_TRUE;
129
130         if (!sd->inside_view[3] && (((y + h) >= vy) && ((y + h) <= (vy + vh))))
131           sd->inside_view[3] = EINA_TRUE;
132
133         if (sd->inside_view[0] && sd->inside_view[1] && sd->inside_view[2] &&
134             sd->inside_view[3])
135              inside_all = EINA_TRUE;
136
137         if (!sd->enabled || !inside_all)
138           evas_object_move(sd->content, x, y);
139         else
140           {
141              evas_smart_objects_calculate(e);
142              ELM_WIDGET_CHECK_OR_RETURN(obj);
143              evas_nochange_push(e);
144              evas_object_move(sd->content, x, y);
145              evas_smart_objects_calculate(e);
146              ELM_WIDGET_CHECK_OR_RETURN(obj);
147              evas_nochange_pop(e);
148           }
149         _mapbuf(obj);
150      }
151 }
152
153 static void
154 _elm_mapbuf_smart_move(Evas_Object *obj,
155                        Evas_Coord x,
156                        Evas_Coord y)
157 {
158    ELM_WIDGET_CLASS(_elm_mapbuf_parent_sc)->base.move(obj, x, y);
159
160    _configure(obj, EINA_FALSE);
161 }
162
163 static void
164 _elm_mapbuf_smart_resize(Evas_Object *obj,
165                          Evas_Coord x,
166                          Evas_Coord y)
167 {
168    ELM_WIDGET_CLASS(_elm_mapbuf_parent_sc)->base.resize(obj, x, y);
169
170    _configure(obj, EINA_FALSE);
171 }
172
173 static void
174 _elm_mapbuf_inside_view_reset(Evas_Object *obj)
175 {
176    ELM_MAPBUF_DATA_GET(obj, sd);
177
178    sd->inside_view[0] = EINA_FALSE;
179    sd->inside_view[1] = EINA_FALSE;
180    sd->inside_view[2] = EINA_FALSE;
181    sd->inside_view[3] = EINA_FALSE;
182 }
183
184 static Eina_Bool
185 _elm_mapbuf_smart_content_set(Evas_Object *obj,
186                               const char *part,
187                               Evas_Object *content)
188 {
189    ELM_MAPBUF_DATA_GET(obj, sd);
190
191    if (part && strcmp(part, "default")) return EINA_FALSE;
192    if (sd->content == content) return EINA_TRUE;
193
194    if (sd->content) evas_object_del(sd->content);
195    sd->content = content;
196
197    if (content)
198      {
199         evas_object_data_set(content, "_elm_leaveme", (void *)1);
200         elm_widget_sub_object_add(obj, content);
201         evas_object_smart_member_add(content, obj);
202         evas_object_clip_set(content, ELM_WIDGET_DATA(sd)->resize_obj);
203         evas_object_color_set
204           (ELM_WIDGET_DATA(sd)->resize_obj, 255, 255, 255, 255);
205         evas_object_event_callback_add
206           (content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
207           _changed_size_hints_cb, obj);
208      }
209    else
210      evas_object_color_set(ELM_WIDGET_DATA(sd)->resize_obj, 0, 0, 0, 0);
211
212    _elm_mapbuf_inside_view_reset(obj);
213
214    _sizing_eval(obj);
215    _configure(obj, EINA_TRUE);
216
217    return EINA_TRUE;
218 }
219
220 static Evas_Object *
221 _elm_mapbuf_smart_content_get(const Evas_Object *obj,
222                               const char *part)
223 {
224    ELM_MAPBUF_DATA_GET(obj, sd);
225
226    if (part && strcmp(part, "default")) return NULL;
227    return sd->content;
228 }
229
230 static Evas_Object *
231 _elm_mapbuf_smart_content_unset(Evas_Object *obj,
232                                 const char *part)
233 {
234    Evas_Object *content;
235
236    ELM_MAPBUF_DATA_GET(obj, sd);
237
238    if (part && strcmp(part, "default")) return NULL;
239    if (!sd->content) return NULL;
240
241    content = sd->content;
242    elm_widget_sub_object_del(obj, content);
243    evas_object_smart_member_del(content);
244    evas_object_data_del(content, "_elm_leaveme");
245    evas_object_color_set(ELM_WIDGET_DATA(sd)->resize_obj, 0, 0, 0, 0);
246    return content;
247 }
248
249 static void
250 _elm_mapbuf_smart_add(Evas_Object *obj)
251 {
252    EVAS_SMART_DATA_ALLOC(obj, Elm_Mapbuf_Smart_Data);
253
254    ELM_WIDGET_DATA(priv)->resize_obj =
255        evas_object_rectangle_add(evas_object_evas_get(obj));
256
257    ELM_WIDGET_CLASS(_elm_mapbuf_parent_sc)->base.add(obj);
258
259    evas_object_static_clip_set(ELM_WIDGET_DATA(priv)->resize_obj, EINA_TRUE);
260    evas_object_pass_events_set(ELM_WIDGET_DATA(priv)->resize_obj, EINA_TRUE);
261    evas_object_color_set(ELM_WIDGET_DATA(priv)->resize_obj, 0, 0, 0, 0);
262
263    priv->enabled = 0;
264    priv->alpha = 1;
265    priv->smooth = 1;
266
267    elm_widget_can_focus_set(obj, EINA_FALSE);
268
269    _sizing_eval(obj);
270 }
271
272 static Eina_Bool
273 _elm_mapbuf_smart_focus_next(const Evas_Object *obj,
274                              Elm_Focus_Direction dir,
275                              Evas_Object **next)
276 {
277    ELM_MAPBUF_CHECK(obj) EINA_FALSE;
278    ELM_MAPBUF_DATA_GET(obj, sd);
279
280    if (sd->content)
281      return elm_widget_focus_next_get(sd->content, dir, next);
282
283    return EINA_FALSE;
284 }
285
286 static void
287 _elm_mapbuf_smart_access(Evas_Object *obj, Eina_Bool is_access)
288 {
289    ELM_MAPBUF_DATA_GET(obj, sd);
290
291    if (is_access)
292      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next =
293         _elm_mapbuf_smart_focus_next;
294    else
295      ELM_WIDGET_CLASS(ELM_WIDGET_DATA(sd)->api)->focus_next = NULL;
296 }
297
298 static void
299 _elm_mapbuf_smart_set_user(Elm_Mapbuf_Smart_Class *sc)
300 {
301    ELM_WIDGET_CLASS(sc)->base.add = _elm_mapbuf_smart_add;
302    ELM_WIDGET_CLASS(sc)->base.resize = _elm_mapbuf_smart_resize;
303    ELM_WIDGET_CLASS(sc)->base.move = _elm_mapbuf_smart_move;
304
305    ELM_WIDGET_CLASS(sc)->theme = _elm_mapbuf_smart_theme;
306    ELM_WIDGET_CLASS(sc)->sub_object_del = _elm_mapbuf_smart_sub_object_del;
307    ELM_WIDGET_CLASS(sc)->access = _elm_mapbuf_smart_access;
308
309    if (_elm_config->access_mode)
310      ELM_WIDGET_CLASS(sc)->focus_next = _elm_mapbuf_smart_focus_next;
311
312    ELM_CONTAINER_CLASS(sc)->content_set = _elm_mapbuf_smart_content_set;
313    ELM_CONTAINER_CLASS(sc)->content_get = _elm_mapbuf_smart_content_get;
314    ELM_CONTAINER_CLASS(sc)->content_unset = _elm_mapbuf_smart_content_unset;
315 }
316
317 EAPI const Elm_Mapbuf_Smart_Class *
318 elm_mapbuf_smart_class_get(void)
319 {
320    static Elm_Mapbuf_Smart_Class _sc =
321      ELM_MAPBUF_SMART_CLASS_INIT_NAME_VERSION(ELM_MAPBUF_SMART_NAME);
322    static const Elm_Mapbuf_Smart_Class *class = NULL;
323
324    if (class) return class;
325
326    _elm_mapbuf_smart_set(&_sc);
327    class = &_sc;
328
329    return class;
330 }
331
332 EAPI Evas_Object *
333 elm_mapbuf_add(Evas_Object *parent)
334 {
335    Evas_Object *obj;
336
337    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
338
339    obj = elm_widget_add(_elm_mapbuf_smart_class_new(), parent);
340    if (!obj) return NULL;
341
342    if (!elm_widget_sub_object_add(parent, obj))
343      ERR("could not add %p as sub object of %p", obj, parent);
344
345    return obj;
346 }
347
348 EAPI void
349 elm_mapbuf_enabled_set(Evas_Object *obj,
350                        Eina_Bool enabled)
351 {
352    ELM_MAPBUF_CHECK(obj);
353    ELM_MAPBUF_DATA_GET(obj, sd);
354
355    if (sd->enabled == enabled) return;
356    sd->enabled = enabled;
357
358    _elm_mapbuf_inside_view_reset(obj);
359    if (sd->content) evas_object_static_clip_set(sd->content, sd->enabled);
360    _configure(obj, EINA_TRUE);
361 }
362
363 EAPI Eina_Bool
364 elm_mapbuf_enabled_get(const Evas_Object *obj)
365 {
366    ELM_MAPBUF_CHECK(obj) EINA_FALSE;
367    ELM_MAPBUF_DATA_GET(obj, sd);
368
369    return sd->enabled;
370 }
371
372 EAPI void
373 elm_mapbuf_smooth_set(Evas_Object *obj,
374                       Eina_Bool smooth)
375 {
376    ELM_MAPBUF_CHECK(obj);
377    ELM_MAPBUF_DATA_GET(obj, sd);
378
379    if (sd->smooth == smooth) return;
380    sd->smooth = smooth;
381    _configure(obj, EINA_TRUE);
382 }
383
384 EAPI Eina_Bool
385 elm_mapbuf_smooth_get(const Evas_Object *obj)
386 {
387    ELM_MAPBUF_CHECK(obj) EINA_FALSE;
388    ELM_MAPBUF_DATA_GET(obj, sd);
389
390    return sd->smooth;
391 }
392
393 EAPI void
394 elm_mapbuf_alpha_set(Evas_Object *obj,
395                      Eina_Bool alpha)
396 {
397    ELM_MAPBUF_CHECK(obj);
398    ELM_MAPBUF_DATA_GET(obj, sd);
399
400    if (sd->alpha == alpha) return;
401    sd->alpha = alpha;
402    _configure(obj, EINA_TRUE);
403 }
404
405 EAPI Eina_Bool
406 elm_mapbuf_alpha_get(const Evas_Object *obj)
407 {
408    ELM_MAPBUF_CHECK(obj) EINA_FALSE;
409    ELM_MAPBUF_DATA_GET(obj, sd);
410
411    return sd->alpha;
412 }