1 #ifdef HAVE_CONFIG_H
2 # include "elementary_config.h"
3 #endif
4 
5 #define EFL_ACCESS_OBJECT_PROTECTED
6 #define EFL_PART_PROTECTED
7 
8 #include <Elementary.h>
9 
10 #include "elm_priv.h"
11 #include "elm_widget_mapbuf.h"
12 #include "elm_widget_container.h"
13 #include "elm_mapbuf_eo.h"
14 
15 #include "elm_mapbuf_part.eo.h"
16 #include "elm_part_helper.h"
17 
18 #define MY_CLASS ELM_MAPBUF_CLASS
19 
20 #define MY_CLASS_NAME "Elm_Mapbuf"
21 #define MY_CLASS_NAME_LEGACY "elm_mapbuf"
22 
23 static void
_sizing_eval(Evas_Object * obj)24 _sizing_eval(Evas_Object *obj)
25 {
26    Evas_Coord minw = 0, minh = 0;
27    Evas_Coord maxw = -1, maxh = -1;
28 
29    ELM_MAPBUF_DATA_GET(obj, sd);
30    if (sd->content)
31      {
32         evas_object_size_hint_combined_min_get(sd->content, &minw, &minh);
33         evas_object_size_hint_max_get(sd->content, &maxw, &maxh);
34      }
35    evas_object_size_hint_min_set(obj, minw, minh);
36    evas_object_size_hint_max_set(obj, maxw, maxh);
37 }
38 
39 EOLIAN static Eina_Error
_elm_mapbuf_efl_ui_widget_theme_apply(Eo * obj,Elm_Mapbuf_Data * sd EINA_UNUSED)40 _elm_mapbuf_efl_ui_widget_theme_apply(Eo *obj, Elm_Mapbuf_Data *sd EINA_UNUSED)
41 {
42    Eina_Error int_ret = EFL_UI_THEME_APPLY_ERROR_GENERIC;
43    int_ret = efl_ui_widget_theme_apply(efl_super(obj, MY_CLASS));
44    if (int_ret == EFL_UI_THEME_APPLY_ERROR_GENERIC) return int_ret;
45 
46    _sizing_eval(obj);
47 
48    return int_ret;
49 }
50 
51 static void
_changed_size_hints_cb(void * data,Evas * e EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event_info EINA_UNUSED)52 _changed_size_hints_cb(void *data,
53                        Evas *e EINA_UNUSED,
54                        Evas_Object *obj EINA_UNUSED,
55                        void *event_info EINA_UNUSED)
56 {
57    _sizing_eval(data);
58 }
59 
60 static void
_elm_mapbuf_content_unset_internal(Elm_Mapbuf_Data * sd,Evas_Object * obj,Evas_Object * content)61 _elm_mapbuf_content_unset_internal(Elm_Mapbuf_Data *sd, Evas_Object *obj,
62                                    Evas_Object *content)
63 {
64    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
65 
66    evas_object_data_del(content, "_elm_leaveme");
67    evas_object_smart_member_del(content);
68    evas_object_clip_unset(content);
69    evas_object_color_set(wd->resize_obj, 0, 0, 0, 0);
70    evas_object_event_callback_del_full
71       (content, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints_cb,
72        obj);
73    sd->content = NULL;
74    _sizing_eval(obj);
75    ELM_SAFE_FREE(sd->idler, ecore_idler_del);
76 }
77 
78 EOLIAN static Eina_Bool
_elm_mapbuf_efl_ui_widget_widget_sub_object_del(Eo * obj,Elm_Mapbuf_Data * sd,Evas_Object * sobj)79 _elm_mapbuf_efl_ui_widget_widget_sub_object_del(Eo *obj, Elm_Mapbuf_Data *sd, Evas_Object *sobj)
80 {
81    Eina_Bool int_ret = EINA_FALSE;
82    int_ret = elm_widget_sub_object_del(efl_super(obj, MY_CLASS), sobj);
83    if (!int_ret) return EINA_FALSE;
84 
85    if (sobj == sd->content)
86      _elm_mapbuf_content_unset_internal(sd, (Evas_Object *)obj, sobj);
87    return EINA_TRUE;
88 }
89 
90 static void
_configure(Evas_Object * obj)91 _configure(Evas_Object *obj)
92 {
93    ELM_MAPBUF_DATA_GET(obj, sd);
94    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd);
95 
96    if (!sd->content) return;
97    if (sd->enabled && !evas_object_visible_get(obj)) return;
98 
99    Evas_Coord x, y, w, h;
100    int i;
101    evas_object_geometry_get(wd->resize_obj, &x, &y, &w, &h);
102 
103    if (sd->enabled)
104      {
105         if (!sd->map) sd->map = evas_map_new(4);
106         evas_map_util_points_populate_from_geometry(sd->map, x, y, w, h, 0);
107         for (i = 0; i < (int)(sizeof(sd->colors)/sizeof(sd->colors[0])); i++)
108           {
109              evas_map_point_color_set(sd->map, i, sd->colors[i].r,
110                                       sd->colors[i].g, sd->colors[i].b,
111                                       sd->colors[i].a);
112           }
113 
114         evas_map_smooth_set(sd->map, sd->smooth);
115         evas_map_alpha_set(sd->map, sd->alpha);
116         evas_object_map_set(sd->content, sd->map);
117         evas_object_map_enable_set(sd->content, EINA_TRUE);
118      }
119    else
120      evas_object_move(sd->content, x, y);
121 }
122 
123 static void
_mapbuf_auto_eval(Evas_Object * obj,Elm_Mapbuf_Data * sd)124 _mapbuf_auto_eval(Evas_Object *obj, Elm_Mapbuf_Data *sd)
125 {
126    Eina_Bool vis;
127    Evas_Coord x, y, w, h;
128    Evas_Coord vx, vy, vw, vh;
129    Eina_Bool on = EINA_FALSE;
130 
131    if (!sd->automode) return ;
132    vis = evas_object_visible_get(obj);
133    evas_object_geometry_get(obj, &x, &y, &w, &h);
134    evas_output_viewport_get(evas_object_evas_get(obj), &vx, &vy, &vw, &vh);
135    if ((vis) && (ELM_RECTS_INTERSECT(x, y, w, h, vx, vy, vw, vh)))
136      on = EINA_TRUE;
137    elm_mapbuf_enabled_set(obj, on);
138 }
139 
140 static Eina_Bool
_mapbuf_move_end(void * data)141 _mapbuf_move_end(void *data)
142 {
143    Elm_Mapbuf_Data *sd = data;
144 
145    elm_mapbuf_smooth_set(sd->self, sd->smooth_saved);
146    sd->idler = NULL;
147 
148    return EINA_FALSE;
149 }
150 
151 static void
_mapbuf_auto_smooth(Evas_Object * obj EINA_UNUSED,Elm_Mapbuf_Data * sd)152 _mapbuf_auto_smooth(Evas_Object *obj EINA_UNUSED, Elm_Mapbuf_Data *sd)
153 {
154    if (!sd->automode) return ;
155    if (!sd->idler) sd->idler = ecore_idler_add(_mapbuf_move_end, sd);
156    sd->smooth = EINA_FALSE;
157 }
158 
159 EOLIAN static void
_elm_mapbuf_efl_gfx_entity_position_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Position2D pos)160 _elm_mapbuf_efl_gfx_entity_position_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Position2D pos)
161 {
162    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_MOVE, 0, pos.x, pos.y))
163      return;
164 
165    efl_gfx_entity_position_set(efl_super(obj, MY_CLASS), pos);
166 
167    _mapbuf_auto_eval(obj, sd);
168    _mapbuf_auto_smooth(obj, sd);
169    _configure(obj);
170 }
171 
172 EOLIAN static void
_elm_mapbuf_efl_gfx_entity_size_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Size2D sz)173 _elm_mapbuf_efl_gfx_entity_size_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Size2D sz)
174 {
175    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_RESIZE, 0, sz.w, sz.h))
176      return;
177 
178    efl_gfx_entity_size_set(efl_super(obj, MY_CLASS), sz);
179    if (sd->content)
180      efl_gfx_entity_size_set(sd->content, sz);
181 
182    _mapbuf_auto_eval(obj, sd);
183    _configure(obj);
184 }
185 
186 EOLIAN static void
_elm_mapbuf_efl_gfx_entity_visible_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool vis)187 _elm_mapbuf_efl_gfx_entity_visible_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool vis)
188 {
189    if (_evas_object_intercept_call(obj, EVAS_OBJECT_INTERCEPT_CB_VISIBLE, 0, vis))
190      return;
191 
192    efl_gfx_entity_visible_set(efl_super(obj, MY_CLASS), vis);
193 
194    _mapbuf_auto_eval(obj, sd);
195    _configure(obj);
196 }
197 
198 static Eina_Bool
_elm_mapbuf_content_set(Eo * obj,Elm_Mapbuf_Data * sd,const char * part,Evas_Object * content)199 _elm_mapbuf_content_set(Eo *obj, Elm_Mapbuf_Data *sd, const char *part, Evas_Object *content)
200 {
201    ELM_WIDGET_DATA_GET_OR_RETURN(obj, wd, EINA_FALSE);
202 
203    if (part && strcmp(part, "default")) return EINA_FALSE;
204    if (sd->content == content) return EINA_TRUE;
205 
206    evas_object_del(sd->content);
207    sd->content = content;
208 
209    if (content)
210      {
211         evas_object_data_set(content, "_elm_leaveme", (void *)1);
212         elm_widget_sub_object_add(obj, content);
213         evas_object_smart_member_add(content, obj);
214         evas_object_clip_set(content, wd->resize_obj);
215         evas_object_color_set
216           (wd->resize_obj, 255, 255, 255, 255);
217         evas_object_event_callback_add
218           (content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
219           _changed_size_hints_cb, obj);
220      }
221    else
222      evas_object_color_set(wd->resize_obj, 0, 0, 0, 0);
223    efl_event_callback_call(obj, EFL_CONTENT_EVENT_CONTENT_CHANGED, content);
224    _sizing_eval(obj);
225    _configure(obj);
226 
227    return EINA_TRUE;
228 }
229 
230 static Evas_Object*
_elm_mapbuf_content_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd,const char * part)231 _elm_mapbuf_content_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd, const char *part)
232 {
233    if (part && strcmp(part, "default")) return NULL;
234    return sd->content;
235 }
236 
237 static Evas_Object*
_elm_mapbuf_content_unset(Eo * obj,Elm_Mapbuf_Data * sd,const char * part)238 _elm_mapbuf_content_unset(Eo *obj, Elm_Mapbuf_Data *sd, const char *part)
239 {
240    Evas_Object *content;
241    if (part && strcmp(part, "default")) return NULL;
242    if (!sd->content) return NULL;
243 
244    content = sd->content;
245    _elm_widget_sub_object_redirect_to_top(obj, content);
246    _elm_mapbuf_content_unset_internal(sd, obj, content);
247    efl_event_callback_call(obj, EFL_CONTENT_EVENT_CONTENT_CHANGED, NULL);
248    return content;
249 }
250 
251 EOLIAN static Eina_Bool
_elm_mapbuf_efl_content_content_set(Eo * obj,Elm_Mapbuf_Data * sd,Evas_Object * content)252 _elm_mapbuf_efl_content_content_set(Eo *obj, Elm_Mapbuf_Data *sd, Evas_Object *content)
253 {
254    return _elm_mapbuf_content_set(obj, sd, NULL, content);
255 }
256 
257 EOLIAN static Evas_Object*
_elm_mapbuf_efl_content_content_get(const Eo * obj,Elm_Mapbuf_Data * sd)258 _elm_mapbuf_efl_content_content_get(const Eo *obj, Elm_Mapbuf_Data *sd)
259 {
260    return _elm_mapbuf_content_get(obj, sd, NULL);
261 }
262 
263 EOLIAN static Evas_Object*
_elm_mapbuf_efl_content_content_unset(Eo * obj,Elm_Mapbuf_Data * sd)264 _elm_mapbuf_efl_content_content_unset(Eo *obj, Elm_Mapbuf_Data *sd)
265 {
266    return _elm_mapbuf_content_unset(obj, sd, NULL);
267 }
268 
269 EOLIAN static void
_elm_mapbuf_efl_canvas_group_group_del(Eo * obj,Elm_Mapbuf_Data * priv)270 _elm_mapbuf_efl_canvas_group_group_del(Eo *obj, Elm_Mapbuf_Data *priv)
271 {
272    ELM_SAFE_FREE(priv->idler, ecore_idler_del);
273    ELM_SAFE_FREE(priv->map, evas_map_free);
274 
275    efl_canvas_group_del(efl_super(obj, MY_CLASS));
276 }
277 
278 EOLIAN static void
_elm_mapbuf_efl_canvas_group_group_add(Eo * obj,Elm_Mapbuf_Data * priv)279 _elm_mapbuf_efl_canvas_group_group_add(Eo *obj, Elm_Mapbuf_Data *priv)
280 {
281    Evas_Object *rect = evas_object_rectangle_add(evas_object_evas_get(obj));
282    int i;
283 
284    elm_widget_resize_object_set(obj, rect);
285 
286    efl_canvas_group_add(efl_super(obj, MY_CLASS));
287 
288    evas_object_static_clip_set(rect, EINA_TRUE);
289    evas_object_pass_events_set(rect, EINA_TRUE);
290    evas_object_color_set(rect, 0, 0, 0, 0);
291 
292    for (i = 0; i < (int)(sizeof(priv->colors)/sizeof(priv->colors[0])); i++)
293      {
294         priv->colors[i].r = 255;
295         priv->colors[i].g = 255;
296         priv->colors[i].b = 255;
297         priv->colors[i].a = 255;
298      }
299 
300    priv->self = obj;
301    priv->alpha = EINA_TRUE;
302    priv->smooth = EINA_TRUE;
303 
304    elm_widget_can_focus_set(obj, EINA_FALSE);
305 
306    _sizing_eval(obj);
307 }
308 
309 EAPI Evas_Object *
elm_mapbuf_add(Evas_Object * parent)310 elm_mapbuf_add(Evas_Object *parent)
311 {
312    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
313    return elm_legacy_add(MY_CLASS, parent);
314 }
315 
316 EOLIAN static Eo *
_elm_mapbuf_efl_object_constructor(Eo * obj,Elm_Mapbuf_Data * sd EINA_UNUSED)317 _elm_mapbuf_efl_object_constructor(Eo *obj, Elm_Mapbuf_Data *sd EINA_UNUSED)
318 {
319    obj = efl_constructor(efl_super(obj, MY_CLASS));
320    efl_canvas_object_type_set(obj, MY_CLASS_NAME_LEGACY);
321    efl_access_object_role_set(obj, EFL_ACCESS_ROLE_IMAGE_MAP);
322 
323    return obj;
324 }
325 
326 static void
_internal_enable_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool enabled)327 _internal_enable_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool enabled)
328 {
329    if (sd->enabled == enabled) return;
330    sd->enabled = enabled;
331 
332    if (!sd->enabled && sd->content)
333      {
334         evas_object_map_set(sd->content, NULL);
335         evas_object_map_enable_set(sd->content, EINA_FALSE);
336      }
337    _configure(obj);
338 }
339 
340 EOLIAN static void
_elm_mapbuf_enabled_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool enabled)341 _elm_mapbuf_enabled_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool enabled)
342 {
343    _internal_enable_set(obj, sd, enabled);
344 }
345 
346 EOLIAN static Eina_Bool
_elm_mapbuf_enabled_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd)347 _elm_mapbuf_enabled_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd)
348 {
349    return sd->enabled;
350 }
351 
352 EOLIAN static void
_elm_mapbuf_smooth_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool smooth)353 _elm_mapbuf_smooth_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool smooth)
354 {
355    if (sd->smooth == smooth) return;
356    sd->smooth = smooth;
357    sd->smooth_saved = smooth;
358    _configure(obj);
359 }
360 
361 EOLIAN static Eina_Bool
_elm_mapbuf_smooth_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd)362 _elm_mapbuf_smooth_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd)
363 {
364    return sd->smooth;
365 }
366 
367 EOLIAN static void
_elm_mapbuf_alpha_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool alpha)368 _elm_mapbuf_alpha_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool alpha)
369 {
370    if (sd->alpha == alpha) return;
371    sd->alpha = alpha;
372    _configure(obj);
373 }
374 
375 EOLIAN static Eina_Bool
_elm_mapbuf_alpha_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd)376 _elm_mapbuf_alpha_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd)
377 {
378    return sd->alpha;
379 }
380 
381 EOLIAN static void
_elm_mapbuf_auto_set(Eo * obj,Elm_Mapbuf_Data * sd,Eina_Bool on)382 _elm_mapbuf_auto_set(Eo *obj, Elm_Mapbuf_Data *sd, Eina_Bool on)
383 {
384    if (sd->automode == on) return;
385    sd->automode = on;
386    if (on)
387      {
388         _mapbuf_auto_eval(obj, sd);
389      }
390    else
391      {
392         ELM_SAFE_FREE(sd->idler, ecore_idler_del);
393 
394         _internal_enable_set(obj, sd, EINA_FALSE);
395      }
396    _configure(obj);
397 }
398 
399 EOLIAN static Eina_Bool
_elm_mapbuf_auto_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd)400 _elm_mapbuf_auto_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd)
401 {
402    return sd->automode;
403 }
404 
405 EOLIAN static void
_elm_mapbuf_point_color_get(const Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd,int idx,int * r,int * g,int * b,int * a)406 _elm_mapbuf_point_color_get(const Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd, int idx, int *r, int *g, int *b, int *a)
407 {
408    if ((idx < 0) || (idx >= 4))
409      {
410         ERR("idx value should be 0 ~ 4");
411         return;
412      }
413    *r = sd->colors[idx].r;
414    *g = sd->colors[idx].g;
415    *b = sd->colors[idx].b;
416    *a =sd->colors[idx].a;
417 }
418 
419 EOLIAN static void
_elm_mapbuf_point_color_set(Eo * obj EINA_UNUSED,Elm_Mapbuf_Data * sd,int idx,int r,int g,int b,int a)420 _elm_mapbuf_point_color_set(Eo *obj EINA_UNUSED, Elm_Mapbuf_Data *sd, int idx, int r, int g, int b, int a)
421 {
422    if ((idx < 0) || (idx >= 4))
423      {
424         ERR("idx value should be 0 ~ 4");
425         return;
426      }
427    sd->colors[idx].r = r;
428    sd->colors[idx].g = g;
429    sd->colors[idx].b = b;
430    sd->colors[idx].a = a;
431 
432    _configure(obj);
433 }
434 
435 static void
_elm_mapbuf_class_constructor(Efl_Class * klass)436 _elm_mapbuf_class_constructor(Efl_Class *klass)
437 {
438    evas_smart_legacy_type_register(MY_CLASS_NAME_LEGACY, klass);
439 }
440 
441 /* Efl.Part begin */
442 
443 ELM_PART_OVERRIDE(elm_mapbuf, ELM_MAPBUF, Elm_Mapbuf_Data)
444 ELM_PART_OVERRIDE_CONTENT_SET(elm_mapbuf, ELM_MAPBUF, Elm_Mapbuf_Data)
445 ELM_PART_OVERRIDE_CONTENT_GET(elm_mapbuf, ELM_MAPBUF, Elm_Mapbuf_Data)
446 ELM_PART_OVERRIDE_CONTENT_UNSET(elm_mapbuf, ELM_MAPBUF, Elm_Mapbuf_Data)
447 ELM_PART_CONTENT_DEFAULT_GET(elm_mapbuf, "default")
448 #include "elm_mapbuf_part.eo.c"
449 
450 /* Efl.Part end */
451 
452 /* Internal EO APIs and hidden overrides */
453 
454 #define ELM_MAPBUF_EXTRA_OPS \
455    ELM_PART_CONTENT_DEFAULT_OPS(elm_mapbuf), \
456    EFL_CANVAS_GROUP_ADD_DEL_OPS(elm_mapbuf)
457 
458 #include "elm_mapbuf_eo.c"
459