1 #include <Elementary.h>
5 static Elm_Theme theme_default =
7 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1
10 static Eina_List *themes = NULL;
13 _elm_theme_clear(Elm_Theme *th)
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);
24 eina_hash_free(th->cache);
29 eina_hash_free(th->cache_data);
30 th->cache_data = NULL;
34 eina_stringshare_del(th->theme);
39 th->ref_theme->referrers =
40 eina_list_remove(th->ref_theme->referrers, th);
41 elm_theme_free(th->ref_theme);
47 _elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
51 if (edje_file_group_exists(f, group))
53 file = eina_stringshare_add(f);
56 eina_hash_add(th->cache, group, file);
64 _elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
67 const char *file = NULL;
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] == '/')))
75 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
76 return _elm_theme_find_try(th, buf, group);
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);
87 _elm_theme_group_file_find(Elm_Theme *th, const char *group)
91 static const char *home = NULL;
92 const char *file = eina_hash_find(th->cache, group);
94 if (file) return file;
97 home = getenv("HOME");
100 EINA_LIST_FOREACH(th->overlay, l, f)
102 file = _elm_theme_theme_element_try(th, home, f, group);
103 if (file) return file;
105 EINA_LIST_FOREACH(th->themes, l, f)
107 file = _elm_theme_theme_element_try(th, home, f, group);
108 if (file) return file;
110 EINA_LIST_FOREACH(th->extension, l, f)
112 file = _elm_theme_theme_element_try(th, home, f, group);
113 if (file) return file;
115 if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
120 _elm_theme_find_data_try(Elm_Theme *th, const char *f, const char *key)
125 data = edje_file_data_get(f, key);
126 t = eina_stringshare_add(data);
130 eina_hash_add(th->cache, key, t);
137 _elm_theme_theme_data_try(Elm_Theme *th, const char *home, const char *f, const char *key)
140 const char *data = NULL;
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] == '/')))
148 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
149 return _elm_theme_find_try(th, buf, key);
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);
160 _elm_theme_data_find(Elm_Theme *th, const char *key)
164 static const char *home = NULL;
165 const char *data = eina_hash_find(th->cache_data, key);
167 if (data) return data;
170 home = getenv("HOME");
171 if (!home) home = "";
173 EINA_LIST_FOREACH(th->overlay, l, f)
175 data = _elm_theme_theme_data_try(th, home, f, key);
176 if (data) return data;
178 EINA_LIST_FOREACH(th->themes, l, f)
180 data = _elm_theme_theme_data_try(th, home, f, key);
181 if (data) return data;
183 EINA_LIST_FOREACH(th->extension, l, f)
185 data = _elm_theme_theme_data_try(th, home, f, key);
186 if (data) return data;
188 if (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key);
193 _elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style)
195 Elm_Theme *th = NULL;
196 if (parent) th = elm_widget_theme_get(parent);
197 return _elm_theme_set(th, o, clas, group, style);
201 _elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style)
203 Elm_Theme *th = NULL;
204 if (parent) th = elm_widget_theme_get(parent);
205 return _elm_theme_icon_set(th, o, group, style);
209 _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style)
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);
221 ok = edje_object_file_set(o, file, buf2);
222 if (ok) return EINA_TRUE;
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)));
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);
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)));
238 _elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style)
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);
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;
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);
262 _elm_theme_parse(Elm_Theme *th, const char *theme)
264 Eina_List *names = NULL;
267 if (!th) th = &(theme_default);
274 if ((*pe == ':') || (!*pe))
275 { // p -> pe == 'name:'
278 char *n = malloc(pe - p + 1);
283 strncpy(n, p, pe - p);
285 nn = eina_stringshare_add(n);
286 if (nn) names = eina_list_append(names, nn);
298 p = eina_list_data_get(eina_list_last(names));
299 if ((!p) || ((p) && (strcmp(p, "default"))))
301 p = eina_stringshare_add("default");
302 if (p) names = eina_list_append(names, p);
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));
309 EINA_LIST_FREE(th->themes, p) eina_stringshare_del(p);
316 _elm_theme_shutdown(void)
318 _elm_theme_clear(&(theme_default));
324 Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
325 if (!th) return NULL;
327 th->themes = eina_list_append(th->themes, eina_stringshare_add("default"));
328 themes = eina_list_append(themes, th);
333 elm_theme_free(Elm_Theme *th)
335 EINA_SAFETY_ON_NULL_RETURN(th);
339 _elm_theme_clear(th);
340 themes = eina_list_remove(themes, th);
346 elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
351 if (!th) th = &(theme_default);
352 if (!thdst) thdst = &(theme_default);
353 _elm_theme_clear(thdst);
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++;
361 EINA_LIST_FOREACH(th->overlay, l, f)
363 const char *s = eina_stringshare_add(f);
364 if (s) thdst->overlay = eina_list_append(thdst->overlay, s);
366 EINA_LIST_FOREACH(th->themes, l, f)
368 const char *s = eina_stringshare_add(f);
369 if (s) thdst->themes = eina_list_append(thdst->themes, s);
371 EINA_LIST_FOREACH(th->extension, l, f)
373 const char *s = eina_stringshare_add(f);
374 if (s) thdst->extension = eina_list_append(thdst->extension, s);
376 if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
377 elm_theme_flush(thdst);
381 elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref)
383 if (!th) th = &(theme_default);
384 if (!thref) thref = &(theme_default);
385 if (th->ref_theme == thref) return;
386 _elm_theme_clear(th);
389 thref->referrers = eina_list_append(thref->referrers, th);
392 th->ref_theme = thref;
397 elm_theme_ref_get(Elm_Theme *th)
399 if (!th) th = &(theme_default);
400 return th->ref_theme;
404 elm_theme_default_get(void)
406 return &theme_default;
410 elm_theme_overlay_add(Elm_Theme *th, const char *item)
412 const char *f = eina_stringshare_add(item);
414 if (!th) th = &(theme_default);
415 if (f) th->overlay = eina_list_prepend(th->overlay, f);
420 elm_theme_overlay_del(Elm_Theme *th, const char *item)
425 if (!th) th = &(theme_default);
426 s = eina_stringshare_add(item);
427 EINA_LIST_FOREACH(th->overlay, l, f)
430 eina_stringshare_del(f);
431 th->overlay = eina_list_remove_list(th->overlay, (Eina_List *)l);
434 eina_stringshare_del(s);
439 elm_theme_extension_add(Elm_Theme *th, const char *item)
441 const char *f = eina_stringshare_add(item);
443 if (!th) th = &(theme_default);
444 if (f) th->extension = eina_list_append(th->extension, f);
449 elm_theme_extension_del(Elm_Theme *th, const char *item)
454 if (!th) th = &(theme_default);
455 s = eina_stringshare_add(item);
456 EINA_LIST_FOREACH(th->extension, l, f)
459 eina_stringshare_del(f);
460 th->extension = eina_list_remove_list(th->extension, (Eina_List *)l);
463 eina_stringshare_del(s);
468 elm_theme_set(Elm_Theme *th, const char *theme)
470 if (!th) th = &(theme_default);
471 _elm_theme_parse(th, theme);
474 eina_stringshare_del(th->theme);
481 elm_theme_get(Elm_Theme *th)
483 if (!th) th = &(theme_default);
492 EINA_LIST_FOREACH(th->themes, l, f)
495 if (l->next) len += 1;
497 tmp = alloca(len + 1);
499 EINA_LIST_FOREACH(th->themes, l, f)
502 if (l->next) strcat(tmp, ":");
504 th->theme = eina_stringshare_add(tmp);
509 EAPI const Eina_List *
510 elm_theme_list_get(const Elm_Theme *th)
512 if (!th) th = &(theme_default);
517 elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path)
519 static const char *home = NULL;
524 if (in_search_path) *in_search_path = EINA_FALSE;
530 home = getenv("HOME");
531 if (!home) home = "";
534 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
535 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
536 ((isalpha(f[0])) && (f[1] == ':')))
538 if (in_search_path) *in_search_path = EINA_FALSE;
541 else if (((f[0] == '~') && (f[1] == '/')))
543 if (in_search_path) *in_search_path = EINA_FALSE;
544 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
547 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
548 if (ecore_file_exists(buf))
550 if (in_search_path) *in_search_path = EINA_TRUE;
554 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
555 if (ecore_file_exists(buf))
557 if (in_search_path) *in_search_path = EINA_TRUE;
561 if (in_search_path) *in_search_path = EINA_FALSE;
566 elm_theme_flush(Elm_Theme *th)
568 if (!th) th = &(theme_default);
569 if (th->cache) eina_hash_free(th->cache);
570 th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
571 if (th->cache_data) eina_hash_free(th->cache_data);
572 th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
573 _elm_win_rescale(th, EINA_TRUE);
574 _elm_ews_wm_rescale(th, EINA_TRUE);
580 EINA_LIST_FOREACH(th->referrers, l, th2) elm_theme_flush(th2);
585 elm_theme_full_flush(void)
590 EINA_LIST_FOREACH(themes, l, th)
594 elm_theme_flush(&(theme_default));
597 EINA_DEPRECATED EAPI void
598 elm_theme_all_set(const char *theme)
600 eina_stringshare_replace(&_elm_config->theme, theme);
601 elm_theme_set(NULL, theme);
602 elm_config_all_flush();
606 elm_theme_name_available_list_new(void)
608 Eina_List *list = NULL;
610 char buf[PATH_MAX], *file, *s, *th;
611 static const char *home = NULL;
615 home = getenv("HOME");
616 if (!home) home = "";
619 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes", home);
620 dir = ecore_file_ls(buf);
621 EINA_LIST_FREE(dir, file)
623 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s", home, file);
624 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
626 s = strchr(file, '.');
627 if ((s) && (!strcasecmp(s, ".edj")))
632 list = eina_list_append(list, th);
638 snprintf(buf, sizeof(buf), "%s/themes", _elm_data_dir);
639 dir = ecore_file_ls(buf);
640 EINA_LIST_FREE(dir, file)
642 snprintf(buf, sizeof(buf), "%s/themes/%s", _elm_data_dir, file);
643 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
645 s = strchr(file, '.');
646 if ((s) && (!strcasecmp(s, ".edj")))
654 EINA_LIST_FOREACH(list, l, s)
663 else list = eina_list_append(list, th);
668 list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcasecmp));
673 elm_theme_name_available_list_free(Eina_List *list)
676 EINA_LIST_FREE(list, s) free(s);
680 elm_object_theme_set(Evas_Object *obj, Elm_Theme *th)
682 EINA_SAFETY_ON_NULL_RETURN(obj);
683 elm_widget_theme_set(obj, th);
687 elm_object_theme_get(const Evas_Object *obj)
689 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
690 return elm_widget_theme_get(obj);
694 elm_theme_data_get(Elm_Theme *th, const char *key)
696 if (!th) th = &(theme_default);
697 return _elm_theme_data_find(th, key);