summaryrefslogtreecommitdiff
path: root/src/gui/theme.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-04-09 06:14:53 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-04-09 06:14:53 (GMT)
commit799edfed201e47b5d16fa811ffc77231695000d7 (patch)
tree5f539bb5498a594db48299fac059f72bcd92df9c /src/gui/theme.c
parent010c4d4c07d19ff3f50d0f3caa9fc519ec17df14 (diff)
Introduced a new theme format.
Diffstat (limited to 'src/gui/theme.c')
-rw-r--r--src/gui/theme.c403
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");
+
+}