diff options
Diffstat (limited to 'libraries/evas/src/lib/canvas/evas_smart.c')
-rw-r--r-- | libraries/evas/src/lib/canvas/evas_smart.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/libraries/evas/src/lib/canvas/evas_smart.c b/libraries/evas/src/lib/canvas/evas_smart.c new file mode 100644 index 0000000..0cfba05 --- /dev/null +++ b/libraries/evas/src/lib/canvas/evas_smart.c | |||
@@ -0,0 +1,266 @@ | |||
1 | #include "evas_common.h" | ||
2 | #include "evas_private.h" | ||
3 | |||
4 | |||
5 | static void _evas_smart_class_callbacks_create(Evas_Smart *s); | ||
6 | |||
7 | /* all public */ | ||
8 | |||
9 | EAPI void | ||
10 | evas_smart_free(Evas_Smart *s) | ||
11 | { | ||
12 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
13 | return; | ||
14 | MAGIC_CHECK_END(); | ||
15 | s->delete_me = 1; | ||
16 | if (s->usage > 0) return; | ||
17 | if (s->class_allocated) free((void *)s->smart_class); | ||
18 | free(s->callbacks.array); | ||
19 | free(s); | ||
20 | } | ||
21 | |||
22 | EAPI Evas_Smart * | ||
23 | evas_smart_class_new(const Evas_Smart_Class *sc) | ||
24 | { | ||
25 | Evas_Smart *s; | ||
26 | |||
27 | if (!sc) return NULL; | ||
28 | |||
29 | /* api does not match abi! for now refuse as we only have 1 version */ | ||
30 | if (sc->version != EVAS_SMART_CLASS_VERSION) return NULL; | ||
31 | |||
32 | s = evas_mem_calloc(sizeof(Evas_Smart)); | ||
33 | if (!s) return NULL; | ||
34 | |||
35 | s->magic = MAGIC_SMART; | ||
36 | |||
37 | s->smart_class = sc; | ||
38 | _evas_smart_class_callbacks_create(s); | ||
39 | |||
40 | return s; | ||
41 | } | ||
42 | |||
43 | EAPI const Evas_Smart_Class * | ||
44 | evas_smart_class_get(const Evas_Smart *s) | ||
45 | { | ||
46 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
47 | return NULL; | ||
48 | MAGIC_CHECK_END(); | ||
49 | return s->smart_class; | ||
50 | } | ||
51 | |||
52 | EAPI void * | ||
53 | evas_smart_data_get(const Evas_Smart *s) | ||
54 | { | ||
55 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
56 | return NULL; | ||
57 | MAGIC_CHECK_END(); | ||
58 | return (void *)s->smart_class->data; | ||
59 | } | ||
60 | |||
61 | EAPI const Evas_Smart_Cb_Description ** | ||
62 | evas_smart_callbacks_descriptions_get(const Evas_Smart *s, unsigned int *count) | ||
63 | { | ||
64 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
65 | if (count) *count = 0; | ||
66 | return NULL; | ||
67 | MAGIC_CHECK_END(); | ||
68 | |||
69 | if (count) *count = s->callbacks.size; | ||
70 | return s->callbacks.array; | ||
71 | } | ||
72 | |||
73 | EAPI const Evas_Smart_Cb_Description * | ||
74 | evas_smart_callback_description_find(const Evas_Smart *s, const char *name) | ||
75 | { | ||
76 | if (!name) return NULL; | ||
77 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
78 | return NULL; | ||
79 | MAGIC_CHECK_END(); | ||
80 | return evas_smart_cb_description_find(&s->callbacks, name); | ||
81 | } | ||
82 | |||
83 | EAPI Eina_Bool | ||
84 | evas_smart_class_inherit_full(Evas_Smart_Class *sc, const Evas_Smart_Class *parent_sc, unsigned int parent_sc_size) | ||
85 | { | ||
86 | unsigned int off; | ||
87 | |||
88 | /* api does not match abi! for now refuse as we only have 1 version */ | ||
89 | if (parent_sc->version != EVAS_SMART_CLASS_VERSION) return EINA_FALSE; | ||
90 | |||
91 | #define _CP(m) sc->m = parent_sc->m | ||
92 | _CP(add); | ||
93 | _CP(del); | ||
94 | _CP(move); | ||
95 | _CP(resize); | ||
96 | _CP(show); | ||
97 | _CP(hide); | ||
98 | _CP(color_set); | ||
99 | _CP(clip_set); | ||
100 | _CP(clip_unset); | ||
101 | _CP(calculate); | ||
102 | _CP(member_add); | ||
103 | _CP(member_del); | ||
104 | #undef _CP | ||
105 | |||
106 | sc->parent = parent_sc; | ||
107 | |||
108 | off = sizeof(Evas_Smart_Class); | ||
109 | if (parent_sc_size == off) return EINA_TRUE; | ||
110 | |||
111 | memcpy(((char *)sc) + off, ((char *)parent_sc) + off, parent_sc_size - off); | ||
112 | return EINA_TRUE; | ||
113 | } | ||
114 | |||
115 | EAPI int | ||
116 | evas_smart_usage_get(const Evas_Smart *s) | ||
117 | { | ||
118 | MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART); | ||
119 | return 0; | ||
120 | MAGIC_CHECK_END(); | ||
121 | return s->usage; | ||
122 | } | ||
123 | |||
124 | |||
125 | /* internal funcs */ | ||
126 | void | ||
127 | evas_object_smart_use(Evas_Smart *s) | ||
128 | { | ||
129 | s->usage++; | ||
130 | } | ||
131 | |||
132 | void | ||
133 | evas_object_smart_unuse(Evas_Smart *s) | ||
134 | { | ||
135 | s->usage--; | ||
136 | if ((s->usage <= 0) && (s->delete_me)) evas_smart_free(s); | ||
137 | } | ||
138 | |||
139 | Eina_Bool | ||
140 | evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size) | ||
141 | { | ||
142 | void *tmp; | ||
143 | |||
144 | if (size == a->size) | ||
145 | return EINA_TRUE; | ||
146 | |||
147 | if (size == EINA_FALSE) | ||
148 | { | ||
149 | free(a->array); | ||
150 | a->array = NULL; | ||
151 | a->size = 0; | ||
152 | return EINA_TRUE; | ||
153 | } | ||
154 | |||
155 | tmp = realloc(a->array, (size + 1) * sizeof(Evas_Smart_Cb_Description *)); | ||
156 | if (tmp) | ||
157 | { | ||
158 | a->array = tmp; | ||
159 | a->size = size; | ||
160 | a->array[size] = NULL; | ||
161 | return EINA_TRUE; | ||
162 | } | ||
163 | else | ||
164 | { | ||
165 | ERR("realloc failed!"); | ||
166 | return EINA_FALSE; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static int | ||
171 | _evas_smart_cb_description_cmp_sort(const void *p1, const void *p2) | ||
172 | { | ||
173 | const Evas_Smart_Cb_Description **a = (const Evas_Smart_Cb_Description **)p1; | ||
174 | const Evas_Smart_Cb_Description **b = (const Evas_Smart_Cb_Description **)p2; | ||
175 | return strcmp((*a)->name, (*b)->name); | ||
176 | } | ||
177 | |||
178 | void | ||
179 | evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a) | ||
180 | { | ||
181 | unsigned int i, j; | ||
182 | |||
183 | if (!a) | ||
184 | { | ||
185 | ERR("no array to fix!"); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | qsort(a->array, a->size, sizeof(Evas_Smart_Cb_Description *), | ||
190 | _evas_smart_cb_description_cmp_sort); | ||
191 | |||
192 | DBG("%u callbacks", a->size); | ||
193 | if (a->size) | ||
194 | DBG("%s [type=%s]", a->array[0]->name, a->array[0]->type); | ||
195 | |||
196 | for (i = 0, j = 1; j < a->size; j++) | ||
197 | { | ||
198 | const Evas_Smart_Cb_Description *cur, *prev; | ||
199 | |||
200 | cur = a->array[j]; | ||
201 | prev = a->array[i]; | ||
202 | |||
203 | DBG("%s [type=%s]", cur->name, cur->type); | ||
204 | |||
205 | if (strcmp(cur->name, prev->name) != 0) | ||
206 | { | ||
207 | i++; | ||
208 | if (i != j) | ||
209 | a->array[i] = a->array[j]; | ||
210 | } | ||
211 | else | ||
212 | { | ||
213 | if (strcmp(cur->type, prev->type) == 0) | ||
214 | WRN("duplicated smart callback description" | ||
215 | " with name '%s' and type '%s'", cur->name, cur->type); | ||
216 | else | ||
217 | ERR("callback descriptions named '%s' differ" | ||
218 | " in type, keeping '%s', ignoring '%s'", | ||
219 | cur->name, prev->type, cur->type); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | evas_smart_cb_descriptions_resize(a, i + 1); | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | _evas_smart_class_callbacks_create(Evas_Smart *s) | ||
228 | { | ||
229 | const Evas_Smart_Class *sc; | ||
230 | unsigned int n = 0; | ||
231 | |||
232 | for (sc = s->smart_class; sc; sc = sc->parent) | ||
233 | { | ||
234 | const Evas_Smart_Cb_Description *d; | ||
235 | for (d = sc->callbacks; d && d->name; d++) | ||
236 | n++; | ||
237 | } | ||
238 | |||
239 | if (n == 0) return; | ||
240 | if (!evas_smart_cb_descriptions_resize(&s->callbacks, n)) return; | ||
241 | for (n = 0, sc = s->smart_class; sc; sc = sc->parent) | ||
242 | { | ||
243 | const Evas_Smart_Cb_Description *d; | ||
244 | for (d = sc->callbacks; d && d->name; d++) | ||
245 | s->callbacks.array[n++] = d; | ||
246 | } | ||
247 | evas_smart_cb_descriptions_fix(&s->callbacks); | ||
248 | } | ||
249 | |||
250 | static int | ||
251 | _evas_smart_cb_description_cmp_search(const void *p1, const void *p2) | ||
252 | { | ||
253 | const char *name = p1; | ||
254 | const Evas_Smart_Cb_Description **v = (const Evas_Smart_Cb_Description **)p2; | ||
255 | /* speed up string shares searches (same pointers) */ | ||
256 | if (name == (*v)->name) return 0; | ||
257 | return strcmp(name, (*v)->name); | ||
258 | } | ||
259 | |||
260 | const Evas_Smart_Cb_Description * | ||
261 | evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name) | ||
262 | { | ||
263 | if (!a->array) return NULL; | ||
264 | return bsearch(name, a->array, a->size, sizeof(Evas_Smart_Cb_Description *), | ||
265 | _evas_smart_cb_description_cmp_search); | ||
266 | } | ||