aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/elementary/src/lib/elm_theme.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-04-22 09:20:32 +1000
committerDavid Walter Seikel2012-04-22 09:20:32 +1000
commit3ad3455551be0d7859ecb02290376206d5e66498 (patch)
tree497917e12b4d7f458dff9765d9b53f64c4e03fc3 /libraries/elementary/src/lib/elm_theme.c
parentUpdate EFL to latest beta. (diff)
downloadSledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.zip
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.gz
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.bz2
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.xz
And actually include new files, plus elementary libraries.
Diffstat (limited to 'libraries/elementary/src/lib/elm_theme.c')
-rw-r--r--libraries/elementary/src/lib/elm_theme.c706
1 files changed, 706 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/elm_theme.c b/libraries/elementary/src/lib/elm_theme.c
new file mode 100644
index 0000000..a0caea2
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_theme.c
@@ -0,0 +1,706 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4
5static Elm_Theme theme_default =
6{
7 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1
8};
9
10static Eina_List *themes = NULL;
11
12static void
13_elm_theme_clear(Elm_Theme *th)
14{
15 const char *p;
16 EINA_LIST_FREE(th->themes, p)
17 eina_stringshare_del(p);
18 EINA_LIST_FREE(th->overlay, p)
19 eina_stringshare_del(p);
20 EINA_LIST_FREE(th->extension, p)
21 eina_stringshare_del(p);
22 if (th->cache)
23 {
24 eina_hash_free(th->cache);
25 th->cache = NULL;
26 }
27 if (th->cache_data)
28 {
29 eina_hash_free(th->cache_data);
30 th->cache_data = NULL;
31 }
32 if (th->theme)
33 {
34 eina_stringshare_del(th->theme);
35 th->theme = NULL;
36 }
37 if (th->ref_theme)
38 {
39 th->ref_theme->referrers =
40 eina_list_remove(th->ref_theme->referrers, th);
41 elm_theme_free(th->ref_theme);
42 th->ref_theme = NULL;
43 }
44}
45
46static const char *
47_elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
48{
49 const char *file;
50
51 if (edje_file_group_exists(f, group))
52 {
53 file = eina_stringshare_add(f);
54 if (file)
55 {
56 eina_hash_add(th->cache, group, file);
57 return file;
58 }
59 }
60 return NULL;
61}
62
63static const char *
64_elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
65{
66 char buf[PATH_MAX];
67 const char *file = NULL;
68
69 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
70 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
71 ((isalpha(f[0])) && (f[1] == ':')))
72 return _elm_theme_find_try(th, f, group);
73 else if (((f[0] == '~') && (f[1] == '/')))
74 {
75 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
76 return _elm_theme_find_try(th, buf, group);
77 }
78 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
79 file = _elm_theme_find_try(th, buf, group);
80 if (file) return file;
81 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
82 file = _elm_theme_find_try(th, buf, group);
83 return file;
84}
85
86static const char *
87_elm_theme_group_file_find(Elm_Theme *th, const char *group)
88{
89 const Eina_List *l;
90 const char *f;
91 static const char *home = NULL;
92 const char *file = eina_hash_find(th->cache, group);
93
94 if (file) return file;
95 if (!home)
96 {
97 home = getenv("HOME");
98 if (!home) home = "";
99 }
100 EINA_LIST_FOREACH(th->overlay, l, f)
101 {
102 file = _elm_theme_theme_element_try(th, home, f, group);
103 if (file) return file;
104 }
105 EINA_LIST_FOREACH(th->themes, l, f)
106 {
107 file = _elm_theme_theme_element_try(th, home, f, group);
108 if (file) return file;
109 }
110 EINA_LIST_FOREACH(th->extension, l, f)
111 {
112 file = _elm_theme_theme_element_try(th, home, f, group);
113 if (file) return file;
114 }
115 if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
116 return NULL;
117}
118
119static const char *
120_elm_theme_find_data_try(Elm_Theme *th, const char *f, const char *key)
121{
122 char *data;
123 const char *t;
124
125 data = edje_file_data_get(f, key);
126 t = eina_stringshare_add(data);
127 free(data);
128 if (t)
129 {
130 eina_hash_add(th->cache, key, t);
131 return t;
132 }
133 return NULL;
134}
135
136static const char *
137_elm_theme_theme_data_try(Elm_Theme *th, const char *home, const char *f, const char *key)
138{
139 char buf[PATH_MAX];
140 const char *data = NULL;
141
142 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
143 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
144 ((isalpha(f[0])) && (f[1] == ':')))
145 return _elm_theme_find_data_try(th, f, key);
146 else if (((f[0] == '~') && (f[1] == '/')))
147 {
148 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
149 return _elm_theme_find_try(th, buf, key);
150 }
151 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
152 data = _elm_theme_find_data_try(th, buf, key);
153 if (data) return data;
154 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
155 data = _elm_theme_find_data_try(th, buf, key);
156 return data;
157}
158
159static const char *
160_elm_theme_data_find(Elm_Theme *th, const char *key)
161{
162 const Eina_List *l;
163 const char *f;
164 static const char *home = NULL;
165 const char *data = eina_hash_find(th->cache_data, key);
166
167 if (data) return data;
168 if (!home)
169 {
170 home = getenv("HOME");
171 if (!home) home = "";
172 }
173 EINA_LIST_FOREACH(th->overlay, l, f)
174 {
175 data = _elm_theme_theme_data_try(th, home, f, key);
176 if (data) return data;
177 }
178 EINA_LIST_FOREACH(th->themes, l, f)
179 {
180 data = _elm_theme_theme_data_try(th, home, f, key);
181 if (data) return data;
182 }
183 EINA_LIST_FOREACH(th->extension, l, f)
184 {
185 data = _elm_theme_theme_data_try(th, home, f, key);
186 if (data) return data;
187 }
188 if (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key);
189 return NULL;
190}
191
192Eina_Bool
193_elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style)
194{
195 Elm_Theme *th = NULL;
196 if (parent) th = elm_widget_theme_get(parent);
197 return _elm_theme_set(th, o, clas, group, style);
198}
199
200Eina_Bool
201_elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style)
202{
203 Elm_Theme *th = NULL;
204 if (parent) th = elm_widget_theme_get(parent);
205 return _elm_theme_icon_set(th, o, group, style);
206}
207
208Eina_Bool
209_elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style)
210{
211 const char *file;
212 char buf2[1024];
213 Eina_Bool ok;
214
215 if ((!clas) || (!group) || (!style)) return EINA_FALSE;
216 if (!th) th = &(theme_default);
217 snprintf(buf2, sizeof(buf2), "elm/%s/%s/%s", clas, group, style);
218 file = _elm_theme_group_file_find(th, buf2);
219 if (file)
220 {
221 ok = edje_object_file_set(o, file, buf2);
222 if (ok) return EINA_TRUE;
223 else
224 DBG("could not set theme group '%s' from file '%s': %s",
225 buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
226 }
227 snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group);
228 file = _elm_theme_group_file_find(th, buf2);
229 if (!file) return EINA_FALSE;
230 ok = edje_object_file_set(o, file, buf2);
231 if (!ok)
232 DBG("could not set theme group '%s' from file '%s': %s",
233 buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
234 return ok;
235}
236
237Eina_Bool
238_elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style)
239{
240 const char *file;
241 char buf2[1024];
242 int w, h;
243
244 if (!th) th = &(theme_default);
245 snprintf(buf2, sizeof(buf2), "elm/icon/%s/%s", group, style);
246 file = _elm_theme_group_file_find(th, buf2);
247 if (file)
248 {
249 _els_smart_icon_file_edje_set(o, file, buf2);
250 _els_smart_icon_size_get(o, &w, &h);
251 if (w > 0) return EINA_TRUE;
252 }
253 snprintf(buf2, sizeof(buf2), "elm/icon/%s/default", group);
254 file = _elm_theme_group_file_find(th, buf2);
255 if (!file) return EINA_FALSE;
256 _els_smart_icon_file_edje_set(o, file, buf2);
257 _els_smart_icon_size_get(o, &w, &h);
258 return (w > 0);
259}
260
261Eina_Bool
262_elm_theme_parse(Elm_Theme *th, const char *theme)
263{
264 Eina_List *names = NULL;
265 const char *p, *pe;
266
267 if (!th) th = &(theme_default);
268 if (theme)
269 {
270 p = theme;
271 pe = p;
272 for (;;)
273 {
274 if ((*pe == ':') || (!*pe))
275 { // p -> pe == 'name:'
276 if (pe > p)
277 {
278 char *n = malloc(pe - p + 1);
279 if (n)
280 {
281 const char *nn;
282
283 strncpy(n, p, pe - p);
284 n[pe - p] = 0;
285 nn = eina_stringshare_add(n);
286 if (nn) names = eina_list_append(names, nn);
287 free(n);
288 }
289 }
290 if (!*pe) break;
291 p = pe + 1;
292 pe = p;
293 }
294 else
295 pe++;
296 }
297 }
298 p = eina_list_data_get(eina_list_last(names));
299 if ((!p) || ((p) && (strcmp(p, "default"))))
300 {
301 p = eina_stringshare_add("default");
302 if (p) names = eina_list_append(names, p);
303 }
304 if (th->cache) eina_hash_free(th->cache);
305 th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
306 if (th->cache_data) eina_hash_free(th->cache_data);
307 th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
308
309 EINA_LIST_FREE(th->themes, p) eina_stringshare_del(p);
310
311 th->themes = names;
312 return EINA_TRUE;
313}
314
315void
316_elm_theme_shutdown(void)
317{
318 _elm_theme_clear(&(theme_default));
319}
320
321EAPI Elm_Theme *
322elm_theme_new(void)
323{
324 Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
325 if (!th) return NULL;
326 th->ref = 1;
327 th->themes = eina_list_append(th->themes, eina_stringshare_add("default"));
328 themes = eina_list_append(themes, th);
329 return th;
330}
331
332EAPI void
333elm_theme_free(Elm_Theme *th)
334{
335 EINA_SAFETY_ON_NULL_RETURN(th);
336 th->ref--;
337 if (th->ref < 1)
338 {
339 _elm_theme_clear(th);
340 themes = eina_list_remove(themes, th);
341 free(th);
342 }
343}
344
345EAPI void
346elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
347{
348 const Eina_List *l;
349 const char *f;
350
351 if (!th) th = &(theme_default);
352 if (!thdst) thdst = &(theme_default);
353 _elm_theme_clear(thdst);
354 if (th->ref_theme)
355 {
356 thdst->ref_theme = th->ref_theme;
357 thdst->ref_theme->referrers =
358 eina_list_append(thdst->ref_theme->referrers, thdst);
359 thdst->ref_theme->ref++;
360 }
361 EINA_LIST_FOREACH(th->overlay, l, f)
362 {
363 const char *s = eina_stringshare_add(f);
364 if (s) thdst->overlay = eina_list_append(thdst->overlay, s);
365 }
366 EINA_LIST_FOREACH(th->themes, l, f)
367 {
368 const char *s = eina_stringshare_add(f);
369 if (s) thdst->themes = eina_list_append(thdst->themes, s);
370 }
371 EINA_LIST_FOREACH(th->extension, l, f)
372 {
373 const char *s = eina_stringshare_add(f);
374 if (s) thdst->extension = eina_list_append(thdst->extension, s);
375 }
376 if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
377 elm_theme_flush(thdst);
378}
379
380EAPI void
381elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref)
382{
383 if (!th) th = &(theme_default);
384 if (!thref) thref = &(theme_default);
385 if (th->ref_theme == thref) return;
386 _elm_theme_clear(th);
387 if (thref)
388 {
389 thref->referrers = eina_list_append(thref->referrers, th);
390 thref->ref++;
391 }
392 th->ref_theme = thref;
393 elm_theme_flush(th);
394}
395
396EAPI Elm_Theme *
397elm_theme_ref_get(Elm_Theme *th)
398{
399 if (!th) th = &(theme_default);
400 return th->ref_theme;
401}
402
403EAPI Elm_Theme *
404elm_theme_default_get(void)
405{
406 return &theme_default;
407}
408
409EAPI void
410elm_theme_overlay_add(Elm_Theme *th, const char *item)
411{
412 const char *f = eina_stringshare_add(item);
413
414 if (!th) th = &(theme_default);
415 if (f) th->overlay = eina_list_prepend(th->overlay, f);
416 elm_theme_flush(th);
417}
418
419EAPI void
420elm_theme_overlay_del(Elm_Theme *th, const char *item)
421{
422 const Eina_List *l;
423 const char *f, *s;
424
425 if (!th) th = &(theme_default);
426 s = eina_stringshare_add(item);
427 EINA_LIST_FOREACH(th->overlay, l, f)
428 if (f == s)
429 {
430 eina_stringshare_del(f);
431 th->overlay = eina_list_remove_list(th->overlay, (Eina_List *)l);
432 break;
433 }
434 eina_stringshare_del(s);
435 elm_theme_flush(th);
436}
437
438EAPI const Eina_List *
439elm_theme_overlay_list_get(const Elm_Theme *th)
440{
441 if (!th) th = &(theme_default);
442 return th->overlay;
443}
444
445EAPI void
446elm_theme_extension_add(Elm_Theme *th, const char *item)
447{
448 const char *f = eina_stringshare_add(item);
449
450 if (!th) th = &(theme_default);
451 if (f) th->extension = eina_list_append(th->extension, f);
452 elm_theme_flush(th);
453}
454
455EAPI void
456elm_theme_extension_del(Elm_Theme *th, const char *item)
457{
458 const Eina_List *l;
459 const char *f, *s;
460
461 if (!th) th = &(theme_default);
462 s = eina_stringshare_add(item);
463 EINA_LIST_FOREACH(th->extension, l, f)
464 if (f == s)
465 {
466 eina_stringshare_del(f);
467 th->extension = eina_list_remove_list(th->extension, (Eina_List *)l);
468 break;
469 }
470 eina_stringshare_del(s);
471 elm_theme_flush(th);
472}
473
474EAPI const Eina_List *
475elm_theme_extension_list_get(const Elm_Theme *th)
476{
477 if (!th) th = &(theme_default);
478 return th->extension;
479}
480
481EAPI void
482elm_theme_set(Elm_Theme *th, const char *theme)
483{
484 if (!th) th = &(theme_default);
485 _elm_theme_parse(th, theme);
486 if (th->theme)
487 {
488 eina_stringshare_del(th->theme);
489 th->theme = NULL;
490 }
491 elm_theme_flush(th);
492 if (th == &(theme_default))
493 eina_stringshare_replace(&_elm_config->theme, theme);
494}
495
496EAPI const char *
497elm_theme_get(Elm_Theme *th)
498{
499 if (!th) th = &(theme_default);
500 if (!th->theme)
501 {
502 Eina_List *l;
503 const char *f;
504 char *tmp;
505 int len;
506
507 len = 0;
508 EINA_LIST_FOREACH(th->themes, l, f)
509 {
510 len += strlen(f);
511 if (l->next) len += 1;
512 }
513 tmp = alloca(len + 1);
514 tmp[0] = 0;
515 EINA_LIST_FOREACH(th->themes, l, f)
516 {
517 strcat(tmp, f);
518 if (l->next) strcat(tmp, ":");
519 }
520 th->theme = eina_stringshare_add(tmp);
521 }
522 return th->theme;
523}
524
525EAPI const Eina_List *
526elm_theme_list_get(const Elm_Theme *th)
527{
528 if (!th) th = &(theme_default);
529 return th->themes;
530}
531
532EAPI char *
533elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path)
534{
535 static const char *home = NULL;
536 char buf[PATH_MAX];
537
538 if (!f)
539 {
540 if (in_search_path) *in_search_path = EINA_FALSE;
541 return NULL;
542 }
543
544 if (!home)
545 {
546 home = getenv("HOME");
547 if (!home) home = "";
548 }
549
550 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
551 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
552 ((isalpha(f[0])) && (f[1] == ':')))
553 {
554 if (in_search_path) *in_search_path = EINA_FALSE;
555 return strdup(f);
556 }
557 else if (((f[0] == '~') && (f[1] == '/')))
558 {
559 if (in_search_path) *in_search_path = EINA_FALSE;
560 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
561 return strdup(buf);
562 }
563 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
564 if (ecore_file_exists(buf))
565 {
566 if (in_search_path) *in_search_path = EINA_TRUE;
567 return strdup(buf);
568 }
569
570 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
571 if (ecore_file_exists(buf))
572 {
573 if (in_search_path) *in_search_path = EINA_TRUE;
574 return strdup(buf);
575 }
576
577 if (in_search_path) *in_search_path = EINA_FALSE;
578 return NULL;
579}
580
581EAPI void
582elm_theme_flush(Elm_Theme *th)
583{
584 if (!th) th = &(theme_default);
585 if (th->cache) eina_hash_free(th->cache);
586 th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
587 if (th->cache_data) eina_hash_free(th->cache_data);
588 th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
589 _elm_win_rescale(th, EINA_TRUE);
590 _elm_ews_wm_rescale(th, EINA_TRUE);
591 if (th->referrers)
592 {
593 Eina_List *l;
594 Elm_Theme *th2;
595
596 EINA_LIST_FOREACH(th->referrers, l, th2) elm_theme_flush(th2);
597 }
598}
599
600EAPI void
601elm_theme_full_flush(void)
602{
603 Eina_List *l;
604 Elm_Theme *th;
605
606 EINA_LIST_FOREACH(themes, l, th)
607 {
608 elm_theme_flush(th);
609 }
610 elm_theme_flush(&(theme_default));
611}
612
613EAPI Eina_List *
614elm_theme_name_available_list_new(void)
615{
616 Eina_List *list = NULL;
617 Eina_List *dir, *l;
618 char buf[PATH_MAX], *file, *s, *th;
619 static const char *home = NULL;
620
621 if (!home)
622 {
623 home = getenv("HOME");
624 if (!home) home = "";
625 }
626
627 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes", home);
628 dir = ecore_file_ls(buf);
629 EINA_LIST_FREE(dir, file)
630 {
631 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s", home, file);
632 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
633 {
634 s = strchr(file, '.');
635 if ((s) && (!strcasecmp(s, ".edj")))
636 {
637 th = strdup(file);
638 s = strchr(th, '.');
639 *s = 0;
640 list = eina_list_append(list, th);
641 }
642 }
643 free(file);
644 }
645
646 snprintf(buf, sizeof(buf), "%s/themes", _elm_data_dir);
647 dir = ecore_file_ls(buf);
648 EINA_LIST_FREE(dir, file)
649 {
650 snprintf(buf, sizeof(buf), "%s/themes/%s", _elm_data_dir, file);
651 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
652 {
653 s = strchr(file, '.');
654 if ((s) && (!strcasecmp(s, ".edj")))
655 {
656 int dupp;
657
658 th = strdup(file);
659 s = strchr(th, '.');
660 *s = 0;
661 dupp = 0;
662 EINA_LIST_FOREACH(list, l, s)
663 {
664 if (!strcmp(s, th))
665 {
666 dupp = 1;
667 break;
668 }
669 }
670 if (dupp) free(th);
671 else list = eina_list_append(list, th);
672 }
673 }
674 free(file);
675 }
676 list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcasecmp));
677 return list;
678}
679
680EAPI void
681elm_theme_name_available_list_free(Eina_List *list)
682{
683 char *s;
684 EINA_LIST_FREE(list, s) free(s);
685}
686
687EAPI void
688elm_object_theme_set(Evas_Object *obj, Elm_Theme *th)
689{
690 EINA_SAFETY_ON_NULL_RETURN(obj);
691 elm_widget_theme_set(obj, th);
692}
693
694EAPI Elm_Theme *
695elm_object_theme_get(const Evas_Object *obj)
696{
697 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
698 return elm_widget_theme_get(obj);
699}
700
701EAPI const char *
702elm_theme_data_get(Elm_Theme *th, const char *key)
703{
704 if (!th) th = &(theme_default);
705 return _elm_theme_data_find(th, key);
706}