theme: introduce theme overlay/extension matching

after this commit, efl base themes should now specify:

data.item: "efl_theme_base" "theme_name";

and overlays/extensions which match a given theme should use:

data.item: "efl_theme_match" "theme_name";

this will cause overlays and extensions with the data.item to only
be loaded when the corresponding theme is in use. note that this
should not be specified for theme-independent overlays/extensions
as it will completely block loading of themes
This commit is contained in:
Mike Blumenkrantz 2018-02-27 15:42:58 -05:00
parent 7353fc1cb8
commit 07d0fb03db
3 changed files with 36 additions and 7 deletions

View File

@ -5,6 +5,7 @@ externals.external: "elm";
// theme api version. from 1.10 on we will check version to avoid // theme api version. from 1.10 on we will check version to avoid
// compat issues // compat issues
data.item: "version" "119"; data.item: "version" "119";
data.item: "efl_theme_base" "dark";
collections { collections {
#include "fonts.edc" #include "fonts.edc"

View File

@ -125,6 +125,8 @@ typedef struct Elm_Theme_File
*/ */
Eina_Stringshare *item; Eina_Stringshare *item;
Eina_File *handle; Eina_File *handle;
Eina_Stringshare *base_theme; // data.item: efl_theme_base name
Eina_Stringshare *match_theme; // data.item: efl_theme_match name
} Elm_Theme_File; } Elm_Theme_File;
struct _Elm_Theme struct _Elm_Theme

View File

@ -16,12 +16,25 @@ static Elm_Theme theme_default =
static Eina_List *themes = NULL; static Eina_List *themes = NULL;
static Eina_File * static Eina_File *
_elm_theme_find_try(Elm_Theme *th, Eina_File *f, const char *group) _elm_theme_find_try(Elm_Theme *th, Elm_Theme_File *etf, const char *group)
{ {
if (edje_mmap_group_exists(f, group)) if (edje_mmap_group_exists(etf->handle, group))
{ {
eina_hash_add(th->cache, group, eina_file_dup(f)); if (etf->match_theme) // overlay or extension
return f; {
Elm_Theme_File *base_etf;
Eina_Bool found = EINA_FALSE;
EINA_INLIST_FOREACH(th->themes, base_etf)
{
if (base_etf->base_theme != etf->match_theme) continue;
found = EINA_TRUE;
break;
}
if (!found) return NULL;
}
eina_hash_add(th->cache, group, eina_file_dup(etf->handle));
return etf->handle;
} }
return NULL; return NULL;
} }
@ -34,6 +47,7 @@ _elm_theme_item_finalize(Eina_Inlist **files,
Eina_Bool istheme) Eina_Bool istheme)
{ {
Elm_Theme_File *etf; Elm_Theme_File *etf;
char *name;
/* Theme version history: /* Theme version history:
* <110: legacy, had no version tag * <110: legacy, had no version tag
* 110: first supported version * 110: first supported version
@ -60,6 +74,17 @@ _elm_theme_item_finalize(Eina_Inlist **files,
EINA_SAFETY_ON_NULL_RETURN(etf); EINA_SAFETY_ON_NULL_RETURN(etf);
etf->item = eina_stringshare_add(item); etf->item = eina_stringshare_add(item);
etf->handle = f; etf->handle = f;
if (istheme)
{
name = edje_mmap_data_get(f, "efl_theme_base");
etf->base_theme = eina_stringshare_add(name);
}
else
{
name = edje_mmap_data_get(f, "efl_theme_match");
etf->match_theme = eina_stringshare_add(name);
}
free(name);
if (prepend) if (prepend)
{ {
*files = eina_inlist_prepend(*files, EINA_INLIST_GET(etf)); *files = eina_inlist_prepend(*files, EINA_INLIST_GET(etf));
@ -163,6 +188,7 @@ _elm_theme_file_clean(Eina_Inlist **files)
eina_stringshare_del(etf->item); eina_stringshare_del(etf->item);
eina_file_close(etf->handle); eina_file_close(etf->handle);
eina_stringshare_del(etf->match_theme);
*files = eina_inlist_remove(*files, *files); *files = eina_inlist_remove(*files, *files);
free(etf); free(etf);
} }
@ -202,17 +228,17 @@ _elm_theme_group_file_find(Elm_Theme *th, const char *group)
EINA_INLIST_FOREACH(th->overlay, etf) EINA_INLIST_FOREACH(th->overlay, etf)
{ {
file = _elm_theme_find_try(th, etf->handle, group); file = _elm_theme_find_try(th, etf, group);
if (file) return file; if (file) return file;
} }
EINA_INLIST_FOREACH(th->themes, etf) EINA_INLIST_FOREACH(th->themes, etf)
{ {
file = _elm_theme_find_try(th, etf->handle, group); file = _elm_theme_find_try(th, etf, group);
if (file) return file; if (file) return file;
} }
EINA_INLIST_FOREACH(th->extension, etf) EINA_INLIST_FOREACH(th->extension, etf)
{ {
file = _elm_theme_find_try(th, etf->handle, group); file = _elm_theme_find_try(th, etf, group);
if (file) return file; if (file) return file;
} }
if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group); if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);