summaryrefslogtreecommitdiff
path: root/src/gui/panel.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2019-03-26 22:05:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2019-03-26 22:05:49 (GMT)
commitadddee10e395524778c026bf577e885cd8f5947d (patch)
tree6368bccad32f2fdb68bcebd35d5623e48d8d1ba0 /src/gui/panel.c
parent16d050be2b5660f86cf65c465dd5e49ed615b4d0 (diff)
Given the priority to string.h from system includes.
Diffstat (limited to 'src/gui/panel.c')
-rw-r--r--src/gui/panel.c963
1 files changed, 963 insertions, 0 deletions
diff --git a/src/gui/panel.c b/src/gui/panel.c
new file mode 100644
index 0000000..843018e
--- /dev/null
+++ b/src/gui/panel.c
@@ -0,0 +1,963 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel.c - gestion des éléments réactifs spécifiques aux panneaux
+ *
+ * Copyright (C) 2012-2017 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 "panel.h"
+
+
+#include <assert.h>
+#include <stdio.h>
+
+
+#include "panel-int.h"
+#include "../common/extstr.h"
+#include "../core/params.h"
+#include "../gtkext/gtkdockable-int.h"
+
+
+
+/* ------------------------- COEUR DES PANNEAUX D'AFFICHAGE ------------------------- */
+
+
+/* Initialise la classe des éléments réactifs de l'éditeur. */
+static void g_panel_item_class_init(GPanelItemClass *);
+
+/* Initialise une instance d'élément réactif pour l'éditeur. */
+static void g_panel_item_init(GPanelItem *);
+
+/* Procède à l'initialisation de l'interface de rassemblement. */
+static void g_panel_item_dockable_interface_init(GtkDockableInterface *);
+
+/* Supprime toutes les références externes. */
+static void g_panel_item_dispose(GPanelItem *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_panel_item_finalize(GPanelItem *);
+
+/* Détermine si un panneau peut être filtré. */
+static bool gtk_panel_item_can_search(const GPanelItem *);
+
+/* Fournit le nom court du composant encapsulable. */
+static const char *gtk_panel_item_get_name(const GPanelItem *);
+
+/* Fournit le nom long du composant encapsulable. */
+static const char *gtk_panel_item_get_desc(const GPanelItem *);
+
+/* Fournit le composant graphique intégrable dans un ensemble. */
+static GtkWidget *gtk_panel_item_get_widget(GPanelItem *);
+
+/* Démarre l'actualisation du filtrage du contenu. */
+static void gtk_panel_item_update_filtered(GPanelItem *, char *);
+
+/* Construit la chaîne d'accès à un élément de configuration. */
+static char *gtk_panel_item_build_configuration_key(const GPanelItem *, const char *);
+
+
+
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Présente une copie de l'affichage du composant rafraîchi. */
+static gboolean g_panel_item_draw_mask(GtkWidget *, cairo_t *, GPanelItem *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* COEUR DES PANNEAUX D'AFFICHAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour un élément destiné à un panneau. */
+G_DEFINE_TYPE_WITH_CODE(GPanelItem, g_panel_item, G_TYPE_EDITOR_ITEM,
+ G_IMPLEMENT_INTERFACE(GTK_TYPE_DOCKABLE, g_panel_item_dockable_interface_init));
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des éléments réactifs de l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_class_init(GPanelItemClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_panel_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_panel_item_finalize;
+
+ g_signal_new("dock-request",
+ G_TYPE_PANEL_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GPanelItemClass, dock_request),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_signal_new("undock-request",
+ G_TYPE_PANEL_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GPanelItemClass, undock_request),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ klass->can_search = false;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser. *
+* *
+* Description : Initialise une instance d'élément réactif pour l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_init(GPanelItem *item)
+{
+ DL_LIST_ITEM_INIT(&item->link);
+
+ item->personality = PIP_INVALID;
+
+ item->filter = NULL;
+
+ g_atomic_int_set(&item->switched, 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de rassemblement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_dockable_interface_init(GtkDockableInterface *iface)
+{
+ iface->can_search = (can_dockable_search_fc)gtk_panel_item_can_search;
+ iface->get_name = (get_dockable_name_fc)gtk_panel_item_get_name;
+ iface->get_desc = (get_dockable_desc_fc)gtk_panel_item_get_desc;
+ iface->get_widget = (get_dockable_widget_fc)gtk_panel_item_get_widget;
+ iface->update_filtered = (update_filtered_data_fc)gtk_panel_item_update_filtered;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_dispose(GPanelItem *item)
+{
+ g_clear_object(&item->builder);
+
+ G_OBJECT_CLASS(g_panel_item_parent_class)->dispose(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_finalize(GPanelItem *item)
+{
+ free(item->path);
+
+ if (item->filter != NULL)
+ free(item->filter);
+
+ if (item->surface != NULL)
+ cairo_surface_destroy(item->surface);
+
+ G_OBJECT_CLASS(g_panel_item_parent_class)->finalize(G_OBJECT(item));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : personality = nature du panneau à mettre en place. *
+* name = nom associé à l'élément. *
+* lname = description longue du panneau. *
+* widget = composant à présenter à l'affichage. *
+* startup = chargement au démarrage ? *
+* path = chemin vers la place idéale pour le futur panneau. *
+* *
+* Description : Crée un élément de panneau réactif. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPanelItem *g_panel_item_new(PanelItemPersonality personality, const char *name, const char *lname, GtkWidget *widget, bool startup, const char *path)
+{
+ GPanelItem *result; /* Structure à retourner */
+ GEditorItem *parent; /* Autre version de l'élément */
+
+ result = g_object_new(G_TYPE_PANEL_ITEM, NULL);
+
+ parent = G_EDITOR_ITEM(result);
+
+ parent->name = name;
+ parent->widget = widget;
+
+ assert(personality > PIP_INVALID && personality < PIP_COUNT);
+ result->personality = personality;
+
+ result->lname = lname;
+
+ result->dock_at_startup = startup;
+ result->path = strdup(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = panneau dont la construction est à poursuivre. *
+* name = nom associé à l'élément dans les ressources globales. *
+* *
+* Description : Charge les éléments graphiques du panneau via les ressources.*
+* *
+* Retour : Constructeur mis en place, afin de faciliter son usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkBuilder *g_panel_item_build(GPanelItem *item, const char *name)
+{
+ GtkBuilder *result; /* Constructeur à retourner */
+ char *path; /* Chemin d'accès à constituer */
+
+ asprintf(&path, "/org/chrysalide/gui/panels/%s.ui", name);
+
+ result = g_panel_item_build_full(item, path);
+
+ free(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = panneau dont la construction est à poursuivre. *
+* path = chemin d'accès complet à la ressource à charger. *
+* *
+* Description : Charge les éléments graphiques du panneau via les ressources.*
+* *
+* Retour : Constructeur mis en place, afin de faciliter son usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkBuilder *g_panel_item_build_full(GPanelItem *item, const char *path)
+{
+ GtkBuilder *result; /* Constructeur à retourner */
+ GEditorItem *base; /* Version basique d'instance */
+
+ result = gtk_builder_new_from_resource(path);
+
+ item->builder = result;
+
+ base = G_EDITOR_ITEM(item);
+
+ base->widget = GTK_WIDGET(gtk_builder_get_object(result, "box"));
+
+ g_object_ref(G_OBJECT(base->widget));
+
+ gtk_widget_unparent(base->widget);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à consulter. *
+* *
+* Description : Détermine si un panneau peut être filtré. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool gtk_panel_item_can_search(const GPanelItem *item)
+{
+ bool result; /* Indication à retourner */
+ GPanelItemClass *class; /* Classe de l'élément visé */
+
+ class = G_PANEL_ITEM_GET_CLASS(item);
+
+ result = class->can_search;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à consulter. *
+* *
+* Description : Fournit le nom court du composant encapsulable. *
+* *
+* Retour : Désignation humaine pour titre d'onglet ou de fenêtre. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static const char *gtk_panel_item_get_name(const GPanelItem *item)
+{
+ return G_EDITOR_ITEM(item)->name;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à consulter. *
+* *
+* Description : Fournit le nom long du composant encapsulable. *
+* *
+* Retour : Désignation humaine pour titre d'onglet ou de fenêtre. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static const char *gtk_panel_item_get_desc(const GPanelItem *item)
+{
+ return item->lname;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à consulter. *
+* *
+* Description : Fournit le composant graphique intégrable dans un ensemble. *
+* *
+* Retour : Composant graphique prêt à emploi. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GtkWidget *gtk_panel_item_get_widget(GPanelItem *item)
+{
+ return G_EDITOR_ITEM(item)->widget;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à sollicitée. *
+* *
+* Description : Démarre l'actualisation du filtrage du contenu. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_item_update_filtered(GPanelItem *item, char *filter)
+{
+ assert(gtk_panel_item_can_search(item));
+
+ if (item->filter != NULL)
+ free(item->filter);
+
+ item->filter = filter;
+
+ G_PANEL_ITEM_GET_CLASS(item)->update_filtered(item);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* attrib = élément de configuration à inclure dans le résultat.*
+* *
+* Description : Construit la chaîne d'accès à un élément de configuration. *
+* *
+* Retour : Chaîne de caractères à libérer après usage. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static char *gtk_panel_item_build_configuration_key(const GPanelItem *item, const char *attrib)
+{
+ char *result; /* Construction à renvoyer */
+ const char *name; /* Nom court du panneau */
+
+ name = g_editor_item_get_name(G_EDITOR_ITEM(item));
+
+ asprintf(&result, "gui.panels.%s.%s", attrib, name);
+
+ result = strrpl(result, " ", "_");
+
+ result = strlower(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* config = configuration à compléter. *
+* *
+* Description : Met en place les bases de la configuration du panneau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_setup_configuration(const GPanelItem *item, GGenConfig *config)
+{
+ bool result; /* Bilan à retourner */
+ char *key; /* Clef d'accès à un paramètre */
+ GCfgParam *param; /* Paramètre chargé */
+
+ result = true;
+
+ key = gtk_panel_item_build_configuration_key(item, "dock_at_startup");
+
+ param = g_generic_config_create_param(config, key, CPT_BOOLEAN, item->dock_at_startup);
+
+ if (param == NULL)
+ {
+ result = false;
+ goto gpisc_exit;
+ }
+
+ free(key);
+
+ key = gtk_panel_item_build_configuration_key(item, "path");
+
+ param = g_generic_config_create_param(config, key, CPT_STRING, item->path);
+ if (param == NULL)
+ result = false;
+
+ gpisc_exit:
+
+ free(key);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* config = configuration à charger. *
+* *
+* Description : Charge un panneau sur les bases de la configuration fournie. *
+* *
+* Retour : true, par conformité avec browse_all_item_panels(). *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_apply_configuration(GPanelItem *item, GGenConfig *config)
+{
+ char *key; /* Clef d'accès à un paramètre */
+ const char *new_path; /* Nouveau chemin de placement */
+ bool status; /* Statut de l'encapsulation */
+
+ key = gtk_panel_item_build_configuration_key(item, "path");
+
+ if (g_generic_config_get_value(config, key, &new_path))
+ {
+ free(item->path);
+
+ item->path = strdup(new_path);
+
+ }
+
+ free(key);
+
+ key = gtk_panel_item_build_configuration_key(item, "dock_at_startup");
+
+ if (g_generic_config_get_value(config, key, &status))
+ {
+ item->dock_at_startup = status;
+
+ if (item->dock_at_startup)
+ g_signal_emit_by_name(item, "dock-request");
+
+ }
+
+ free(key);
+
+ return true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* *
+* Description : Fournit une indication sur la personnalité du panneau. *
+* *
+* Retour : Identifiant lié à la nature du panneau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PanelItemPersonality gtk_panel_item_get_personality(const GPanelItem *item)
+{
+ return item->personality;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* *
+* Description : Fournit le chemin d'accès à utiliser pour les encapsulations.*
+* *
+* Retour : Chemin d'accès défini. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_panel_item_get_path(const GPanelItem *item)
+{
+ return item->path;
+
+}
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK à consulter. *
+* path = nouvelle emplacement d'inclusion. *
+* *
+* Description : Définit le chemin d'accès à utiliser pour les encapsulations.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_panel_item_set_path(GPanelItem *item, const char *path)
+{
+ char *key; /* Clef d'accès à un paramètre */
+
+ free(item->path);
+
+ item->path = strdup(path);
+
+ key = gtk_panel_item_build_configuration_key(item, "path");
+
+ g_generic_config_set_value(get_main_configuration(), key, item->path);
+
+ free(key);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance GTK dont l'interface est à consulter. *
+* *
+* Description : Indique la définition d'un éventuel raccourci clavier. *
+* *
+* Retour : Description d'un raccourci ou NULL si aucun de défini. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_panel_item_get_key_bindings(const GPanelItem *item)
+{
+ return G_PANEL_ITEM_GET_CLASS(item)->bindings;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = composant à présenter à l'affichage. *
+* *
+* Description : Place un panneau dans l'ensemble affiché. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_panel_item_dock(GPanelItem *item)
+{
+ assert(!item->docked);
+
+ g_signal_emit_by_name(item, "dock-request");
+
+ if (G_PANEL_ITEM_GET_CLASS(item)->ack_dock != NULL)
+ G_PANEL_ITEM_GET_CLASS(item)->ack_dock(item);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = composant d'affichage à mettre à jour. *
+* status = nouvel état d'encapsulation. *
+* *
+* Description : Définit si le composant repose sur un support de l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_panel_item_set_dock_status(GPanelItem *item, bool status)
+{
+ char *key; /* Clef d'accès à un paramètre */
+
+ item->docked = status;
+ item->dock_at_startup = status;
+
+ key = gtk_panel_item_build_configuration_key(item, "dock_at_startup");
+
+ g_generic_config_set_value(get_main_configuration(), key, item->dock_at_startup);
+
+ free(key);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = composant d'affichage à consulter. *
+* *
+* Description : Indique si le composant repose sur un support de l'éditeur. *
+* *
+* Retour : true si le composant est bien incrusté quelque part. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_panel_item_is_docked(const GPanelItem *item)
+{
+ return item->docked;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = composant à retirer de l'affichage. *
+* *
+* Description : Supprime un panneau de l'ensemble affiché. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_panel_item_undock(GPanelItem *item)
+{
+ assert(item->docked);
+
+ g_signal_emit_by_name(item, "undock-request");
+
+ if (G_PANEL_ITEM_GET_CLASS(item)->ack_undock != NULL)
+ G_PANEL_ITEM_GET_CLASS(item)->ack_undock(item);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MECANISMES DE MISE A JOUR DE PANNEAU */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : item = panneau ciblé par une mise à jour. *
+* *
+* Description : Obtient le groupe de travail dédié à une mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+wgroup_id_t g_panel_item_get_group(const GPanelItem *item)
+{
+ wgroup_id_t result; /* Identifiant à retourner */
+
+ result = G_PANEL_ITEM_GET_CLASS(item)->gid;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : widget = composant graphique sur lequel dessiner. *
+* cr = contexte graphique pour le dessin. *
+* panel = panneau ciblé par une mise à jour. *
+* *
+* Description : Présente une copie de l'affichage du composant rafraîchi. *
+* *
+* Retour : FALSE afin de poursuivre les traitements. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean g_panel_item_draw_mask(GtkWidget *widget, cairo_t *cr, GPanelItem *item)
+{
+ int width; /* Largeur du composant actuel */
+ int height; /* Hauteur du composant actuel */
+
+ width = gtk_widget_get_allocated_width(widget);
+ height = gtk_widget_get_allocated_height(widget);
+
+ cairo_save(cr);
+
+ cairo_set_source_surface(cr, item->surface, 0, 0);
+ cairo_rectangle(cr, 0, 0, width, height);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_fill(cr);
+
+ cairo_restore(cr);
+
+ return FALSE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* *
+* Description : Bascule l'affichage d'un panneau avant sa mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_panel_item_switch_to_updating_mask(GPanelItem *item)
+{
+ GtkWidget *content; /* Composant à faire évoluer */
+ GdkWindow *window; /* Fenêtre au contenu à copier */
+ int width; /* Largeur du composant actuel */
+ int height; /* Hauteur du composant actuel */
+ cairo_t *cr; /* Pinceau pour les dessins */
+ GtkAdjustment *adj; /* Défilement éventuel */
+ GtkStack *stack; /* Pile de composants GTK */
+ GtkWidget *mask; /* Masque des travaux */
+
+ if (g_atomic_int_add(&item->switched, 1) > 0)
+ return;
+
+ /* Copie de l'affichage courant */
+
+ assert(item->surface == NULL);
+
+ content = GTK_WIDGET(gtk_builder_get_object(item->builder, "content"));
+
+ window = gtk_widget_get_window(content);
+
+ if (window != NULL)
+ {
+ width = gtk_widget_get_allocated_width(content);
+ height = gtk_widget_get_allocated_height(content);
+
+ item->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+
+ cr = cairo_create(item->surface);
+
+ gdk_cairo_set_source_window(cr, window, 0, 0);
+
+ cairo_paint(cr);
+
+ cairo_destroy(cr);
+
+ }
+
+ /* Sauvegarde de l'éventuelle position */
+
+ if (GTK_IS_SCROLLED_WINDOW(content))
+ {
+ adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(content));
+ item->hadj_value = gtk_adjustment_get_value(adj);
+
+ adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(content));
+ item->vadj_value = gtk_adjustment_get_value(adj);
+
+ }
+
+ /* Opération de basculement effectif */
+
+ stack = GTK_STACK(gtk_builder_get_object(item->builder, "stack"));
+
+ mask = GTK_WIDGET(gtk_builder_get_object(item->builder, "mask"));
+
+ gtk_spinner_start(GTK_SPINNER(mask));
+
+ if (item->surface != NULL)
+ g_signal_connect(mask, "draw", G_CALLBACK(g_panel_item_draw_mask), item);
+
+ gtk_stack_set_visible_child(stack, mask);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau ciblé par une mise à jour. *
+* *
+* Description : Bascule l'affichage d'un panneau après sa mise à jour. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_panel_item_switch_to_updated_content(GPanelItem *item)
+{
+ GtkWidget *content; /* Composant à faire évoluer */
+ GtkAdjustment *adj; /* Défilement éventuel */
+ GtkStack *stack; /* Pile de composants GTK */
+ GtkWidget *mask; /* Masque des travaux */
+
+ if (g_atomic_int_get(&item->switched) > 1)
+ goto skip;
+
+ /* Restauration d'une éventuelle position */
+
+ content = GTK_WIDGET(gtk_builder_get_object(item->builder, "content"));
+
+ if (GTK_IS_SCROLLED_WINDOW(content))
+ {
+ adj = gtk_scrolled_window_get_hadjustment(GTK_SCROLLED_WINDOW(content));
+ gtk_adjustment_set_value(adj, item->hadj_value);
+
+ adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(content));
+ gtk_adjustment_set_value(adj, item->vadj_value);
+
+ }
+
+ /* Opération de basculement effectif */
+
+ stack = GTK_STACK(gtk_builder_get_object(item->builder, "stack"));
+
+ gtk_stack_set_visible_child(stack, content);
+
+ mask = GTK_WIDGET(gtk_builder_get_object(item->builder, "mask"));
+
+ g_signal_handlers_disconnect_by_func(mask, G_CALLBACK(g_panel_item_draw_mask), item);
+
+ gtk_spinner_stop(GTK_SPINNER(mask));
+
+ /* Supression de la copie d'affichage */
+
+ if (item->surface != NULL)
+ {
+ cairo_surface_destroy(item->surface);
+ item->surface = NULL;
+ }
+
+ skip:
+
+ g_atomic_int_dec_and_test(&item->switched);
+
+}