summaryrefslogtreecommitdiff
path: root/src/lib/edje/edje_part_helper.h
blob: 3bea35fc45b35322486de8a1058cbed8162b0319 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include "edje_private.h"
#include "efl_canvas_layout_part.eo.h"

typedef struct _Efl_Canvas_Layout_Part_Data Efl_Canvas_Layout_Part_Data;

struct _Efl_Canvas_Layout_Part_Data
{
   Edje           *ed;
   Edje_Real_Part *rp;
   const char     *part;
   Eo             *obj;
   unsigned char   temp, in_call, in_use;
};

struct _Part_Item_Iterator
{
   Eina_Iterator  iterator;
   Eina_List     *list;
   Eina_Iterator *real_iterator;
   Eo            *object;
};

void _part_reuse_error(Efl_Canvas_Layout_Part_Data *pd);
const char * _part_type_to_string(unsigned char type);

#define PROXY_CALL_BEGIN(pd) do { pd->in_call = 1; } while (0)
#define PROXY_CALL_END(pd) do { pd->in_call = 0; } while (0)
#define PROXY_REF(obj, pd) do { if (!(pd->temp++)) efl_ref(obj); } while(0)
#define PROXY_UNREF(obj, pd) do { if (pd->temp) { if (!(--pd->temp)) efl_del(obj); } } while(0)
#define RETURN_VAL(a) do { typeof(a) _ret = a; PROXY_CALL_END(pd); PROXY_UNREF(obj, pd); return _ret; } while(0)
#define RETURN_VOID do { PROXY_CALL_END(pd); PROXY_UNREF(obj, pd); return; } while(0)
#define PROXY_CALL(a) ({ PROXY_REF(obj, pd); a; })
#define PROXY_STATIC_VAR(type) _##type##_proxy

#ifndef PROXY_ADD_EXTRA_OP
# define PROXY_ADD_EXTRA_OP
#endif

void _edje_real_part_set(Eo *obj, Edje *ed, Edje_Real_Part *rp, const char *part);

static inline void
_part_proxy_del_cb(Eo *proxy, Eo **static_var)
{
   Efl_Canvas_Layout_Part_Data *pd;
   if (*static_var)
     {
        // FIXME: Enable debug checks only in debug mode
        pd = efl_data_scope_get(*static_var, EFL_CANVAS_LAYOUT_PART_CLASS);
        if (pd && pd->temp && !pd->in_call)
          _part_reuse_error(pd);
        if (*static_var != proxy)
          efl_del_intercept_set(*static_var, NULL);
     }
   if (efl_parent_get(proxy))
     {
        efl_ref(proxy);
        efl_parent_set(proxy, NULL);
     }
   efl_reuse(proxy);
   pd = efl_data_scope_get(proxy, EFL_CANVAS_LAYOUT_PART_CLASS);
   pd->in_use = EINA_FALSE;
   *static_var = proxy;
}

/* ugly macros to avoid code duplication */

#define PROXY_RESET(type) \
   do { if (PROXY_STATIC_VAR(type)) \
     { \
        efl_del_intercept_set(PROXY_STATIC_VAR(type), NULL); \
        efl_del(PROXY_STATIC_VAR(type)); \
        PROXY_STATIC_VAR(type) = NULL; \
     } } while (0)

#define PROXY_INIT(type) \
void \
_ ## type ## _shutdown(void); \

#define PROXY_DATA_GET(obj, pd) \
   Efl_Canvas_Layout_Part_Data *pd = efl_data_scope_get(obj, EFL_CANVAS_LAYOUT_PART_CLASS); \
   PROXY_CALL_BEGIN(pd)

#define PROXY_IMPLEMENTATION(type, KLASS, no_del_cb, ...) \
static Eo * PROXY_STATIC_VAR(type) = NULL; \
\
static void \
_ ## type ## _del_cb(Eo *proxy) \
{ \
   _part_proxy_del_cb(proxy, &(PROXY_STATIC_VAR(type))); \
} \
\
void \
_ ## type ## _shutdown(void) \
{ \
   PROXY_RESET(type); \
} \
\
Eo * \
_edje_ ## type ## _internal_proxy_get(Edje_Object *obj EINA_UNUSED, Edje *ed, Edje_Real_Part *rp) \
{ \
   Efl_Canvas_Layout_Part_Data *pd; \
   Eo *proxy = PROXY_STATIC_VAR(type); \
   \
   pd = proxy ? efl_data_scope_get(proxy, EFL_CANVAS_LAYOUT_PART_CLASS) : NULL; \
   if (!pd) \
     { \
        if (EINA_UNLIKELY(PROXY_STATIC_VAR(type) != NULL)) \
          ERR("Found invalid handle for efl_part. Reset."); \
        proxy = efl_add(KLASS, ed->obj, _edje_real_part_set(efl_added, ed, rp, rp->part->name)); \
        goto end ; \
     } \
   \
   if (EINA_UNLIKELY(pd->in_use)) \
     { \
        /* if (!pd->in_call) _part_reuse_error(pd); */ \
        proxy = efl_add(KLASS, ed->obj, _edje_real_part_set(efl_added, ed, rp, rp->part->name)); \
     } \
   else \
     { \
        _edje_real_part_set(proxy, ed, rp, rp->part->name); \
     } \
   \
end: \
    \
   __VA_ARGS__; \
   if (!no_del_cb) \
     { \
        PROXY_STATIC_VAR(type) = proxy; \
        efl_del_intercept_set(proxy, _ ## type ## _del_cb); \
     } \
   return proxy; \
}

#ifdef DEBUG
#define PART_TABLE_GET(obj, part, ...) ({ \
   Eo *__table = efl_part(obj, part); \
   if (!__table || !efl_isa(__table, EFL_CANVAS_LAYOUT_PART_TABLE_CLASS)) \
     { \
        ERR("No such table part '%s' in layout %p", part, obj); \
        return __VA_ARGS__; \
     } \
   __table; })
#else
#define PART_TABLE_GET(obj, part, ...) ({ \
   Eo *__table = efl_part(obj, part); \
   if (!__table) return __VA_ARGS__; \
   __table; })
#endif