From 799edfed201e47b5d16fa811ffc77231695000d7 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 9 Apr 2019 08:14:53 +0200 Subject: Introduced a new theme format. --- .gitignore | 3 + src/gui/Makefile.am | 3 +- src/gui/core/core.c | 12 +- src/gui/core/theme.c | 294 ++++++++++++++---------------- src/gui/core/theme.h | 11 +- src/gui/theme.c | 403 ++++++++++++++++++++++++++++++++++++++++++ src/gui/theme.h | 63 +++++++ themes/Adwaita/Makefile.am | 12 +- themes/Adwaita/definition.xml | 22 +++ themes/Adwaita/gresource.xml | 12 ++ 10 files changed, 668 insertions(+), 167 deletions(-) create mode 100644 src/gui/theme.c create mode 100644 src/gui/theme.h create mode 100644 themes/Adwaita/definition.xml create mode 100644 themes/Adwaita/gresource.xml diff --git a/.gitignore b/.gitignore index a3fb693..d67d2d2 100644 --- a/.gitignore +++ b/.gitignore @@ -73,3 +73,6 @@ tools/d2c/d2c # Misc plugins/python/androperms/androperms.db + +# Themes +*.ctm diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am index 879b42d..9aceec7 100644 --- a/src/gui/Makefile.am +++ b/src/gui/Makefile.am @@ -8,7 +8,8 @@ libgui_la_SOURCES = \ editor.h editor.c \ panel-int.h \ panel.h panel.c \ - status.h status.c + status.h status.c \ + theme.h theme.c libgui_la_LIBADD = \ core/libguicore.la \ diff --git a/src/gui/core/core.c b/src/gui/core/core.c index 8783783..a0904f8 100644 --- a/src/gui/core/core.c +++ b/src/gui/core/core.c @@ -90,10 +90,16 @@ bool load_all_gui_components(void) bool complete_loading_of_all_gui_components(GGenConfig *config) { bool result; /* Bilan à faire remonter */ + const char *name; /* Nom du thème recherché */ GtkTiledGrid *grid; /* Composant d'affichage */ GPanelItem *welcome; /* Panneau d'accueil */ - load_extra_gtk_theme(); + result = g_generic_config_get_value(config, MPK_INTERNAL_THEME, &name); + if (!result) goto no_theme; + + load_all_themes(); + + apply_gtk_theme(name); result = load_segment_rendering_parameters(); @@ -119,6 +125,8 @@ bool complete_loading_of_all_gui_components(GGenConfig *config) gtk_tiled_grid_restore_positions(grid, config); + no_theme: + return result; } @@ -140,4 +148,6 @@ void unload_all_gui_components(void) { exit_segment_content_hash_table(); + unload_all_themes(); + } diff --git a/src/gui/core/theme.c b/src/gui/core/theme.c index 77eff7f..83bcf4e 100644 --- a/src/gui/core/theme.c +++ b/src/gui/core/theme.c @@ -39,22 +39,16 @@ #include +#include "../theme.h" #include "../../common/extstr.h" #include "../../common/xdg.h" #include "../../core/logs.h" -#include "../../core/params.h" #include "../../plugins/pglist.h" -/* Parcourt tous les répertoires connus pour trouver un thème. */ -static bool browse_themes_directories(GdkScreen *, const char *, gboolean); - -/* Parcourt un répertoire donné à la recherche d'un thème. */ -static bool look_for_named_theme(GdkScreen *, const char *, const char *, gboolean); - -/* Ajoute les définitions CSS à partir d'un chemin donné. */ -static bool load_css_content(GdkScreen *, const char *, gboolean); +/* Parcourt un répertoire donné à la recherche de thèmes. */ +static void look_for_editor_themes(const char *); /* Parcourt tous les greffons à la recherche de définitions CSS. */ static bool extend_with_plugins_themes(GdkScreen *, gboolean); @@ -72,56 +66,15 @@ static const char *_themes_directories[] = { }; +/* Liste de thèmes utilisables */ +static GEditorTheme **_themes = NULL; +static size_t _theme_count = 0; -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Charge le thème GTK pour les composants spécifiques. * -* * -* Retour : true ou false selon le bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool load_extra_gtk_theme(void) -{ - bool result; /* Bilan à faire remonter */ - const char *name; /* Nom du thème recherché */ - GdkScreen *screen; /* Ecran(s) concerné(s) */ - GtkSettings *settings; /* Propriétés du système */ - gboolean dark; /* Envie d'un thème sombre ? */ - - result = false; - - if (!g_generic_config_get_value(get_main_configuration(), MPK_INTERNAL_THEME, &name)) - goto legt_done; - - screen = gdk_screen_get_default(); - - settings = gtk_settings_get_for_screen(screen); - - g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL); - - result = browse_themes_directories(screen, name, dark); - - if (result) - result = extend_with_plugins_themes(screen, dark); - - legt_done: - - return result; - -} - /****************************************************************************** * * -* Paramètres : screen = écran visé par le chargement d'un thème. * -* name = nom du thème recherché, et donc de son répertoire. * -* dark = indique une préférence pour la variante foncée. * +* Paramètres : - * * * * Description : Parcourt tous les répertoires connus pour trouver un thème. * * * @@ -131,15 +84,12 @@ bool load_extra_gtk_theme(void) * * ******************************************************************************/ -static bool browse_themes_directories(GdkScreen *screen, const char *name, gboolean dark) +void load_all_themes(void) { - bool result; /* Bilan à renvoyer */ char *suffix; /* Fin du répertoire personnel */ char *owndir; /* Thèmes personnels ? */ const char **iter; /* Boucle de parcours */ - result = false; - /* Répertoire de l'utilisateur en premier ! */ suffix = strdup("chrysalide"); @@ -152,74 +102,70 @@ static bool browse_themes_directories(GdkScreen *screen, const char *name, gbool if (owndir != NULL) { - result = look_for_named_theme(screen, owndir, name, dark); - + look_for_editor_themes(owndir); free(owndir); - } /* Parcours des autres répertoires classiques au besoin */ - for (iter = _themes_directories; *iter != NULL && !result; iter++) - result = look_for_named_theme(screen, *iter, name, dark); - - return result; + for (iter = _themes_directories; *iter != NULL; iter++) + look_for_editor_themes(*iter); } /****************************************************************************** * * -* Paramètres : screen = écran visé par le chargement d'un thème. * -* dirname = chemin du répertoire où effectuer des recherches. * -* name = nom du thème recherché, et donc de son répertoire. * -* dark = indique une préférence pour la variante foncée. * +* Paramètres : dirname = chemin du répertoire où effectuer des recherches. * * * -* Description : Parcourt un répertoire donné à la recherche d'un thème. * +* Description : Parcourt un répertoire donné à la recherche de thèmes. * * * -* Retour : Bilan de l'opération. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const char *name, gboolean dark) +static void look_for_editor_themes(const char *dirname) { - bool result; /* Bilan à renvoyer */ - char *path; /* Chemin d'accès à essayer */ - int ret; /* Bilan d'un appel */ int dirfd; /* Canal de lecture */ struct dirent **namelist; /* Liste des trouvailles */ int count; /* Nombre de fichiers trouvés */ int i; /* Boucle de parcours */ + struct dirent *entry; /* Raccourci d'usage */ + int ret; /* Bilan d'un appel */ char *filename; /* Chemin d'accès constitué */ + GEditorTheme *theme; /* Nouveau thème valide */ - result = false; - - ret = asprintf(&path, "%s" G_DIR_SEPARATOR_S "%s", dirname, name); - if (ret == -1) goto lfnt_done; + dirfd = open(dirname, O_RDONLY | O_DIRECTORY); + if (dirfd == -1) goto not_found; - dirfd = open(path, O_RDONLY | O_DIRECTORY); - if (dirfd == -1) goto lfnt_not_found; + count = scandirat(dirfd, ".", &namelist, NULL, alphasort); - int keep_css_only(const struct dirent *entry) + for (i = 0; i < count; i++) { - return (entry->d_type == DT_REG - && endswith(entry->d_name, ".css") - && !endswith(entry->d_name, "-dark.css") ? 1 : 0); + entry = namelist[i]; - } + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; - count = scandirat(dirfd, ".", &namelist, keep_css_only, alphasort); + ret = asprintf(&filename, "%s%s%s", dirname, G_DIR_SEPARATOR_S, entry->d_name); + if (ret == -1) continue; - result = (count > 0); + if (entry->d_type == DT_DIR) + look_for_editor_themes(filename); - for (i = 0; i < count && result; i++) - { - ret = asprintf(&filename, "%s%s%s", path, G_DIR_SEPARATOR_S, namelist[i]->d_name); - if (ret == -1) continue; + else if (entry->d_type == DT_REG) + { + theme = g_editor_theme_new(filename, true); - result = load_css_content(screen, filename, dark); + if (theme != NULL) + { + _themes = realloc(_themes, ++_theme_count * sizeof(GEditorTheme *)); + _themes[_theme_count - 1] = theme; + } + + } free(filename); @@ -230,11 +176,80 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c close(dirfd); - lfnt_not_found: + not_found: - free(path); + ; - lfnt_done: +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Décharge tous les thèmes référencés en mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_all_themes(void) +{ + size_t i; /* Boucle de parcours */ + + for (i = 0; i < _theme_count; i++) + g_object_unref(G_OBJECT(_themes[i])); + + if (_themes != NULL) + free(_themes); + + _theme_count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : name = désignation du thème GTK à charger. * +* * +* Description : Charge le thème GTK pour les composants spécifiques. * +* * +* Retour : true ou false selon le bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool apply_gtk_theme(const char *name) +{ + bool result; /* Bilan à faire remonter */ + size_t i; /* Boucle de parcours */ + GdkScreen *screen; /* Ecran(s) concerné(s) */ + GtkSettings *settings; /* Propriétés du système */ + gboolean dark; /* Envie d'un thème sombre ? */ + + result = false; + + for (i = 0; i < _theme_count; i++) + if (strcmp(name, g_editor_theme_get_name(_themes[i])) == 0) + { + result = true; + break; + } + + if (result) + { + screen = gdk_screen_get_default(); + + settings = gtk_settings_get_for_screen(screen); + + g_object_get(settings, "gtk-application-prefer-dark-theme", &dark, NULL); + + g_editor_theme_load(_themes[i], screen, dark); + + } return result; @@ -255,16 +270,12 @@ static bool look_for_named_theme(GdkScreen *screen, const char *dirname, const c * * ******************************************************************************/ -static bool load_css_content(GdkScreen *screen, const char *path, gboolean dark) +GtkCssProvider *load_css_content(GdkScreen *screen, const char *path) { - bool result; /* Bilan à renvoyer */ - GtkCssProvider *provider; /* Nouveau fournisseur CSS */ - char *dark_path; /* Version sombre du chemin */ + GtkCssProvider *result; /* Fournisseur à renvoyer */ GFile *file; /* Fichier à charger */ GError *error; /* Relevé d'éventuelles erreurs*/ - result = false; - /** * Comme GTK exporte les images sous forme de données encodées en base 64 * (cf. gtk_css_image_surface_print()) et ne sait pas recharger ensuite @@ -278,75 +289,32 @@ static bool load_css_content(GdkScreen *screen, const char *path, gboolean dark) * Ce constat est valable pour la version 3.22.11-1 de Debian, au moins. */ - if (dark) - { - provider = gtk_css_provider_new(); - - error = NULL; + result = gtk_css_provider_new(); - dark_path = strdup(path); - dark_path = strrpl(dark_path, ".css", "-dark.css"); + error = NULL; - if (strstr(path, "://") != NULL) - file = g_file_new_for_uri(dark_path); - else - file = g_file_new_for_path(dark_path); + assert(strstr(path, "://") != NULL); - gtk_css_provider_load_from_file(provider, file, &error); + file = g_file_new_for_uri(path); - g_object_unref(G_OBJECT(file)); + gtk_css_provider_load_from_file(result, file, &error); - if (error == NULL) - { - log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), dark_path); + g_object_unref(G_OBJECT(file)); - gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - - result = true; - - } - else - g_error_free(error); - - free(dark_path); + if (error == NULL) + { + log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path); - g_object_unref(G_OBJECT(provider)); + gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(result), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); } - - if (!result) + else { - provider = gtk_css_provider_new(); - - error = NULL; - - if (strstr(path, "://") != NULL) - file = g_file_new_for_uri(path); - else - file = g_file_new_for_path(path); - - gtk_css_provider_load_from_file(provider, file, &error); - - g_object_unref(G_OBJECT(file)); + log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), path); + g_error_free(error); - if (error == NULL) - { - log_variadic_message(LMT_INFO, _("Loaded CSS definitions from '%s'"), path); - - gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), - GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - - result = true; - - } - else - { - log_variadic_message(LMT_ERROR, _("Failed to load CSS definitions from '%s'"), path); - g_error_free(error); - } - - g_object_unref(G_OBJECT(provider)); + g_object_unref(G_OBJECT(result)); } @@ -374,6 +342,7 @@ static bool extend_with_plugins_themes(GdkScreen *screen, gboolean dark) char **resources; /* Fichiers supplémentaires */ size_t count; /* Nombre de ces fichiers */ size_t i; /* Boucle de parcours */ + GtkCssProvider *provider; /* Nouveau fournisseur CSS */ result = true; @@ -384,8 +353,11 @@ static bool extend_with_plugins_themes(GdkScreen *screen, gboolean dark) for (i = 0; i < count && result; i++) { - result = load_css_content(screen, resources[i], dark); + provider = load_css_content(screen, resources[i]); + g_clear_object(&provider); + free(resources[i]); + } if (resources != NULL) diff --git a/src/gui/core/theme.h b/src/gui/core/theme.h index dfa7d34..52c6fb0 100644 --- a/src/gui/core/theme.h +++ b/src/gui/core/theme.h @@ -31,8 +31,17 @@ +/* Parcourt tous les répertoires connus pour trouver un thème. */ +void load_all_themes(void); + +/* Décharge tous les thèmes référencés en mémoire. */ +void unload_all_themes(void); + /* Charge le thème GTK pour les composants spécifiques. */ -bool load_extra_gtk_theme(void); +bool apply_gtk_theme(const char *); + +/* Ajoute les définitions CSS à partir d'un chemin donné. */ +GtkCssProvider *load_css_content(GdkScreen *, const char *); diff --git a/src/gui/theme.c b/src/gui/theme.c new file mode 100644 index 0000000..dc3d1bb --- /dev/null +++ b/src/gui/theme.c @@ -0,0 +1,403 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * theme.c - gestion d'un thème pour l'interface grahique + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "theme.h" + + +#include +#include +#include +#include + + +#include "core/theme.h" +#include "../common/xml.h" + + + +/* Thème graphique pour l'éditeur (instance) */ +struct _GEditorTheme +{ + GObject parent; /* A laisser en premier */ + + GResource *resource; /* Resources GLib associées */ + + char *name; /* Désignation courte du thème */ + + xmlDocPtr xdoc; /* Document XML récupéré */ + xmlXPathContextPtr context; /* Contexte d'analyse associé */ + + GtkCssProvider **providers; /* Fournisseur CSS appliqués */ + size_t count; /* Quantité de ces fournisseurs*/ + +}; + + +/* Thème graphique pour l'éditeur (classe) */ +struct _GEditorThemeClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des éléments réactifs de l'éditeur. */ +static void g_editor_theme_class_init(GEditorThemeClass *); + +/* Initialise une instance d'élément réactif pour l'éditeur. */ +static void g_editor_theme_init(GEditorTheme *); + +/* Supprime toutes les références externes. */ +static void g_editor_theme_dispose(GEditorTheme *); + +/* Procède à la libération totale de la mémoire. */ +static void g_editor_theme_finalize(GEditorTheme *); + +/* Active une partie choisie de thème graphique. */ +static void g_editor_theme_load_section(GEditorTheme *, GdkScreen *, gboolean, const char *); + + + +/* Indique le type défini pour un theme de l'interface graphique. */ +G_DEFINE_TYPE(GEditorTheme, g_editor_theme, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des éléments réactifs de l'éditeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_editor_theme_class_init(GEditorThemeClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_editor_theme_dispose; + object->finalize = (GObjectFinalizeFunc)g_editor_theme_finalize; + +} + + +/****************************************************************************** +* * +* Paramètres : theme = instance à initialiser. * +* * +* Description : Initialise une instance d'élément réactif pour l'éditeur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_editor_theme_init(GEditorTheme *theme) +{ + theme->resource = NULL; + + theme->name = NULL; + + theme->xdoc = NULL; + theme->context = NULL; + + theme->providers = NULL; + theme->count = 0; + +} + + +/****************************************************************************** +* * +* Paramètres : theme = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_editor_theme_dispose(GEditorTheme *theme) +{ + if (theme->resource != NULL) + { + g_resource_unref(theme->resource); + theme->resource = NULL; + } + + G_OBJECT_CLASS(g_editor_theme_parent_class)->dispose(G_OBJECT(theme)); + +} + + +/****************************************************************************** +* * +* Paramètres : theme = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_editor_theme_finalize(GEditorTheme *theme) +{ + if (theme->name != NULL) + free(theme->name); + + if (theme->xdoc != NULL) + close_xml_file(theme->xdoc, theme->context); + + G_OBJECT_CLASS(g_editor_theme_parent_class)->finalize(G_OBJECT(theme)); + +} + + +/****************************************************************************** +* * +* Paramètres : filename = chemin d'accès vers un ressource. * +* include = enregistre la ressource dans l'espace global ? * +* * +* Description : Charge les éléments associés à un thème graphique. * +* * +* Retour : Adresse de la représentation ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GEditorTheme *g_editor_theme_new(const char *filename, bool include) +{ + GEditorTheme *result; /* Adresse à retourner */ + GResource *resource; /* Resources du thème */ + char **children; /* Sous-éléments présents */ + size_t name_len; /* Taille de la désignation */ + char *name; /* Désignation courte du thème */ + char *path; /* Chemin vers à la définition */ + GBytes *bytes; /* Données d'identité */ + const char *data; /* Données XML de définition */ + size_t data_len; /* Quantité de ces données */ + xmlDocPtr xdoc; /* Document XML récupéré */ + xmlXPathContextPtr context; /* Contexte d'analyse associé */ + bool status; /* Bilan de chargement */ + + /* Ouverture de la ressource */ + + resource = g_resource_load(filename, NULL); + if (resource == NULL) goto bad_res; + + children = g_resource_enumerate_children(resource, "/org/chrysalide/gui/themes", + G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); + + if (children == NULL || children[0] == NULL) + goto empty_res; + + name_len = strlen(children[0]); + + if (name_len < 2 || children[0][name_len - 1] != '/') + goto empty_res; + + name = strndup(children[0], name_len - 1); + + /* Chargement de la définition XML */ + + asprintf(&path, "/org/chrysalide/gui/themes/%s/definition.xml", name); + + bytes = g_resource_lookup_data(resource, path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL); + + free(path); + + if (bytes == NULL) + goto no_def; + + data = g_bytes_get_data(bytes, &data_len); + + status = load_xml_from_memory(data, data_len, &xdoc, &context); + + g_bytes_unref(bytes); + + if (!status) + goto bad_xml; + + /* Création du thème */ + + result = g_object_new(G_TYPE_EDITOR_THEME, NULL); + + result->resource = resource; + + result->name = name; + + result->xdoc = xdoc; + result->context = context; + + if (include) + g_resources_register(result->resource); + + return result; + + bad_xml: + + no_def: + + free(name); + + empty_res: + + g_resource_unref(resource); + + bad_res: + + return NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : theme = theme graphique à consulter. * +* * +* Description : Indique le nom d'un thème donné. * +* * +* Retour : Désignation courte associée au thème. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_editor_theme_get_name(const GEditorTheme *theme) +{ + const char *result; /* Désignation à retourner */ + + result = theme->name; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : theme = theme graphique à charger. * +* screen = écran visé par le chargement d'un thème. * +* dark = indique une préférence pour la variante foncée. * +* section = sous-partie de la définition à traiter. * +* * +* Description : Active une partie choisie de thème graphique. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_editor_theme_load_section(GEditorTheme *theme, GdkScreen *screen, gboolean dark, const char *section) +{ + char *def_prefix; /* Base de ressource par défaut*/ + char *sec_access; /* Chemin d'accès à la section */ + xmlXPathObjectPtr xobject; /* Cible d'une recherche */ + unsigned int i; /* Boucle de parcours */ + char *access; /* Chemin d'accès à un élément */ + char *value; /* Resource à charger */ + char *path; /* Chemin d'accès final */ + GtkCssProvider *provider; /* Nouveau fournisseur CSS */ + + asprintf(&def_prefix, "/org/chrysalide/gui/themes/%s/", theme->name); + + asprintf(&sec_access, "/ChrysalideTheme/resources/%s/path", section); + + xobject = get_node_xpath_object(theme->context, sec_access); + + for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) + { + asprintf(&access, "%s[position()=%u]", sec_access, i + 1); + + value = get_node_text_value(theme->context, access); + + free(access); + + if (strlen(value) > 0) + { + if (value[0] == '/') + asprintf(&path, "resource://%s", value); + else + asprintf(&path, "resource://%s%s", def_prefix, value); + + provider = load_css_content(screen, path); + + if (provider != NULL) + { + theme->providers = realloc(theme->providers, ++theme->count * sizeof(GtkCssProvider *)); + theme->providers[theme->count - 1] = provider; + } + + } + + free(value); + + } + + if(xobject != NULL) + xmlXPathFreeObject(xobject); + + free(sec_access); + + free(def_prefix); + +} + + +/****************************************************************************** +* * +* Paramètres : theme = theme graphique à charger. * +* screen = écran visé par le chargement d'un thème. * +* dark = indique une préférence pour la variante foncée. * +* * +* Description : Active un thème graphique particulier. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_editor_theme_load(GEditorTheme *theme, GdkScreen *screen, gboolean dark) +{ + g_editor_theme_load_section(theme, screen, dark, "common"); + + if (dark) + g_editor_theme_load_section(theme, screen, dark, "dark"); + else + g_editor_theme_load_section(theme, screen, dark, "light"); + +} diff --git a/src/gui/theme.h b/src/gui/theme.h new file mode 100644 index 0000000..000347b --- /dev/null +++ b/src/gui/theme.h @@ -0,0 +1,63 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * theme.h - prototypes pour la gestion d'un thème pour l'interface grahique + * + * Copyright (C) 2019 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _GUI_THEME_H +#define _GUI_THEME_H + + +#include +#include + + + +#define G_TYPE_EDITOR_THEME g_editor_theme_get_type() +#define G_EDITOR_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_EDITOR_THEME, GEditorTheme)) +#define G_IS_EDITOR_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_EDITOR_THEME)) +#define G_EDITOR_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_EDITOR_THEME, GEditorThemeClass)) +#define G_IS_EDITOR_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_EDITOR_THEME)) +#define G_EDITOR_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_EDITOR_THEME, GEditorThemeClass)) + + +/* Thème graphique pour l'éditeur (instance) */ +typedef struct _GEditorTheme GEditorTheme; + +/* Thème graphique pour l'éditeur (classe) */ +typedef struct _GEditorThemeClass GEditorThemeClass; + + +/* Indique le type défini pour un theme de l'interface graphique. */ +GType g_editor_theme_get_type(void); + +/* Charge les éléments associés à un thème graphique. */ +GEditorTheme *g_editor_theme_new(const char *, bool); + +/* Indique le nom d'un thème donné. */ +const char *g_editor_theme_get_name(const GEditorTheme *); + +/* Active un thème graphique particulier. */ +void g_editor_theme_load(GEditorTheme *, GdkScreen *, gboolean); + + + +#endif /* _GUI_THEME_H */ diff --git a/themes/Adwaita/Makefile.am b/themes/Adwaita/Makefile.am index cf4d6a3..dd9b215 100644 --- a/themes/Adwaita/Makefile.am +++ b/themes/Adwaita/Makefile.am @@ -1,6 +1,7 @@ GTK3_CSS = \ core.css \ + definition.xml \ display.css \ icons.css \ portions.css \ @@ -10,8 +11,13 @@ GTK3_CSS = \ redo.png \ undo.png -css_DATA = $(GTK3_CSS) +adwaita.ctm: gresource.xml $(GTK3_CSS) + glib-compile-resources --target=$@ --sourcedir=$(srcdir) gresource.xml -cssdir = $(themesdir)/Adwaita +css_DATA = adwaita.ctm -EXTRA_DIST = $(css_DATA) +cssdir = $(themesdir) + +EXTRA_DIST = $(css_DATA) gresource.xml + +CLEANFILES = $(css_DATA) diff --git a/themes/Adwaita/definition.xml b/themes/Adwaita/definition.xml new file mode 100644 index 0000000..b469695 --- /dev/null +++ b/themes/Adwaita/definition.xml @@ -0,0 +1,22 @@ + + + + Adwaita + Cyrille Bagard + Default theme for Chrysalide + + + + core.css + display.css + icons.css + portions.css + + + widgets.css + + + widgets-dark.css + + + diff --git a/themes/Adwaita/gresource.xml b/themes/Adwaita/gresource.xml new file mode 100644 index 0000000..32a8a09 --- /dev/null +++ b/themes/Adwaita/gresource.xml @@ -0,0 +1,12 @@ + + + + definition.xml + core.css + display.css + icons.css + portions.css + widgets.css + widgets-dark.css + + -- cgit v0.11.2-87-g4458