diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2019-04-09 06:14:53 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2019-04-09 06:14:53 (GMT) |
commit | 799edfed201e47b5d16fa811ffc77231695000d7 (patch) | |
tree | 5f539bb5498a594db48299fac059f72bcd92df9c /src/gui/theme.c | |
parent | 010c4d4c07d19ff3f50d0f3caa9fc519ec17df14 (diff) |
Introduced a new theme format.
Diffstat (limited to 'src/gui/theme.c')
-rw-r--r-- | src/gui/theme.c | 403 |
1 files changed, 403 insertions, 0 deletions
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 <malloc.h> +#include <stdio.h> +#include <string.h> +#include <gio/gio.h> + + +#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"); + +} |