summaryrefslogtreecommitdiff
path: root/src/gtkext
diff options
context:
space:
mode:
Diffstat (limited to 'src/gtkext')
-rw-r--r--src/gtkext/Makefile.am37
-rw-r--r--src/gtkext/area.c2
-rw-r--r--src/gtkext/bindings/Makefile.am42
-rw-r--r--src/gtkext/bindings/generated-enums.c.template41
-rw-r--r--src/gtkext/bindings/generated-enums.h.template23
-rw-r--r--src/gtkext/bufferview.c20
-rw-r--r--src/gtkext/dockstation-int.h68
-rw-r--r--src/gtkext/dockstation.c1052
-rw-r--r--src/gtkext/dockstation.h (renamed from src/gtkext/gtkdockstation.h)47
-rw-r--r--src/gtkext/dockstation.ui80
-rw-r--r--src/gtkext/gresource.xml10
-rw-r--r--src/gtkext/grid-int.h81
-rw-r--r--src/gtkext/grid.c1128
-rw-r--r--src/gtkext/grid.h (renamed from src/gtkext/tiledgrid.h)81
-rw-r--r--src/gtkext/grid.ui217
-rw-r--r--src/gtkext/gtkdockstation.c467
-rw-r--r--src/gtkext/gtkstatusstack.c1121
-rw-r--r--src/gtkext/helpers.h43
-rw-r--r--src/gtkext/hexview.c301
-rw-r--r--src/gtkext/hexview.h6
-rw-r--r--src/gtkext/hexview.ui52
-rw-r--r--src/gtkext/launcher-int.h56
-rw-r--r--src/gtkext/launcher.c211
-rw-r--r--src/gtkext/launcher.h45
-rw-r--r--src/gtkext/launcher.ui76
-rw-r--r--src/gtkext/panel-int.h180
-rw-r--r--src/gtkext/panel.c1321
-rw-r--r--src/gtkext/panel.h142
-rw-r--r--src/gtkext/statusstack-int.h106
-rw-r--r--src/gtkext/statusstack.c1383
-rw-r--r--src/gtkext/statusstack.h (renamed from src/gtkext/gtkstatusstack.h)52
-rw-r--r--src/gtkext/statusstack.ui214
-rw-r--r--src/gtkext/tiledgrid.c1143
-rw-r--r--src/gtkext/tweak-int.h65
-rw-r--r--src/gtkext/tweak.c319
-rw-r--r--src/gtkext/tweak.h90
-rw-r--r--src/gtkext/tweak.ui46
37 files changed, 7488 insertions, 2880 deletions
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index c9445e6..c6908dd 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -13,15 +13,11 @@ libgtkext_la_SOURCES = \
gtkblockdisplay.h gtkblockdisplay.c \
gtkdockable-int.h \
gtkdockable.h gtkdockable.c \
- gtkdockstation.h gtkdockstation.c \
gtkgraphdisplay.h gtkgraphdisplay.c \
- gtkstatusstack.h gtkstatusstack.c \
hexdisplay.h hexdisplay.c \
named-int.h \
named.h named.c \
- resources.h resources.c \
support.h support.c \
- tiledgrid.h tiledgrid.c \
tmgt.h tmgt.c
libgtkext_la_LIBADD = \
@@ -30,9 +26,19 @@ libgtkext_la_LIBADD = \
libgtkext_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+IMG_PATH = ../../data/images
+
RES_FILES = \
+ grid.ui \
+ dockstation.ui \
hexview.css \
- hexview.ui
+ hexview.ui \
+ launcher.ui \
+ statusstack.ui \
+ $(IMG_PATH)/nolock-symbolic.svg \
+ $(IMG_PATH)/locked-symbolic.svg \
+ $(IMG_PATH)/unlocked-symbolic.svg \
+ tweak.ui
libgtkext4_la_SOURCES = \
area-int.h \
@@ -41,19 +47,36 @@ libgtkext4_la_SOURCES = \
bufferview.h bufferview.c \
contentview-int.h \
contentview.h contentview.c \
+ dockstation-int.h \
+ dockstation.h dockstation.c \
+ grid-int.h \
+ grid.h grid.c \
+ helpers.h \
hexview-int.h \
hexview.h hexview.c \
- resources.h resources.c
+ launcher-int.h \
+ launcher.h launcher.c \
+ panel-int.h \
+ panel.h panel.c \
+ resources.h resources.c \
+ statusstack-int.h \
+ statusstack.h statusstack.c \
+ tweak-int.h \
+ tweak.h tweak.c
libgtkext4_la_CFLAGS = $(LIBGTK4_CFLAGS)
+libgtkext4_la_LIBADD = \
+ bindings/libgtkextbindings.la
+
devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
-dev_HEADERS = $(libgtkext_la_SOURCES:%c=)
+dev_HEADERS = $(libgtkext4_la_SOURCES:%c=)
#SUBDIRS = graph
+SUBDIRS = bindings
resources.c: gresource.xml $(RES_FILES)
diff --git a/src/gtkext/area.c b/src/gtkext/area.c
index 3c59a59..3c573b2 100644
--- a/src/gtkext/area.c
+++ b/src/gtkext/area.c
@@ -85,6 +85,8 @@ static void gtk_composing_area_class_init(GtkComposingAreaClass *class)
widget = GTK_WIDGET_CLASS(class);
+ gtk_widget_class_set_css_name(widget, "comparea");
+
widget->snapshot = gtk_composing_area_snapshot;
}
diff --git a/src/gtkext/bindings/Makefile.am b/src/gtkext/bindings/Makefile.am
new file mode 100644
index 0000000..71e770d
--- /dev/null
+++ b/src/gtkext/bindings/Makefile.am
@@ -0,0 +1,42 @@
+
+EXTRA_DIST = \
+ generated-enums.c.template \
+ generated-enums.h.template
+
+
+noinst_LTLIBRARIES = libgtkextbindings.la
+
+
+nodist_libgtkextbindings_la_SOURCES = \
+ grid-enums.h grid-enums.c
+
+libgtkextbindings_la_CFLAGS = $(LIBGTK4_CFLAGS)
+
+
+BUILT_SOURCES = $(nodist_libgtkextbindings_la_SOURCES)
+CLEANFILES = $(nodist_libgtkextbindings_la_SOURCES)
+
+
+devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
+
+dev_HEADERS = $(nodist_libgtkextbindings_la_SOURCES:%c=)
+
+
+grid-enums.c: ../../gtkext/grid.h generated-enums.c.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#include \"$(subst .c,.h,$@)\"\n" \
+ --template=$(srcdir)/generated-enums.c.template \
+ --output=$(srcdir)/$@ \
+ $<
+
+grid-enums.h: ../../gtkext/grid.h generated-enums.h.template
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --fhead "#ifndef _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "#define _GTKEXT_BINDINGS_GRID_ENUM_H\n" \
+ --fhead "\n" \
+ --fhead "#include \"$<\"\n" \
+ --fhead "\n" \
+ --ftail "#endif /* _GTKEXT_BINDINGS_GRID_ENUM_H */\n" \
+ --template=$(srcdir)/generated-enums.h.template \
+ --output=$(srcdir)/$@ \
+ $<
diff --git a/src/gtkext/bindings/generated-enums.c.template b/src/gtkext/bindings/generated-enums.c.template
new file mode 100644
index 0000000..8f54149
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.c.template
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* Enumerations de "@filename@" */
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+
+GType @enum_name@_get_type(void)
+{
+ static gsize static_g_@type@_type_id;
+
+ if (g_once_init_enter(&static_g_@type@_type_id)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ {@VALUENAME@, "@VALUENAME@", "@valuenick@"},
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ GType g_@type@_type_id = g_@type@_register_static(
+ g_intern_static_string("@EnumName@"), values);
+
+ g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id);
+ }
+
+ return static_g_@type@_type_id;
+}
+
+/*** END value-tail ***/
diff --git a/src/gtkext/bindings/generated-enums.h.template b/src/gtkext/bindings/generated-enums.h.template
new file mode 100644
index 0000000..58c772d
--- /dev/null
+++ b/src/gtkext/bindings/generated-enums.h.template
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2023-2024 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
+
+/*** BEGIN file-header ***/
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type(void) G_GNUC_CONST;
+#define @ENUMPREFIX@_@ENUMSHORT@_TYPE (@enum_name@_get_type())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+/*** END file-tail ***/
diff --git a/src/gtkext/bufferview.c b/src/gtkext/bufferview.c
index 4a700c3..13c2632 100644
--- a/src/gtkext/bufferview.c
+++ b/src/gtkext/bufferview.c
@@ -33,10 +33,10 @@
/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
-/* Procède à l'initialisation de l'afficheur de tampons. */
+/* Initialise la classe des afficheurs de tampons. */
static void gtk_buffer_view_class_init(GtkBufferViewClass *);
-/* Procède à l'initialisation de l'afficheur de tampons. */
+/* Initialise une instance d'afficheur de tampons. */
static void gtk_buffer_view_init(GtkBufferView *);
/* Supprime toutes les références externes. */
@@ -72,7 +72,7 @@ G_DEFINE_TYPE(GtkBufferView, gtk_buffer_view, GTK_TYPE_CONTENT_VIEW);
* *
* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur de tampons. *
+* Description : Initialise la classe des afficheurs de tampons. *
* *
* Retour : - *
* *
@@ -146,9 +146,9 @@ static void gtk_buffer_view_class_init(GtkBufferViewClass *class)
/******************************************************************************
* *
-* Paramètres : display = composant GTK à initialiser. *
+* Paramètres : view = composant GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur de tampons. *
+* Description : Initialise une instance d'afficheur de tampons. *
* *
* Retour : - *
* *
@@ -168,7 +168,7 @@ static void gtk_buffer_view_init(GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : display = instance d'objet GLib à traiter. *
+* Paramètres : view = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -208,7 +208,7 @@ static void gtk_buffer_view_dispose(GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : display = instance d'objet Gtk à traiter. *
+* Paramètres : view = instance d'objet Gtk à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -279,9 +279,9 @@ GBufferView *gtk_buffer_view_get_view(const GtkBufferView *view)
/******************************************************************************
* *
-* Paramètres : widget = composant GTK à examiner. *
-* width = largeur affectée au composant graphique. *
-* height = hauteur affectée au composant graphique. *
+* Paramètres : widget = composant GTK à examiner. *
+* width = largeur affectée au composant graphique. *
+* height = hauteur affectée au composant graphique. *
* baseline = ligne de base affectée au composant graphique. *
* *
* Description : Prend acte de la taille allouée au composant d'affichage. *
diff --git a/src/gtkext/dockstation-int.h b/src/gtkext/dockstation-int.h
new file mode 100644
index 0000000..17ed828
--- /dev/null
+++ b/src/gtkext/dockstation-int.h
@@ -0,0 +1,68 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockstation.h - prototypes internes pour la manipulation et l'affichage de composants rassemblés
+ *
+ * Copyright (C) 2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_DOCKSTATION_INT_H
+#define _GTKEXT_DOCKSTATION_INT_H
+
+
+#include "dockstation.h"
+
+
+
+/* Station de réception pour concentration d'éléments (instance) */
+struct _GtkDockStation
+{
+ GtkBox parent; /* A laisser en premier */
+
+ GtkOrientation orientation; /* Spécification d'orientation */
+
+ GtkWidget *tabs; /* Bascule entre panneaux */
+ GtkWidget *toolbar; /* Boutons d'action */
+ GtkWidget *sep1; /* Séparateur #1 */
+ GtkStack *stack; /* Pile de panneaux affichés */
+ GtkWidget *sep2; /* Séparateur #2 */
+
+ GtkTiledPanel *def_panel; /* Eventuel panneau à maintenir*/
+
+};
+
+/* Station de réception pour concentration d'éléments (classe) */
+struct _GtkDockStationClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* panel_docked) (GtkDockStation *, GtkTiledPanel *);
+ void (* panel_undocked) (GtkDockStation *, GtkTiledPanel *);
+
+ void (* switch_widget) (GtkDockStation *, GtkWidget *);
+
+ void (* menu_requested) (GtkDockStation *, GtkWidget *);
+ void (* close_requested) (GtkDockStation *, GtkWidget *);
+
+};
+
+
+
+#endif /* _GTKEXT_DOCKSTATION_INT_H */
diff --git a/src/gtkext/dockstation.c b/src/gtkext/dockstation.c
new file mode 100644
index 0000000..80bae75
--- /dev/null
+++ b/src/gtkext/dockstation.c
@@ -0,0 +1,1052 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * dockstation.c - manipulation et l'affichage de composants rassemblés
+ *
+ * Copyright (C) 2012-2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "dockstation.h"
+
+
+#include "dockstation-int.h"
+
+
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _DockStationProperty {
+
+ PROP_0, /* Réservé */
+
+ /* Interface GtkOrientable */
+ PROP_ORIENTATION,
+
+ N_PROPERTIES = PROP_ORIENTATION
+
+} DockStationProperty;
+
+//static GParamSpec *_dock_station_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Procède à l'initialisation de l'afficheur concentré. */
+static void gtk_dock_station_class_init(GtkDockStationClass *);
+
+/* Procède à l'initialisation du support d'affichage concentré. */
+static void gtk_dock_station_init(GtkDockStation *);
+
+/* Supprime toutes les références externes. */
+static void gtk_dock_station_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_dock_station_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_dock_station_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_dock_station_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE DU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage concentré. */
+G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_GRID)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_class_init(GtkDockStationClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_dock_station_dispose;
+ object->finalize = gtk_dock_station_finalize;
+ object->set_property = gtk_dock_station_set_property;
+ object->get_property = gtk_dock_station_get_property;
+
+ //g_object_class_install_properties(object, N_PROPERTIES, _dock_station_properties);
+ g_object_class_override_property(object, PROP_ORIENTATION, "orientation");
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/dockstation.ui");
+
+ //gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press));
+
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, tabs);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, toolbar);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep1);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, stack);
+ gtk_widget_class_bind_template_child(widget, GtkDockStation, sep2);
+
+ g_signal_new("panel-docked",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_docked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("panel-undocked",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, panel_undocked),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ /*
+ g_signal_new("switch-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("menu-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("close-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+ */
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation du support d'affichage concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_init(GtkDockStation *station)
+{
+ gtk_widget_init_template(GTK_WIDGET(station));
+
+ station->orientation = GTK_ORIENTATION_HORIZONTAL;
+
+ station->def_panel = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_dispose(GObject *object)
+{
+ GtkDockStation *station; /* Version spécialisée */
+
+ station = GTK_DOCK_STATION(object);
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
+
+ g_clear_object(&station->def_panel);
+
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_dock_station_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant pour support d'affichage concentré.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_dock_station_new(void)
+{
+ GtkWidget *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
+* *
+* Description : Ajoute un panneau à un groupe de tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_add_panel(GtkDockStation *station, GtkTiledPanel *panel)
+{
+ GtkStackPage *page; /* Nouvelle page insérée */
+
+ page = gtk_stack_add_child(station->stack, GTK_WIDGET(panel));
+
+ if (0) // TODO
+ gtk_stack_page_set_title(page, "settings");
+
+ else
+ gtk_stack_page_set_icon_name(page, "logs-symbolic");
+
+ gtk_stack_set_visible_child(station->stack, GTK_WIDGET(panel));
+
+
+ g_signal_emit_by_name(station, "panel-docked", panel);
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à compléter. *
+* panel = nouveau panneau à afficher. *
+* *
+* Description : Ajoute un panneau à conserver à un groupe de tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_keep_panel(GtkDockStation *station, GtkTiledPanel *panel)
+{
+ bool visible; /* Visibilité des barres */
+
+ g_clear_object(&station->def_panel);
+
+ if (panel != NULL)
+ {
+ station->def_panel = panel;
+ ref_object(panel);
+
+ if (gtk_stack_get_page(station->stack, GTK_WIDGET(panel)) == NULL)
+ gtk_dock_station_add_panel(station, panel);
+
+ }
+
+ visible = (station->def_panel == NULL);
+
+ gtk_widget_set_visible(station->tabs, visible);
+ gtk_widget_set_visible(station->toolbar, visible);
+ gtk_widget_set_visible(station->sep1, visible);
+ gtk_widget_set_visible(station->sep2, visible && station->orientation == GTK_ORIENTATION_HORIZONTAL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à consulter. *
+* *
+* Description : Indique si la station d'accueil contient au moins un panneau.*
+* *
+* Retour : true si aucun panneau n'est intégré, false sinon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_dock_station_is_empty(const GtkDockStation *station)
+{
+ bool result; /* Bilan à retourner */
+ GtkSelectionModel *model; /* Modèle pour la pile */
+ guint count; /* Nombre de panneaux présents */
+
+ model = gtk_stack_get_pages(station->stack);
+
+ count = g_list_model_get_n_items(G_LIST_MODEL(model));
+
+ result = (count == 0);
+
+ unref_object(model);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = station d'accueil pour panneaux à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *station, GtkTiledPanel *main, bool activated)
+{
+ GListModel *list; /* Liste de pages à parcourir */
+ guint count; /* Nombre de pages */
+ guint i; /* Boucle de parcours */
+ GtkStackPage *page; /* Page à consulter */
+ GtkWidget *panel; /* Panneau intégré */
+
+ list = G_LIST_MODEL(gtk_stack_get_pages(station->stack));
+
+ count = g_list_model_get_n_items(list);
+
+ for (i = 0; i < count; i++)
+ {
+ page = GTK_STACK_PAGE(g_list_model_get_object(list, i));
+ if (page == NULL) continue;
+
+ panel = gtk_stack_page_get_child(page);
+
+ gtk_tiled_panel_notify_new_main_panel_state(GTK_TILED_PANEL(panel), main, activated);
+
+ unref_object(page);
+
+ }
+
+ unref_object(list);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+ GtkOrientation orientation; /* Spécification d'orientation */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkLayoutChild *child_layout; /* Disposition de composant */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+
+ orientation = g_value_get_enum(value);
+
+ if (station->orientation != orientation)
+ {
+ station->orientation = orientation;
+
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->tabs), orientation);
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(station->toolbar), orientation);
+
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(object));
+
+ if (orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_CENTER,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 1,
+ "column-span", 2,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, FALSE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 0,
+ "row", 2,
+ "column-span", 2,
+ NULL);
+
+ }
+ else
+ {
+ g_object_set(G_OBJECT(station->tabs),
+ "halign", GTK_ALIGN_START,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ g_object_set(G_OBJECT(station->toolbar),
+ "halign", GTK_ALIGN_END,
+ "valign", GTK_ALIGN_START,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep1);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 1,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, GTK_WIDGET(station->stack));
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 2,
+ "row", 0,
+ "column-span", 1,
+ NULL);
+
+ gtk_widget_set_visible(station->sep2, TRUE);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->sep2);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 3,
+ "row", 0,
+ NULL);
+
+ child_layout = gtk_layout_manager_get_layout_child(layout, station->toolbar);
+
+ g_object_set(G_OBJECT(child_layout),
+ "column", 4,
+ "row", 0,
+ NULL);
+
+ }
+
+ g_object_notify_by_pspec(object, pspec);
+
+ }
+
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkDockStation *station; /* Version spécialisée */
+
+ station = GTK_DOCK_STATION(object);
+
+ switch (prop_id)
+ {
+ case PROP_ORIENTATION:
+ g_value_set_enum(value, station->orientation);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "easygtk.h"
+#include "../core/params.h"
+#include "../common/extstr.h"
+#include "../glibext/chrysamarshal.h"
+
+
+
+/* Procède à l'initialisation de l'afficheur concentré. */
+static void gtk_dock_station_class_init(GtkDockStationClass *);
+
+/* Procède à l'initialisation du support d'affichage concentré. */
+static void gtk_dock_station_init(GtkDockStation *);
+
+/* Met à jour le titre du support de panneaux concentrés. */
+static gboolean gtk_dock_station_switch_panel(GtkNotebook *, gpointer *, guint, GtkDockStation *);
+
+
+
+
+/* Révèle ou cache la zone de recherches. */
+static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *);
+
+/* Demande l'apparition d'un menu pour inclure des composants. */
+static void on_click_for_menu(GtkButton *, GtkDockStation *);
+
+/* Demande la disparition du composant courant. */
+static void on_click_for_close(GtkButton *, GtkDockStation *);
+
+
+
+
+
+
+/* Détermine le type du composant d'affichage concentré. */
+G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_NOTEBOOK)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'afficheur concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_class_init(GtkDockStationClass *class)
+{
+ g_signal_new("dock-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, dock_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("undock-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, undock_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("switch-widget",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("menu-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+ g_signal_new("close-requested",
+ GTK_TYPE_DOCK_STATION,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = composant GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation du support d'affichage concentré. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_dock_station_init(GtkDockStation *station)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ GtkWidget *hbox; /* Division supérieure */
+ GtkWidget *button; /* Bouton de contrôle */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ gtk_notebook_set_show_border(notebook, FALSE);
+ gtk_notebook_set_scrollable(notebook, TRUE);
+
+ /* Définition de la zone de contrôle */
+
+ hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+ gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER);
+ gtk_widget_set_margin_end(hbox, 8);
+ gtk_widget_show(hbox);
+
+ button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search",
+ "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_toggle_revealer), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ button = qck_create_button_with_named_img(G_OBJECT(station), "menu",
+ "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_click_for_menu), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ button = qck_create_button_with_named_img(G_OBJECT(station), "close",
+ "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL,
+ G_CALLBACK(on_click_for_close), station);
+ gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END);
+
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée un nouveau composant pour support d'affichage concentré.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_dock_station_new(void)
+{
+ return g_object_new(GTK_TYPE_DOCK_STATION, NULL);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : notebook = support à l'origine de la mise à jour. *
+* page = onglet mis en avant. *
+* index = indice de l'onglet actuellement actif. *
+* station = conteneur de gestion supérieur. *
+* *
+* Description : Met à jour le titre du support de panneaux concentrés. *
+* *
+* Retour : TRUE ? *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *page, guint index, GtkDockStation *station)
+{
+ GtkWidget *widget; /* Panneau concerné */
+ GtkDockable *dockable; /* Elément encapsulé */
+ GtkWidget *button; /* Bouton de contrôle */
+
+ widget = gtk_notebook_get_nth_page(notebook, index);
+
+ dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
+
+ /* Mise à jour des boutons utilisables */
+
+ button = GTK_WIDGET(g_object_get_data(G_OBJECT(station), "search"));
+
+ if (gtk_dockable_can_search(dockable))
+ gtk_widget_show(button);
+ else
+ gtk_widget_hide(button);
+
+ /* Remontée du changement d'onglet */
+
+ g_signal_emit_by_name(station, "switch-widget", widget);
+
+ return TRUE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* dockable = nouvel élément à intégrer. *
+* *
+* Description : Ajoute un paquet d'informations à l'affichage centralisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#include "gtkdisplaypanel.h"
+#include "../gui/panels/history.h"
+void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockable)
+{
+ GtkWidget *widget; /* Composant GTK à intégrer */
+ char *name; /* Nom à donner à l'onglet */
+ char *desc; /* Description à y associer */
+ int max; /* Taille maximale des titres */
+ GtkWidget *label; /* Etiquette d'onglet */
+ GtkNotebook *notebook; /* Autre version du composant */
+
+
+
+
+
+
+
+ /* Récupération des éléments utiles */
+
+ widget = gtk_dockable_build_widget(dockable);
+
+ //widget = gtk_button_new_with_label("123");
+ gtk_widget_show(widget);
+
+
+ g_object_set_data(G_OBJECT(widget), "dockable", dockable);
+
+ name = gtk_dockable_get_name(dockable);
+ desc = gtk_dockable_get_desc(dockable);
+
+ /* Mise en place de la page */
+
+ if (!g_generic_config_get_value(get_main_configuration(), MPK_ELLIPSIS_TAB, &max))
+ max = -1;
+
+ name = ellipsis(name, max);
+ label = qck_create_label(NULL, NULL, name);
+ free(name);
+
+ notebook = GTK_NOTEBOOK(station);
+
+ if (gtk_notebook_get_n_pages(notebook) > 0)
+ g_signal_handlers_disconnect_by_func(notebook,
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ gtk_notebook_append_page(notebook, widget, label);
+
+ gtk_widget_set_tooltip_text(label, desc);
+
+ free(desc);
+
+ if (gtk_notebook_get_n_pages(notebook) > 1)
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ /* Lancement des mises à jour */
+
+ if (gtk_notebook_get_n_pages(notebook) > 1)
+ gtk_notebook_set_current_page(notebook, -1);
+
+ //g_signal_emit_by_name(station, "dock-widget", widget);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* widget = nouvel élément à intégrer. *
+* *
+* Description : Change le contenu de l'onglet courant uniquement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *widget)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ gint index; /* Indice de l'onglet actif */
+ GtkWidget *old; /* Ancien composant */
+ GtkWidget *label; /* Etiquette d'onglet */
+ char *str; /* Titre des prochaines fois */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ index = gtk_notebook_get_current_page(notebook);
+
+ g_signal_handlers_disconnect_by_func(notebook,
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+ old = gtk_notebook_get_nth_page(notebook, index);
+ label = gtk_notebook_get_tab_label(notebook, old);
+
+ g_object_ref(G_OBJECT(label));
+ str = g_object_get_data(G_OBJECT(old), "title");
+
+ gtk_notebook_remove_page(notebook, index);
+ gtk_notebook_insert_page(notebook, widget, label, index);
+
+ g_object_unref(G_OBJECT(label));
+ g_object_set_data(G_OBJECT(widget), "title", str);
+
+ gtk_notebook_set_current_page(notebook, index);
+
+ g_signal_connect(notebook, "switch-page",
+ G_CALLBACK(gtk_dock_station_switch_panel), station);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK à compléter. *
+* dockable = élément existant à retirer. *
+* *
+* Description : Retire un paquet d'informations de l'affichage centralisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_dock_station_remove_dockable(GtkDockStation *station, GtkDockable *dockable)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ GtkWidget *widget; /* Composant GTK à retirer */
+ gint index; /* Indice de l'onglet visé */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ widget = gtk_dockable_decompose(dockable, NULL);
+
+ index = gtk_notebook_page_num(notebook, widget);
+
+ gtk_notebook_remove_page(notebook, index);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Révèle ou cache la zone de recherches. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station)
+{
+ GtkNotebook *notebook; /* Autre version du composant */
+ gint index; /* Indice de l'onglet courant */
+ GtkWidget *widget; /* Panneau concerné */
+ GtkDockable *dockable; /* Elément encapsulé */
+
+ notebook = GTK_NOTEBOOK(station);
+
+ index = gtk_notebook_get_current_page(notebook);
+ widget = gtk_notebook_get_nth_page(notebook, index);
+
+ dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
+
+ gtk_dockable_toggle_revealer(dockable, widget, gtk_toggle_button_get_active(button));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Demande l'apparition d'un menu pour inclure des composants. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_click_for_menu(GtkButton *button, GtkDockStation *station)
+{
+ g_signal_emit_by_name(station, "menu-requested", button);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : button = bouton à l'origine de la procédure. *
+* station = station d'accueil pour différents composants. *
+* *
+* Description : Demande la disparition du composant courant. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void on_click_for_close(GtkButton *button, GtkDockStation *station)
+{
+ g_signal_emit_by_name(station, "close-requested", button);
+
+}
+
+
+#endif
+
diff --git a/src/gtkext/gtkdockstation.h b/src/gtkext/dockstation.h
index f286c1c..e4c849f 100644
--- a/src/gtkext/gtkdockstation.h
+++ b/src/gtkext/dockstation.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkdockstation.h - prototypes pour la manipulation et l'affichage de composants rassemblés
+ * dockstation.h - prototypes pour la manipulation et l'affichage de composants rassemblés
*
- * Copyright (C) 2012-2018 Cyrille Bagard
+ * Copyright (C) 2012-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,13 +21,46 @@
*/
-#ifndef _GTKEXT_GTKDOCKSTATION_H
-#define _GTKEXT_GTKDOCKSTATION_H
+#ifndef _GTKEXT_DOCKSTATION_H
+#define _GTKEXT_DOCKSTATION_H
#include <gtk/gtk.h>
+#include "panel.h"
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_DOCK_STATION (gtk_dock_station_get_type())
+
+DECLARE_GTYPE(GtkDockStation, gtk_dock_station, GTK, DOCK_STATION);
+
+
+/* Crée un nouveau composant pour support d'affichage concentré. */
+GtkWidget *gtk_dock_station_new(void);
+
+/* Ajoute un panneau à un groupe de tuiles. */
+void gtk_dock_station_add_panel(GtkDockStation *, GtkTiledPanel *);
+
+/* Ajoute un panneau à conserver à un groupe de tuiles. */
+void gtk_dock_station_keep_panel(GtkDockStation *, GtkTiledPanel *);
+
+/* Indique si la station d'accueil contient au moins un panneau. */
+bool gtk_dock_station_is_empty(const GtkDockStation *);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_dock_station_notify_new_main_panel_state(const GtkDockStation *, GtkTiledPanel *, bool);
+
+
+
+
+#if 0
+
+#include <gtk/gtk.h>
+
+
#include "gtkdockable.h"
@@ -76,9 +109,6 @@ struct _GtkDockStationClass
/* Détermine le type du composant d'affichage concentré. */
GType gtk_dock_station_get_type(void);
-/* Crée un nouveau composant pour support d'affichage concentré. */
-GtkWidget *gtk_dock_station_new(void);
-
/* Ajoute un paquet d'informations à l'affichage centralisé. */
void gtk_dock_station_add_dockable(GtkDockStation *, GtkDockable *);
@@ -92,6 +122,7 @@ void gtk_dock_station_remove_dockable(GtkDockStation *, GtkDockable *);
//G_END_DECLS
+#endif
-#endif /* _GTKEXT_GTKDOCKSTATION_H */
+#endif /* _GTKEXT_DOCKSTATION_H */
diff --git a/src/gtkext/dockstation.ui b/src/gtkext/dockstation.ui
new file mode 100644
index 0000000..4d25134
--- /dev/null
+++ b/src/gtkext/dockstation.ui
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkDockStation" parent="GtkGrid">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkStackSwitcher" id="tabs">
+ <property name="orientation">horizontal</property>
+ <property name="halign">start</property>
+ <property name="valign">start</property>
+ <property name="margin-start">2</property>
+ <property name="margin-top">2</property>
+ <property name="margin-end">2</property>
+ <property name="margin-bottom">2</property>
+ <property name="stack">stack</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkBox" id="toolbar">
+ <property name="orientation">horizontal</property>
+ <property name="halign">end</property>
+ <property name="valign">start</property>
+
+ <child>
+ <object class="GtkButton">
+ <property name="icon-name">window-close-symbolic</property>
+ <style>
+ <class name="circular"/>
+ <class name="flat"/>
+ <class name="control-button"/>
+ </style>
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">4</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep1">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkStack" id="stack">
+ <property name="hexpand">true</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="column-span">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="sep2">
+ <property name="orientation">horizontal</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/gresource.xml b/src/gtkext/gresource.xml
index 225b2a4..26943a6 100644
--- a/src/gtkext/gresource.xml
+++ b/src/gtkext/gresource.xml
@@ -1,7 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/re/chrysalide/framework/gtkext">
+ <file compressed="true">dockstation.ui</file>
+ <file compressed="true">grid.ui</file>
<file compressed="true">hexview.css</file>
<file compressed="true">hexview.ui</file>
+ <file compressed="true">launcher.ui</file>
+ <file compressed="true">statusstack.ui</file>
+ <file compressed="true">tweak.ui</file>
+ </gresource>
+ <gresource prefix="/re/chrysalide/framework/gui/icons/scalable/actions">
+ <file compressed="true" alias="nolock-symbolic.svg">../../data/images/nolock-symbolic.svg</file>
+ <file compressed="true" alias="locked-symbolic.svg">../../data/images/locked-symbolic.svg</file>
+ <file compressed="true" alias="unlocked-symbolic.svg">../../data/images/unlocked-symbolic.svg</file>
</gresource>
</gresources>
diff --git a/src/gtkext/grid-int.h b/src/gtkext/grid-int.h
new file mode 100644
index 0000000..8a2702b
--- /dev/null
+++ b/src/gtkext/grid-int.h
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * grid-int.h - prototypes interne pour un composant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_GRID_INT_H
+#define _GTKEXT_GRID_INT_H
+
+
+#include "dockstation.h"
+#include "grid.h"
+
+
+
+/* Conteneur pour un affichage en tuiles nommées (instance) */
+struct _GtkTilingGrid
+{
+ GtkGrid parent; /* A laisser en premier */
+
+ GSettings *settings; /* Configuration du conteneur */
+
+ LayoutReachOptions layout; /* Disposition générale */
+
+ bool visible[TGB_COUNT]; /* Visibilités souhaitées */
+
+ GtkRevealer *top; /* Zone d'accueil #1 */
+ GtkWidget *top_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *top_station; /* Station entière */
+
+ GtkRevealer *left; /* Zone d'accueil #2 */
+ GtkWidget *left_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *left_station; /* Station entière */
+
+ GtkDockStation *main_station; /* Zone d'accueil #3 */
+
+ GtkRevealer *right; /* Zone d'accueil #4 */
+ GtkWidget *right_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *right_station; /* Station entière */
+
+ GtkRevealer *bottom; /* Zone d'accueil #5 */
+ GtkWidget *bottom_handle; /* Poignée de redimensionnement*/
+ GtkDockStation *bottom_station; /* Station entière */
+
+ GtkGesture *tpad_gesture[TGB_COUNT]; /* Gestionnaires du touchpad */
+
+ bool panning; /* Redimensionnement en cours */
+
+};
+
+/* Conteneur pour un affichage en tuiles nommées (classe) */
+struct _GtkTilingGridClass
+{
+ GtkGridClass parent; /* A laisser en premier */
+
+ /* Signaux */
+
+ void (* station_created) (GtkTilingGrid *, GtkDockStation *, gpointer);
+
+};
+
+
+
+#endif /* _GTKEXT_GRID_INT_H */
diff --git a/src/gtkext/grid.c b/src/gtkext/grid.c
new file mode 100644
index 0000000..eb3cdf9
--- /dev/null
+++ b/src/gtkext/grid.c
@@ -0,0 +1,1128 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * grid.c - composant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2018-2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "grid.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "grid-int.h"
+#include "helpers.h"
+#include "bindings/grid-enums.h"
+
+
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _TilingGridProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_LAYOUT, /* Disposition générale */
+
+ PROP_EMPTY_TOP, /* Vide de la zone supérieure */
+ PROP_EMPTY_LEFT, /* Vide de la zone de gauche */
+ PROP_EMPTY_RIGHT, /* Vide de la zone de droite */
+ PROP_EMPTY_BOTTOM, /* Vide de la zone inférieure */
+
+ PROP_VISIBLE_TOP, /* Visibilité de zone sup. */
+ PROP_VISIBLE_LEFT, /* Visibilité de zone de gauche*/
+ PROP_VISIBLE_RIGHT, /* Visibilité de zone de droite*/
+ PROP_VISIBLE_BOTTOM, /* Visibilité de zone inf. */
+
+ N_PROPERTIES
+
+} TilingGridProperty;
+
+static GParamSpec *_tiling_grid_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des conteneurs d'affichage en tuiles. */
+static void gtk_tiling_grid_class_init(GtkTilingGridClass *);
+
+/* Initialise une instance de conteneur d'affichage en tuiles. */
+static void gtk_tiling_grid_init(GtkTilingGrid *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tiling_grid_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tiling_grid_finalize(GObject *);
+
+/* Réagit à une intégration ou à un retrait de panneau. */
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *, GtkTiledPanel *, GtkTilingGrid *);
+
+
+
+/* -------------------- REDIMENSIONNEMENT DE ZONES POUR PANNEAUX -------------------- */
+
+
+/* Initie un redimensionnement par drag-and-drop. */
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Applique l'effet d'un redimensionnement drag-and-drop donné. */
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *, TilingGridBorder, double, double);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Actualise l'effet d'un redimensionnement drag-and-drop. */
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+/* Clôture un drag-and-drop de redimensionnement. */
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *, double, double, GtkTilingGrid *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_tiling_grid_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_tiling_grid_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* INTERFACE DU COMPOSANT GTK */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du conteneur d'affichage en tuiles nommées. */
+G_DEFINE_TYPE(GtkTilingGrid, gtk_tiling_grid, GTK_TYPE_GRID)
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des conteneurs d'affichage en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_class_init(GtkTilingGridClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_tiling_grid_dispose;
+ object->finalize = gtk_tiling_grid_finalize;
+ object->set_property = gtk_tiling_grid_set_property;
+ object->get_property = gtk_tiling_grid_get_property;
+
+ _tiling_grid_properties[PROP_LAYOUT] =
+ g_param_spec_flags("layout", NULL, NULL,
+ LAYOUT_REACH_OPTIONS_TYPE,
+ LRO_NONE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_TOP] =
+ g_param_spec_boolean("empty-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_LEFT] =
+ g_param_spec_boolean("empty-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_RIGHT] =
+ g_param_spec_boolean("empty-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_EMPTY_BOTTOM] =
+ g_param_spec_boolean("empty-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * La valeur initiale des champs suivants est à maintenir synchronisée avec
+ * les initialisations de gtk_tiling_grid_init().
+ */
+
+ _tiling_grid_properties[PROP_VISIBLE_TOP] =
+ g_param_spec_boolean("visible-top", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_LEFT] =
+ g_param_spec_boolean("visible-left", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_RIGHT] =
+ g_param_spec_boolean("visible-right", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ _tiling_grid_properties[PROP_VISIBLE_BOTTOM] =
+ g_param_spec_boolean("visible-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _tiling_grid_properties);
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ g_type_ensure(GTK_TYPE_DOCK_STATION);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/grid.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_panel_un_docked));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_begin));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_top_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_left_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_right_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_bottom_gesture_drag_update));
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_tiling_grid_on_gesture_drag_end));
+
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, top_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, left_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, main_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, right_station);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_handle);
+ gtk_widget_class_bind_template_child(widget, GtkTilingGrid, bottom_station);
+
+
+ /////////////
+
+ g_signal_new("station-created",
+ GTK_TYPE_TILING_GRID,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(GtkTilingGridClass, station_created),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET/*DOCK_STATION FIXME */);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = instance GTK à initialiser. *
+* *
+* Description : Initialise une instance de conteneur d'affichage en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_init(GtkTilingGrid *grid)
+{
+ gtk_widget_init_template(GTK_WIDGET(grid));
+
+ grid->settings = g_settings_new_with_path("re.chrysalide.framework.tiledgrid",
+ "/re/chrysalide/framework/gui/tiles/");
+
+ g_settings_bind(grid->settings, "layout",
+ grid, "layout",
+ G_SETTINGS_BIND_DEFAULT);
+
+ /**
+ * L'initialisation des champs suivants est à maintenir synchronisée avec
+ * les valeurs initiales de gtk_tiling_grid_class_init().
+ */
+
+ grid->visible[TGB_TOP] = true;
+ grid->visible[TGB_LEFT] = true;
+ grid->visible[TGB_RIGHT] = true;
+ grid->visible[TGB_BOTTOM] = true;
+
+ g_settings_bind(grid->settings, "top-request",
+ grid->top_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "top-visibility",
+ grid, "visible-top",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "left-request",
+ grid->left_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "left-visibility",
+ grid, "visible-left",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-request",
+ grid->right_station, "width-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "right-visibility",
+ grid, "visible-right",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-request",
+ grid->bottom_station, "height-request",
+ G_SETTINGS_BIND_DEFAULT);
+
+ g_settings_bind(grid->settings, "bottom-visibility",
+ grid, "visible-bottom",
+ G_SETTINGS_BIND_DEFAULT);
+
+ gtk_widget_set_cursor_from_name(grid->top_handle, "row-resize");
+ gtk_widget_set_cursor_from_name(grid->left_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->right_handle, "col-resize");
+ gtk_widget_set_cursor_from_name(grid->bottom_handle, "row-resize");
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_dispose(GObject *object)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_DOCK_STATION);
+
+ grid = GTK_TILING_GRID(object);
+
+ g_clear_object(&grid->settings);
+
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_tiling_grid_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle instance de conteneur avec tuiles. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkWidget *gtk_tiling_grid_new(void)
+{
+ GtkWidget *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_TILING_GRID, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* visible = nouveau statut de visibilité à appliquer. *
+* *
+* Description : Affiche ou masque une zone du conteneur en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_set_visible(GtkTilingGrid *grid, TilingGridBorder border, bool visible)
+{
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ GtkDockStation *station; /* Apport d'une contrainte */
+
+ if (grid->visible[border] != visible)
+ {
+ grid->visible[border] = visible;
+
+ switch (border)
+ {
+ case TGB_TOP:
+ revealer = grid->top;
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ revealer = grid->left;
+ station = grid->left_station;
+ break;
+
+ case TGB_RIGHT:
+ revealer = grid->right;
+ station = grid->right_station;
+ break;
+
+ case TGB_BOTTOM:
+ revealer = grid->bottom;
+ station = grid->bottom_station;
+ break;
+
+ }
+
+ gtk_revealer_set_reveal_child(revealer, visible && !gtk_dock_station_is_empty(station));
+
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_VISIBLE_TOP + border]);
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* *
+* Description : Fournit la visibilité d'une zone du conteneur en tuiles. *
+* *
+* Retour : Visibilité de la zone considérée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tiling_grid_get_visible(GtkTilingGrid *grid, TilingGridBorder border)
+{
+ bool result; /* Statut à retourner */
+
+ result = grid->visible[border];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* panel = nouveau panneau à afficher. *
+* keep = indique si le panneau est à conserver présent. *
+* *
+* Description : Ajoute un panneau à un conteneur en tuiles. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_add_panel(GtkTilingGrid *grid, GtkTiledPanel *panel, bool keep)
+{
+ char *path; /* Chemin visé par le panneau */
+ bool static_path; /* Nature du chemin à traiter */
+
+ path = gtk_tiled_panel_get_path(panel);
+
+ static_path = (path == NULL);
+
+ if (static_path)
+ path = "";
+
+ switch (path[0])
+ {
+ case 'N':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->top_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->top_station, panel);
+ break;
+
+ case 'W':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->left_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->left_station, panel);
+ break;
+
+ case '\0':
+ case 'M':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->main_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->main_station, panel);
+ break;
+
+ case 'E':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->right_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->right_station, panel);
+ break;
+
+ case 'S':
+ if (keep)
+ gtk_dock_station_keep_panel(grid->bottom_station, panel);
+ else
+ gtk_dock_station_add_panel(grid->bottom_station, panel);
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (!static_path)
+ free(path);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *grid, GtkTiledPanel *main, bool activated)
+{
+ gtk_dock_station_notify_new_main_panel_state(grid->top_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->left_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->main_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->right_station, main, activated);
+
+ gtk_dock_station_notify_new_main_panel_state(grid->bottom_station, main, activated);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : station = plateforme GTK ayant connu un changement. *
+* widget = nouvel élément à intégrer. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Réagit à une intégration ou à un retrait de panneau. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_panel_un_docked(GtkDockStation *station, GtkTiledPanel *panel, GtkTilingGrid *grid)
+{
+ TilingGridBorder border; /* Aire concernée par l'action */
+ GtkRevealer *revealer; /* Cible visée par l'opération */
+ bool new_state; /* Nouveau statut d'affichage */
+
+ if (station == grid->top_station)
+ {
+ border = TGB_TOP;
+ revealer = grid->top;
+ }
+
+ else if (station == grid->left_station)
+ {
+ border = TGB_LEFT;
+ revealer = grid->left;
+ }
+
+ else if (station == grid->right_station)
+ {
+ border = TGB_RIGHT;
+ revealer = grid->right;
+ }
+
+ else if (station == grid->bottom_station)
+ {
+ border = TGB_BOTTOM;
+ revealer = grid->bottom;
+ }
+
+ else
+ assert(false);
+
+ new_state = grid->visible[border] && !gtk_dock_station_is_empty(station);
+
+ if (gtk_revealer_get_reveal_child(revealer) != new_state)
+ gtk_revealer_set_reveal_child(revealer, new_state);
+
+ /**
+ * On ne sait pas si l'état a réellement changé, mais on avertit
+ * d'une mise à jour quand même, au cas où.
+ */
+
+ g_object_notify_by_pspec(G_OBJECT(grid), _tiling_grid_properties[PROP_EMPTY_TOP + border]);
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* REDIMENSIONNEMENT DE ZONES POUR PANNEAUX */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* start_x = pointe de départ sur l'axe des abscisses. *
+* start_y = pointe de départ sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Initie un redimensionnement par drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_begin(GtkGestureDrag *gesture, double start_x, double start_y, GtkTilingGrid *grid)
+{
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED);
+
+ grid->panning = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = zone d'affichage en tuiles à manipuler. *
+* border = sélection de la zone à considérer. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* *
+* Description : Applique l'effet d'un redimensionnement drag-and-drop donné. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_update(GtkTilingGrid *grid, TilingGridBorder border, double offset_x, double offset_y)
+{
+ GtkDockStation *station; /* Station entière */
+ int request; /* Taille requise */
+
+ /* Sélection de la poignée adaptée */
+
+ switch (border)
+ {
+ case TGB_TOP:
+ station = grid->top_station;
+ break;
+
+ case TGB_LEFT:
+ station = grid->left_station;
+ break;
+
+ case TGB_RIGHT:
+ station = grid->right_station;
+ break;
+
+ case TGB_BOTTOM:
+ station = grid->bottom_station;
+ break;
+
+ }
+
+ /* Détermination d'une nouvelle position et application */
+
+ switch (border)
+ {
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_get(G_OBJECT(station), "height-request", &request, NULL);
+ break;
+
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_get(G_OBJECT(station), "width-request", &request, NULL);
+ break;
+
+ }
+
+ switch (border)
+ {
+ case TGB_TOP:
+ request += offset_y;
+ break;
+
+ case TGB_LEFT:
+ request += offset_x;
+ break;
+
+ case TGB_RIGHT:
+ request += -offset_x;
+ break;
+
+ case TGB_BOTTOM:
+ request += -offset_y;
+ break;
+
+ }
+
+ if (request > 0)
+ {
+ switch (border)
+ {
+ case TGB_TOP:
+ case TGB_BOTTOM:
+ g_object_set(G_OBJECT(station), "height-request", request, NULL);
+ break;
+
+ case TGB_LEFT:
+ case TGB_RIGHT:
+ g_object_set(G_OBJECT(station), "width-request", request, NULL);
+ break;
+
+ }
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_top_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_TOP, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_left_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_LEFT, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_right_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_RIGHT, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement sur l'axe des abscisses. *
+* offset_y = déplacement sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Actualise l'effet d'un redimensionnement drag-and-drop. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_bottom_gesture_drag_update(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ gtk_tiling_grid_on_gesture_drag_update(grid, TGB_BOTTOM, offset_x, offset_y);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : gesture = encadrement de déplacement à l'origine de l'appel. *
+* offset_x = déplacement final sur l'axe des abscisses. *
+* offset_y = déplacement final sur l'axe des ordonnées. *
+* grid = gestionnaire de placement en tuile concerné. *
+* *
+* Description : Clôture un drag-and-drop de redimensionnement. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_on_gesture_drag_end(GtkGestureDrag *gesture, double offset_x, double offset_y, GtkTilingGrid *grid)
+{
+ if (!grid->panning)
+ gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_DENIED);
+ else
+ grid->panning = false;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ grid = GTK_TILING_GRID(object);
+
+ switch (prop_id)
+ {
+ case PROP_LAYOUT:
+ if (grid->layout != g_value_get_flags(value))
+ {
+ grid->layout = g_value_get_flags(value);
+
+ apply_tiling_grid_layout(GTK_GRID(grid), grid->layout, (GtkWidget *[]) {
+ GTK_WIDGET(grid->top), GTK_WIDGET(grid->left),
+ GTK_WIDGET(grid->right), GTK_WIDGET(grid->bottom)
+ });
+
+ g_object_notify_by_pspec(object, pspec);
+
+ }
+ break;
+
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_TOP:
+ gtk_tiling_grid_set_visible(grid, TGB_TOP, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_LEFT:
+ gtk_tiling_grid_set_visible(grid, TGB_LEFT, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_RIGHT:
+ gtk_tiling_grid_set_visible(grid, TGB_RIGHT, g_value_get_boolean(value));
+ break;
+
+ case PROP_VISIBLE_BOTTOM:
+ gtk_tiling_grid_set_visible(grid, TGB_BOTTOM, g_value_get_boolean(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiling_grid_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkTilingGrid *grid; /* Version spécialisée */
+
+ grid = GTK_TILING_GRID(object);
+
+ switch (prop_id)
+ {
+ case PROP_EMPTY_TOP:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->top_station));
+ break;
+
+ case PROP_EMPTY_LEFT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->left_station));
+ break;
+
+ case PROP_EMPTY_RIGHT:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->right_station));
+ break;
+
+ case PROP_EMPTY_BOTTOM:
+ g_value_set_boolean(value, gtk_dock_station_is_empty(grid->bottom_station));
+ break;
+
+ case PROP_VISIBLE_TOP:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_TOP));
+ break;
+
+ case PROP_VISIBLE_LEFT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_LEFT));
+ break;
+
+ case PROP_VISIBLE_RIGHT:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_RIGHT));
+ break;
+
+ case PROP_VISIBLE_BOTTOM:
+ g_value_set_boolean(value, gtk_tiling_grid_get_visible(grid, TGB_BOTTOM));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* FORME GENERIQUE DE MISE EN DISPOSITION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : grid = composant GTK dont le contenu est à arranger. *
+* options = options de mise en place. *
+* panels = liste organisée de composants à déplacer. *
+* *
+* Description : Met en place une disposition particulière de panneaux. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void apply_tiling_grid_layout(GtkGrid *grid, LayoutReachOptions options, GtkWidget *panels[TGB_COUNT])
+{
+ int top_panel_span; /* Etendue d'un composant #1 */
+ int left_panel_span; /* Etendue d'un composant #2 */
+ int right_panel_span; /* Etendue d'un composant #3 */
+ int bottom_panel_span; /* Etendue d'un composant #4 */
+ int top_panel_column; /* Position de composant #1 */
+ int left_panel_row; /* Position de composant #2 */
+ int right_panel_row; /* Position de composant #3 */
+ int bottom_panel_column; /* Position de composant #4 */
+ GtkLayoutManager *layout; /* Gestionnaire de disposition */
+ GtkGridLayoutChild *top_panel_layout; /* Disposition de composant #1 */
+ GtkGridLayoutChild *left_panel_layout; /* Disposition de composant #2 */
+ GtkGridLayoutChild *right_panel_layout; /* Disposition de composant #3 */
+ GtkGridLayoutChild *bottom_panel_layout;/* Disposition de composant #4 */
+
+ /* Calcul des placements */
+
+ top_panel_span = 3;
+ left_panel_span = 3;
+ right_panel_span = 3;
+ bottom_panel_span = 3;
+
+ if (options & LRO_LEFT_TOP_REACH)
+ {
+ top_panel_column = 1;
+ top_panel_span--;
+ left_panel_row = 0;
+ }
+ else
+ {
+ top_panel_column = 0;
+ left_panel_row = 1;
+ left_panel_span--;
+ }
+
+ if (options & LRO_LEFT_BOTTOM_REACH)
+ {
+ bottom_panel_column = 1;
+ bottom_panel_span--;
+ }
+ else
+ {
+ left_panel_span--;
+ bottom_panel_column = 0;
+ }
+
+ if (options & LRO_RIGHT_TOP_REACH)
+ {
+ top_panel_span--;
+ right_panel_row = 0;
+ }
+ else
+ {
+ right_panel_row = 1;
+ right_panel_span--;
+ }
+
+ if (options & LRO_RIGHT_BOTTOM_REACH)
+ bottom_panel_span--;
+ else
+ right_panel_span--;
+
+ /* Mise en application des contraintes */
+
+ layout = gtk_widget_get_layout_manager(GTK_WIDGET(grid));
+
+ top_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_TOP]));
+ left_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_LEFT]));
+ right_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_RIGHT]));
+ bottom_panel_layout = GTK_GRID_LAYOUT_CHILD(gtk_layout_manager_get_layout_child(layout, panels[TGB_BOTTOM]));
+
+ g_object_set(G_OBJECT(top_panel_layout),
+ "column", top_panel_column,
+ "column-span", top_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(left_panel_layout),
+ "row", left_panel_row,
+ "row-span", left_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(right_panel_layout),
+ "row", right_panel_row,
+ "row-span", right_panel_span,
+ NULL);
+
+ g_object_set(G_OBJECT(bottom_panel_layout),
+ "column", bottom_panel_column,
+ "column-span", bottom_panel_span,
+ NULL);
+
+ gtk_layout_manager_layout_changed(layout);
+
+}
diff --git a/src/gtkext/tiledgrid.h b/src/gtkext/grid.h
index 539e248..fd98035 100644
--- a/src/gtkext/tiledgrid.h
+++ b/src/gtkext/grid.h
@@ -2,7 +2,7 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
* tiledgrid.h - prototypes pour un composant d'affichage avec des chemins vers les composants contenus
*
- * Copyright (C) 2018-2019 Cyrille Bagard
+ * Copyright (C) 2018-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,10 +21,81 @@
*/
-#ifndef _GTKEXT_TILEDGRID_H
-#define _GTKEXT_TILEDGRID_H
+#ifndef _GTKEXT_GRID_H
+#define _GTKEXT_GRID_H
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+#include "panel.h"
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_TILING_GRID (gtk_tiling_grid_get_type())
+
+DECLARE_GTYPE(GtkTilingGrid, gtk_tiling_grid, GTK, TILING_GRID);
+
+
+/* Crée une nouvelle instance de conteneur avec tuiles. */
+GtkWidget *gtk_tiling_grid_new(void);
+
+/* Liste des zones de bordure */
+typedef enum _TilingGridBorder /*< skip (glib-mkenums) >*/
+{
+ TGB_TOP, /* Zone supérieure */
+ TGB_LEFT, /* Zone de gauche */
+ TGB_RIGHT, /* Zone de droite */
+ TGB_BOTTOM, /* Zone inférieure */
+
+} TilingGridBorder;
+
+/**
+ * Fixe le nombre de combinaisons sans le rendre visible dans l'énumération.
+ */
+#define TGB_COUNT (TGB_BOTTOM + 1)
+
+/* Affiche ou masque une zone du conteneur en tuiles. */
+void gtk_tiling_grid_set_visible(GtkTilingGrid *, TilingGridBorder, bool);
+
+/* Fournit la visibilité d'une zone du conteneur en tuiles. */
+bool gtk_tiling_grid_get_visible(GtkTilingGrid *, TilingGridBorder);
+
+/* Ajoute un panneau à un conteneur en tuiles. */
+void gtk_tiling_grid_add_panel(GtkTilingGrid *, GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_tiling_grid_notify_new_main_panel_state(const GtkTilingGrid *, GtkTiledPanel *, bool);
+
+
+
+/* --------------------- FORME GENERIQUE DE MISE EN DISPOSITION --------------------- */
+
+
+/* Options de dispositions cumulables */
+typedef enum _LayoutReachOptions /*< flags (glib-mkenums) >*/
+{
+ LRO_NONE = (0 << 0), /* Aucune atteinte des bords */
+ LRO_LEFT_TOP_REACH = (1 << 0), /* Atteinte du bord haut à G. */
+ LRO_LEFT_BOTTOM_REACH = (1 << 1), /* Atteinte du bord bas à G. */
+ LRO_RIGHT_TOP_REACH = (1 << 2), /* Atteinte du bord haut à D. */
+ LRO_RIGHT_BOTTOM_REACH = (1 << 3), /* Atteinte du bord bas à D. */
+
+} LayoutReachOptions;
+
+/* Met en place une disposition particulière de panneaux. */
+void apply_tiling_grid_layout(GtkGrid *, LayoutReachOptions, GtkWidget *[TGB_COUNT]);
+
+
+
+
+
+
+
+#if 0
+
#include <gtk/gtk.h>
@@ -81,5 +152,7 @@ void gtk_tiled_grid_restore_positions(const GtkTiledGrid *, GGenConfig *);
void gtk_tiled_grid_save_positions(const GtkTiledGrid *, GGenConfig *);
+#endif
+
-#endif /* _GTKEXT_TILEDGRID_H */
+#endif /* _GTKEXT_GRID_H */
diff --git a/src/gtkext/grid.ui b/src/gtkext/grid.ui
new file mode 100644
index 0000000..b14ced2
--- /dev/null
+++ b/src/gtkext/grid.ui
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkTilingGrid" parent="GtkGrid">
+
+ <!-- Zone supérieure -->
+
+ <child>
+ <object class="GtkRevealer" id="top">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkDockStation" id="top_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">30</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="top_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_top_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de gauche -->
+
+ <child>
+ <object class="GtkRevealer" id="left">
+ <property name="transition-type">slide-right</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkDockStation" id="left_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator" id="left_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_left_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone centrale -->
+
+ <child>
+ <object class="GtkDockStation" id="main_station">
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone de droite -->
+
+ <child>
+ <object class="GtkRevealer" id="right">
+ <property name="transition-type">slide-left</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+
+ <child>
+ <object class="GtkSeparator" id="right_handle">
+ <property name="orientation">horizontal</property>
+ <property name="width-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_right_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="right_station">
+ <property name="orientation">vertical</property>
+ <property name="hexpand">false</property>
+ <property name="vexpand">true</property>
+ <property name="width-request">300</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">2</property>
+ <property name="row">1</property>
+ </layout>
+ </object>
+ </child>
+
+ <!-- Zone inférieure -->
+
+ <child>
+ <object class="GtkRevealer" id="bottom">
+ <property name="transition-type">slide-up</property>
+ <property name="reveal-child">false</property>
+
+ <child>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+
+ <child>
+ <object class="GtkSeparator" id="bottom_handle">
+ <property name="orientation">vertical</property>
+ <property name="height-request">5</property>
+
+ <child>
+ <object class="GtkGestureDrag">
+ <property name="propagation-phase">capture</property>
+ <signal name="drag-begin" handler="gtk_tiling_grid_on_gesture_drag_begin"/>
+ <signal name="drag-update" handler="gtk_tiling_grid_on_bottom_gesture_drag_update"/>
+ <signal name="drag-end" handler="gtk_tiling_grid_on_gesture_drag_end"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkDockStation" id="bottom_station">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">false</property>
+ <property name="height-request">250</property>
+ <signal name="panel-docked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ <signal name="panel-undocked" handler="gtk_tiling_grid_on_panel_un_docked"/>
+ </object>
+ </child>
+
+ </object>
+ </child>
+
+ <layout>
+ <property name="column">0</property>
+ <property name="row">2</property>
+ <property name="column-span">3</property>
+ </layout>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c
deleted file mode 100644
index 1757542..0000000
--- a/src/gtkext/gtkdockstation.c
+++ /dev/null
@@ -1,467 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkdockstation.c - manipulation et l'affichage de composants rassemblés
- *
- * Copyright (C) 2012-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkdockstation.h"
-
-
-#include <malloc.h>
-#include <string.h>
-
-
-#include "easygtk.h"
-#include "../core/params.h"
-#include "../common/extstr.h"
-#include "../glibext/chrysamarshal.h"
-
-
-
-/* Procède à l'initialisation de l'afficheur concentré. */
-static void gtk_dock_station_class_init(GtkDockStationClass *);
-
-/* Procède à l'initialisation du support d'affichage concentré. */
-static void gtk_dock_station_init(GtkDockStation *);
-
-/* Met à jour le titre du support de panneaux concentrés. */
-static gboolean gtk_dock_station_switch_panel(GtkNotebook *, gpointer *, guint, GtkDockStation *);
-
-
-
-
-/* Révèle ou cache la zone de recherches. */
-static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *);
-
-/* Demande l'apparition d'un menu pour inclure des composants. */
-static void on_click_for_menu(GtkButton *, GtkDockStation *);
-
-/* Demande la disparition du composant courant. */
-static void on_click_for_close(GtkButton *, GtkDockStation *);
-
-
-
-
-
-
-/* Détermine le type du composant d'affichage concentré. */
-G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_NOTEBOOK)
-
-
-/******************************************************************************
-* *
-* Paramètres : class = classe GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation de l'afficheur concentré. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_dock_station_class_init(GtkDockStationClass *class)
-{
- g_signal_new("dock-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, dock_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("undock-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, undock_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("switch-widget",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, switch_widget),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("menu-requested",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, menu_requested),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
- g_signal_new("close-requested",
- GTK_TYPE_DOCK_STATION,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkDockStationClass, close_requested),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = composant GTK à initialiser. *
-* *
-* Description : Procède à l'initialisation du support d'affichage concentré. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_dock_station_init(GtkDockStation *station)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- GtkWidget *hbox; /* Division supérieure */
- GtkWidget *button; /* Bouton de contrôle */
-
- notebook = GTK_NOTEBOOK(station);
-
- gtk_notebook_set_show_border(notebook, FALSE);
- gtk_notebook_set_scrollable(notebook, TRUE);
-
- /* Définition de la zone de contrôle */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_set_valign(hbox, GTK_ALIGN_CENTER);
- gtk_widget_set_margin_end(hbox, 8);
- gtk_widget_show(hbox);
-
- button = qck_create_toggle_button_with_named_img(G_OBJECT(station), "search",
- "edit-find-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_toggle_revealer), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- button = qck_create_button_with_named_img(G_OBJECT(station), "menu",
- "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_menu), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- button = qck_create_button_with_named_img(G_OBJECT(station), "close",
- "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL,
- G_CALLBACK(on_click_for_close), station);
- gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
- gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
-
- gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END);
-
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée un nouveau composant pour support d'affichage concentré.*
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkWidget *gtk_dock_station_new(void)
-{
- return g_object_new(GTK_TYPE_DOCK_STATION, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : notebook = support à l'origine de la mise à jour. *
-* page = onglet mis en avant. *
-* index = indice de l'onglet actuellement actif. *
-* station = conteneur de gestion supérieur. *
-* *
-* Description : Met à jour le titre du support de panneaux concentrés. *
-* *
-* Retour : TRUE ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *page, guint index, GtkDockStation *station)
-{
- GtkWidget *widget; /* Panneau concerné */
- GtkDockable *dockable; /* Elément encapsulé */
- GtkWidget *button; /* Bouton de contrôle */
-
- widget = gtk_notebook_get_nth_page(notebook, index);
-
- dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
-
- /* Mise à jour des boutons utilisables */
-
- button = GTK_WIDGET(g_object_get_data(G_OBJECT(station), "search"));
-
- if (gtk_dockable_can_search(dockable))
- gtk_widget_show(button);
- else
- gtk_widget_hide(button);
-
- /* Remontée du changement d'onglet */
-
- g_signal_emit_by_name(station, "switch-widget", widget);
-
- return TRUE;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* dockable = nouvel élément à intégrer. *
-* *
-* Description : Ajoute un paquet d'informations à l'affichage centralisé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-#include "gtkdisplaypanel.h"
-#include "../gui/panels/history.h"
-void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockable)
-{
- GtkWidget *widget; /* Composant GTK à intégrer */
- char *name; /* Nom à donner à l'onglet */
- char *desc; /* Description à y associer */
- int max; /* Taille maximale des titres */
- GtkWidget *label; /* Etiquette d'onglet */
- GtkNotebook *notebook; /* Autre version du composant */
-
-
-
-
-
-
-
- /* Récupération des éléments utiles */
-
- widget = gtk_dockable_build_widget(dockable);
-
- //widget = gtk_button_new_with_label("123");
- gtk_widget_show(widget);
-
-
- g_object_set_data(G_OBJECT(widget), "dockable", dockable);
-
- name = gtk_dockable_get_name(dockable);
- desc = gtk_dockable_get_desc(dockable);
-
- /* Mise en place de la page */
-
- if (!g_generic_config_get_value(get_main_configuration(), MPK_ELLIPSIS_TAB, &max))
- max = -1;
-
- name = ellipsis(name, max);
- label = qck_create_label(NULL, NULL, name);
- free(name);
-
- notebook = GTK_NOTEBOOK(station);
-
- if (gtk_notebook_get_n_pages(notebook) > 0)
- g_signal_handlers_disconnect_by_func(notebook,
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- gtk_notebook_append_page(notebook, widget, label);
-
- gtk_widget_set_tooltip_text(label, desc);
-
- free(desc);
-
- if (gtk_notebook_get_n_pages(notebook) > 1)
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- /* Lancement des mises à jour */
-
- if (gtk_notebook_get_n_pages(notebook) > 1)
- gtk_notebook_set_current_page(notebook, -1);
-
- //g_signal_emit_by_name(station, "dock-widget", widget);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* widget = nouvel élément à intégrer. *
-* *
-* Description : Change le contenu de l'onglet courant uniquement. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *widget)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- gint index; /* Indice de l'onglet actif */
- GtkWidget *old; /* Ancien composant */
- GtkWidget *label; /* Etiquette d'onglet */
- char *str; /* Titre des prochaines fois */
-
- notebook = GTK_NOTEBOOK(station);
-
- index = gtk_notebook_get_current_page(notebook);
-
- g_signal_handlers_disconnect_by_func(notebook,
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
- old = gtk_notebook_get_nth_page(notebook, index);
- label = gtk_notebook_get_tab_label(notebook, old);
-
- g_object_ref(G_OBJECT(label));
- str = g_object_get_data(G_OBJECT(old), "title");
-
- gtk_notebook_remove_page(notebook, index);
- gtk_notebook_insert_page(notebook, widget, label, index);
-
- g_object_unref(G_OBJECT(label));
- g_object_set_data(G_OBJECT(widget), "title", str);
-
- gtk_notebook_set_current_page(notebook, index);
-
- g_signal_connect(notebook, "switch-page",
- G_CALLBACK(gtk_dock_station_switch_panel), station);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : station = plateforme GTK à compléter. *
-* dockable = élément existant à retirer. *
-* *
-* Description : Retire un paquet d'informations de l'affichage centralisé. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_dock_station_remove_dockable(GtkDockStation *station, GtkDockable *dockable)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- GtkWidget *widget; /* Composant GTK à retirer */
- gint index; /* Indice de l'onglet visé */
-
- notebook = GTK_NOTEBOOK(station);
-
- widget = gtk_dockable_decompose(dockable, NULL);
-
- index = gtk_notebook_page_num(notebook, widget);
-
- gtk_notebook_remove_page(notebook, index);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Révèle ou cache la zone de recherches. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station)
-{
- GtkNotebook *notebook; /* Autre version du composant */
- gint index; /* Indice de l'onglet courant */
- GtkWidget *widget; /* Panneau concerné */
- GtkDockable *dockable; /* Elément encapsulé */
-
- notebook = GTK_NOTEBOOK(station);
-
- index = gtk_notebook_get_current_page(notebook);
- widget = gtk_notebook_get_nth_page(notebook, index);
-
- dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable"));
-
- gtk_dockable_toggle_revealer(dockable, widget, gtk_toggle_button_get_active(button));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Demande l'apparition d'un menu pour inclure des composants. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_click_for_menu(GtkButton *button, GtkDockStation *station)
-{
- g_signal_emit_by_name(station, "menu-requested", button);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : button = bouton à l'origine de la procédure. *
-* station = station d'accueil pour différents composants. *
-* *
-* Description : Demande la disparition du composant courant. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_click_for_close(GtkButton *button, GtkDockStation *station)
-{
- g_signal_emit_by_name(station, "close-requested", button);
-
-}
diff --git a/src/gtkext/gtkstatusstack.c b/src/gtkext/gtkstatusstack.c
deleted file mode 100644
index fe4e4d5..0000000
--- a/src/gtkext/gtkstatusstack.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkstatusstack.c - empilement d'informations de statut
- *
- * Copyright (C) 2015-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "gtkstatusstack.h"
-
-
-#include <assert.h>
-#include <inttypes.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include <i18n.h>
-
-
-#include "easygtk.h"
-#include "../gui/agroup.h"
-#include "../format/format.h"
-
-
-
-/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
-
-
-/* Navigation au sein d'assemblage */
-typedef struct _assembly_info assembly_info;
-
-/* Mémorisation des progressions */
-typedef struct _progress_info progress_info;
-
-
-/* Abstration d'une gestion de barre de statut (instance) */
-struct _GtkStatusStack
-{
- GtkBox parent; /* A laisser en premier */
-
- GtkStack *main; /* Pile d'informations associée*/
-
- GSourceFunc def_source; /* Appel en fin d'activité */
-
- GObject *asm_ref; /* Espace de référencements #1 */
- assembly_info *asm_info; /* Informations courantes #1 */
-
- GObject *prog_ref; /* Espace de référencements #2 */
- progress_info *prog_info; /* Informations courantes #2 */
-
-};
-
-/* Abstration d'une gestion de barre de statut (classe) */
-struct _GtkStatusStackClass
-{
- GtkBoxClass parent; /* A laisser en premier */
-
-};
-
-
-/* Initialise la classe des barres de statut améliorées. */
-static void gtk_status_stack_class_init(GtkStatusStackClass *);
-
-/* Initialise une instance de barre de statut améliorée. */
-static void gtk_status_stack_init(GtkStatusStack *);
-
-/* Supprime toutes les références externes. */
-static void gtk_status_stack_dispose(GtkStatusStack *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_status_stack_finalize(GtkStatusStack *);
-
-
-
-/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
-
-
-/* Navigation au sein d'assemblage */
-struct _assembly_info
-{
- bool reset; /* Réinitialisation */
-
- mrange_t current; /* Emplacement correspondant */
-
- char *segment; /* Segment d'appartenance */
-
- VMPA_BUFFER(phys); /* Localisation physique */
- VMPA_BUFFER(virt); /* Localisation virtuelle */
-
- char *symbol; /* Eventuel symbole concerné */
-
- const char *encoding; /* Encodage de l'instruction */
- phys_t size; /* Taille de l'instruction */
-
-};
-
-
-/* Supprime l'empreinte mémoire d'informations d'assemblage. */
-static void reset_assembly_info(assembly_info *);
-
-/* Construit une barre d'état pour language d'assemblage. */
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *);
-
-/* Réagit à un redimensionnement de la barre de désassemblage. */
-static void on_size_allocate_for_asm_status(GtkWidget *, GdkRectangle *, GObject *);
-
-/* Réagit à un clic sur l'icône de zoom. */
-static void on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GdkEventButton *, GtkStatusStack *);
-
-/* S'assure de l'affichage à jour de la partie "assemblage". */
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *);
-
-
-
-/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */
-
-
-/* Informations de progression */
-typedef struct _progress_status
-{
- activity_id_t id; /* Identifiant unique */
-
- char *message; /* Indication à faire valoir */
-
- unsigned long current; /* Position courante */
- unsigned long max; /* Couverture à parcourir */
-
- double last_updated; /* Dernière valeur poussée */
-
-} progress_status;
-
-/* Mémorisation des progressions */
-struct _progress_info
-{
- activity_id_t generator; /* Générateur de séquence */
-
- progress_status *statuses; /* Statuts de progression */
- size_t count; /* Nombre de ces statuts */
- GMutex access; /* Accès à la pile */
-
- guint tag; /* Identifiant de mise à jour */
-
-};
-
-
-#define PROGRESS_SIZE 200
-
-
-/* Supprime l'empreinte mémoire d'informations d'activité. */
-static void reset_progress_info(progress_info *);
-
-/* Construit une barre d'état pour un suivi d'activité. */
-static GtkWidget *build_progress_status_stack(GtkStatusStack *);
-
-/* S'assure de l'affichage à jour de la partie "activité". */
-static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION EXTERIEURE DE LA BARRE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type de la barre de statut améliorée. */
-G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX)
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe des barres de statut améliorées. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_class_init(GtkStatusStackClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance de barre de statut améliorée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_init(GtkStatusStack *stack)
-{
- GtkWidget *layer; /* Couche à empiler */
-
- gtk_orientable_set_orientation(GTK_ORIENTABLE(stack), GTK_ORIENTATION_HORIZONTAL);
-
- stack->main = GTK_STACK(gtk_stack_new());
- gtk_widget_show(GTK_WIDGET(stack->main));
- gtk_box_pack_start(GTK_BOX(stack), GTK_WIDGET(stack->main), TRUE, TRUE, 8);
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- layer = build_assembly_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "asm_info");
-
- stack->asm_ref = G_OBJECT(layer);
- stack->asm_info = (assembly_info *)calloc(1, sizeof(assembly_info));
-
- reset_assembly_info(stack->asm_info);
-
- layer = build_progress_status_stack(stack);
- gtk_stack_add_named(stack->main, layer, "prog_info");
-
- stack->prog_ref = G_OBJECT(layer);
- stack->prog_info = (progress_info *)calloc(1, sizeof(progress_info));
-
- reset_progress_info(stack->prog_info);
-
- gtk_status_stack_reset_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_dispose(GtkStatusStack *stack)
-{
- G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : view = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_status_stack_finalize(GtkStatusStack *stack)
-{
- reset_assembly_info(stack->asm_info);
- free(stack->asm_info);
-
- reset_progress_info(stack->prog_info);
- free(stack->prog_info);
-
- G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une nouvelle instance de barre de statut. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkStatusStack *gtk_status_stack_new(void)
-{
- GtkStatusStack *result; /* Instance à retourner */
-
- result = g_object_new(GTK_TYPE_STATUS_STACK, NULL);
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : info = informations à réinitialiser. *
-* *
-* Description : Supprime l'empreinte mémoire d'informations d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_assembly_info(assembly_info *info)
-{
- info->reset = true;
-
- if (info->segment != NULL)
- {
- free(info->segment);
- info->segment = NULL;
- }
-
- if (info->symbol != NULL)
- {
- free(info->symbol);
- info->symbol = NULL;
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = composant global en cours de construction. *
-* *
-* Description : Construit une barre d'état pour language d'assemblage. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkWidget *build_assembly_status_stack(GtkStatusStack *stack)
-{
- GtkWidget *result; /* Support à retourner */
- GObject *ref; /* Espace de référencements */
- GtkWidget *hbox; /* Sous-division horizontale */
- GtkWidget *label; /* Etiquette pour impression */
- GtkWidget *zoom; /* Sélection du zoom courant */
-
- result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show(result);
-
- ref = G_OBJECT(result);
-
- g_signal_connect(result, "size-allocate", G_CALLBACK(on_size_allocate_for_asm_status), ref);
-
- /* Première partie : navigation */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 16);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, TRUE, TRUE, 8);
-
- label = qck_create_label(ref, "segment", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "phys", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "virt", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "offset", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Seconde partie : architecture */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- g_object_set_data(ref, "arch_box", hbox);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, TRUE, 8);
-
- label = qck_create_label(ref, "arch", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = qck_create_label(ref, "size", NULL);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- /* Troisième partie : affichage */
-
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8);
- gtk_widget_show(hbox);
- gtk_box_pack_start(GTK_BOX(result), hbox, FALSE, FALSE, 8);
-
- zoom = qck_create_entry(ref, "zoom", "100%");
- gtk_entry_set_icon_from_icon_name(GTK_ENTRY(zoom), GTK_ENTRY_ICON_SECONDARY, "go-up-symbolic");
-
- g_signal_connect(zoom, "focus-in-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "focus-out-event", G_CALLBACK(track_focus_change_in_text_area), NULL);
- g_signal_connect(zoom, "icon-press", G_CALLBACK(on_zoom_icon_press), stack);
-
- gtk_box_pack_start(GTK_BOX(hbox), zoom, FALSE, TRUE, 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : widget = composant graphique qui vient d'évoluer. *
-* allocation = espace réservé pour le composant visé. *
-* ref = espace de référencement global. *
-* *
-* Description : Réagit à un redimensionnement de la barre de désassemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_size_allocate_for_asm_status(GtkWidget *widget, GdkRectangle *allocation, GObject *ref)
-{
- GtkWidget *hbox; /* Sous-division horizontale */
-
- hbox = GTK_WIDGET(g_object_get_data(ref, "arch_box"));
-
- gtk_widget_set_size_request(hbox, (allocation->width * 40) / 100, -1);
-
- /**
- * On intervient après que le containeur soit passé collecter les tailles
- * de ses enfants lors de son redimensionnement.
- *
- * Donc on force un prise en compte des changements.
- */
- gtk_container_check_resize(GTK_CONTAINER(widget));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : entry = zone de texte visée par la procédure. *
-* icon_pos = position de l'image associée à l'entrée. *
-* event = informations liées à l'événement. *
-* stack = composant graphique de gestion des statuts. *
-* *
-* Description : Réagit à un clic sur l'icône de zoom. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GdkEventButton *event, GtkStatusStack *stack)
-{
- GtkWidget *popup; /* Popup à faire surgir */
- GdkRectangle rect; /* Zone précise à cibler */
-
- if (event->button != GDK_BUTTON_PRIMARY)
- return;
-
- popup = gtk_popover_new(GTK_WIDGET(entry));
-
- gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
- gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
-
- gtk_widget_show(popup);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* range = emplacement à mettre en valeur. *
-* segment = zone de binaire d'appartenance. *
-* symbol = éventuelle position par rapport à un symbole. *
-* encoding = encodage d'une éventuelle instruction ou NULL. *
-* *
-* Description : Actualise les informations liées une position d'assemblage. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *encoding)
-{
- assembly_info *info; /* Informations à constituer */
- const vmpa2t *addr; /* Localisation de départ */
- phys_t size; /* Taille de l'emplacement */
-
- info = stack->asm_info;
-
- /* Bascule vers une zone courante nouvelle ? */
-
- addr = get_mrange_addr(range);
- size = get_mrange_length(range);
-
- if (cmp_mrange(&info->current, range) == 0
- && info->size == size
- && info->encoding == encoding)
- goto useless;
-
- /* Réinitialisation */
-
- reset_assembly_info(info);
-
- copy_mrange(&info->current, range);
-
- /* Zone d'appartenance */
-
- info->segment = strdup(segment);
-
- /* Adresses de base */
-
- vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
-
- vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
-
- info->encoding = encoding;
- info->size = size;
-
- /* Symbole concerné */
-
- if (symbol != NULL)
- info->symbol = strdup(symbol);
-
- /* Nettoyage et conclusion */
-
- info->reset = false;
-
- gtk_status_stack_show_current_location(stack);
-
- useless:
-
- ;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* *
-* Description : Réinitialise les informations associées une position. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_reset_current_location(GtkStatusStack *stack)
-{
- assembly_info *info; /* Informations à constituer */
-
- info = stack->asm_info;
-
- reset_assembly_info(info);
-
- gtk_status_stack_show_current_location(stack);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = pile de statuts à manipuler. *
-* *
-* Description : S'assure de l'affichage à jour de la partie "assemblage". *
-* *
-* Retour : G_SOURCE_REMOVE pour une exécution unique. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_status_stack_show_current_location(GtkStatusStack *stack)
-{
- GObject *ref; /* Espace de référencements */
- assembly_info *info; /* Informations à consulter */
- GtkLabel *label; /* Etiquette à actualiser */
- char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
- char *content; /* Contenu dynamique */
-
- stack->def_source = (GSourceFunc)gtk_status_stack_show_current_location;
-
- gtk_stack_set_visible_child_name(stack->main, "asm_info");
-
- ref = stack->asm_ref;
- info = stack->asm_info;
-
- /* Première partie : navigation */
-
- if (info->reset)
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "segment"));
- gtk_label_set_text(label, info->segment);
-
- snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
-
- label = GTK_LABEL(g_object_get_data(ref, "phys"));
- gtk_label_set_text(label, raw_pos);
-
- snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
-
- label = GTK_LABEL(g_object_get_data(ref, "virt"));
- gtk_label_set_text(label, raw_pos);
-
- label = GTK_LABEL(g_object_get_data(ref, "offset"));
- gtk_label_set_text(label, info->symbol != NULL ? info->symbol : "");
-
- }
-
- /* Seconde partie : architecture */
-
- if (info->reset || info->encoding == NULL || info->size == VMPA_NO_PHYSICAL)
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, NULL);
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, NULL);
-
- }
- else
- {
- label = GTK_LABEL(g_object_get_data(ref, "arch"));
- gtk_label_set_text(label, info->encoding);
-
- if (info->size > 1)
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("bytes"));
- else
- asprintf(&content, "%" PRIu64 " %s", (uint64_t)info->size, _("byte"));
-
- label = GTK_LABEL(g_object_get_data(ref, "size"));
- gtk_label_set_text(label, content);
-
- free(content);
-
- }
-
- return G_SOURCE_REMOVE;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* STATUT DES SUIVIS D'ACTIVITE */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : info = informations à réinitialiser. *
-* *
-* Description : Supprime l'empreinte mémoire d'informations d'activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void reset_progress_info(progress_info *info)
-{
- size_t i; /* Boucle de parcours */
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = 0;
-
- for (i = 0; i < info->count; i++)
- {
- if (info->statuses[i].message != NULL)
- free(info->statuses[i].message);
- }
-
- if (info->statuses != NULL)
- {
- free(info->statuses);
- info->statuses = NULL;
- }
-
- info->count = 0;
-
- g_mutex_init(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = composant global en cours de construction. *
-* *
-* Description : Construit une barre d'état pour un suivi d'activité. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static GtkWidget *build_progress_status_stack(GtkStatusStack *stack)
-{
- GtkWidget *result; /* Support à retourner */
- GObject *ref; /* Espace de référencements */
- GtkWidget *progress; /* Barre de progression */
- GtkWidget *label; /* Désignation de l'activité */
-
- result = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
- gtk_widget_show(result);
-
- ref = G_OBJECT(result);
-
- progress = gtk_progress_bar_new();
- g_object_set_data(ref, "progress", progress);
- gtk_widget_set_size_request(progress, PROGRESS_SIZE, -1);
- gtk_widget_set_valign(progress, GTK_ALIGN_CENTER);
- gtk_widget_show(progress);
- gtk_box_pack_start(GTK_BOX(result), progress, FALSE, TRUE, 8);
-
- label = qck_create_label(ref, "message", NULL);
- gtk_box_pack_start(GTK_BOX(result), label, TRUE, TRUE, 0);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* msg = nouveau message de statut à copier. *
-* max = taille de la plage à parcourir. *
-* *
-* Description : Démarre le suivi d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)
-{
- activity_id_t result; /* Numéro unique à renvoyer */
- progress_info *info; /* Informations à consulter */
- size_t new; /* Indice de l'activité créée */
-
- if (stack == NULL) return NO_ACTIVITY_ID;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- result = ++info->generator;
-
- new = info->count++;
-
- info->statuses = (progress_status *)realloc(info->statuses,
- info->count * sizeof(progress_status));
-
- info->statuses[new].id = result;
-
- /* Intitulé */
-
- if (msg == NULL)
- info->statuses[new].message = NULL;
- else
- info->statuses[new].message = strdup(msg);
-
- /* Valeur */
-
- info->statuses[new].current = 0;
- info->statuses[new].max = max;
- info->statuses[new].last_updated = 0;
-
- /* Actualisation */
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- g_mutex_unlock(&info->access);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* extra = nouvelle échéance supplémentaire des traitements. *
-* *
-* Description : Etend la portée des travaux d'une nouvelle activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_extend_activity(GtkStatusStack *stack, activity_id_t id, unsigned long extra)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- info->statuses[i].max += extra;
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* msg = nouveau message de statut à copier. *
-* *
-* Description : Actualise les informations concernant une activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_activity(GtkStatusStack *stack, activity_id_t id, const char *msg)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- bool msg_changed; /* Changement d'intitulé */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- /* Intitulé */
-
- if (info->statuses[i].message != NULL)
- {
- if (msg == NULL)
- msg_changed = true;
- else
- msg_changed = (strcmp(info->statuses[i].message, msg) != 0);
-
- free(info->statuses[i].message);
-
- }
- else
- msg_changed = (msg != NULL);
-
- if (msg == NULL)
- info->statuses[i].message = NULL;
- else
- info->statuses[i].message = strdup(msg);
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && msg_changed)
- {
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- }
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* id = identifiant de l'activité à cibler. *
-* inc = nouvelle valeur pour une progression donnée. *
-* *
-* Description : Actualise la progression d'une activité. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
- progress_status *status; /* Raccourci de confort */
- double new; /* Nouvelle progression */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- status = &info->statuses[i];
-
- /* Valeur */
-
- status->current += inc;
-
- new = (status->current * 1.0) / status->max;
-
- /* On n'actualise que le sommet de la pile */
-
- if ((i + 1) == info->count && (new - status->last_updated) > (1.0 / PROGRESS_SIZE))
- {
- status->last_updated = new;
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- }
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = barre de statut à actualiser. *
-* *
-* Description : Met fin au suivi d'une activité donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id)
-{
- progress_info *info; /* Informations à consulter */
- size_t i; /* Boucle de parcours */
-
- if (stack == NULL) return;
-
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- for (i = 0; i < info->count; i++)
- if (info->statuses[i].id == id)
- break;
-
- assert(i < info->count);
-
- if (info->tag != 0)
- g_source_remove(info->tag);
-
- if (info->statuses[i].message != NULL)
- free(info->statuses[i].message);
-
- if (info->count == 1)
- {
- free(info->statuses);
- info->statuses = NULL;
- }
- else
- {
- memmove(&info->statuses[i], &info->statuses[i + 1],
- (info->count - i - 1) * sizeof(progress_status));
-
- info->statuses = (progress_status *)realloc(info->statuses,
- (info->count - 1) * sizeof(progress_status));
-
- }
-
- info->count--;
-
- if (info->count == 0)
- {
- info->tag = 0;
- g_idle_add(stack->def_source, stack);
- }
- else
- info->tag = g_idle_add((GSourceFunc)gtk_status_stack_show_current_activity, stack);
-
- g_mutex_unlock(&info->access);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : stack = pile de statuts à manipuler. *
-* *
-* Description : S'assure de l'affichage à jour de la partie "activité". *
-* *
-* Retour : G_SOURCE_REMOVE pour une exécution unique. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static gboolean gtk_status_stack_show_current_activity(GtkStatusStack *stack)
-{
- GObject *ref; /* Espace de référencements */
- progress_info *info; /* Informations à consulter */
- progress_status *last; /* Dernier statut à traiter */
- GtkProgressBar *progress; /* Barre de progression */
- GtkLabel *label; /* Désignation de l'activité */
-
- if (!g_source_is_destroyed(g_main_current_source()))
- {
- gtk_stack_set_visible_child_name(stack->main, "prog_info");
-
- ref = stack->prog_ref;
- info = stack->prog_info;
-
- g_mutex_lock(&info->access);
-
- info->tag = 0;
-
- if (info->count > 0)
- {
- last = &info->statuses[info->count - 1];
-
- progress = GTK_PROGRESS_BAR(g_object_get_data(ref, "progress"));
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), (last->current * 1.0) / last->max);
-
- label = GTK_LABEL(g_object_get_data(ref, "message"));
- gtk_label_set_text(label, last->message);
-
- }
-
- g_mutex_unlock(&info->access);
-
- }
-
- return G_SOURCE_REMOVE;
-
-}
diff --git a/src/gtkext/helpers.h b/src/gtkext/helpers.h
new file mode 100644
index 0000000..3f8b3cd
--- /dev/null
+++ b/src/gtkext/helpers.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * helpers.h - prototypes pour la simplification des interactions de base avec GTK
+ *
+ * Copyright (C) 2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_HELPERS_H
+#define _GTKEXT_HELPERS_H
+
+
+#include <assert.h>
+#include <glib-object.h>
+
+
+
+/**
+ * Facilités de transmission de paramètres pour les fonctions de type
+ * gtk_widget_class_bind_template_callback_full() et gtk_builder_cscope_add_callback_symbol().
+ */
+
+#define BUILDER_CB(cb) \
+ #cb, G_CALLBACK(cb)
+
+
+
+#endif /* _GTKEXT_HELPERS_H */
diff --git a/src/gtkext/hexview.c b/src/gtkext/hexview.c
index 7363079..95b592e 100644
--- a/src/gtkext/hexview.c
+++ b/src/gtkext/hexview.c
@@ -37,17 +37,33 @@
/* ------------------------- BASES D'UN COMPOSANT GRAPHIQUE ------------------------- */
-/* Procède à l'initialisation de l'afficheur générique. */
+/* Liste des propriétés */
+
+typedef enum _HexViewProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_SHOW_OFFSETS, /* Affichage des positions */
+ PROP_CONTENT, /* Contenu binaire affiché */
+
+ N_PROPERTIES
+
+} HexViewProperty;
+
+static GParamSpec *_hex_view_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des afficheurs de tampons bruts. */
static void gtk_hex_view_class_init(GtkHexViewClass *);
-/* Procède à l'initialisation de l'afficheur générique. */
+/* Initialise une instance d'afficheur de tampons bruts. */
static void gtk_hex_view_init(GtkHexView *);
/* Supprime toutes les références externes. */
-static void gtk_hex_view_dispose(GtkHexView *);
+static void gtk_hex_view_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void gtk_hex_view_finalize(GtkHexView *);
+static void gtk_hex_view_finalize(GObject *);
/* Procède à l'actualisation de l'affichage d'un sous-composant. */
static void gtk_hex_view_dispatch_sub_snapshot(GtkWidget *, GtkSnapshot *, GtkWidget *);
@@ -57,14 +73,14 @@ static void gtk_hex_view_populate_cache(GtkHexView *);
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent);
-
-
-
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
-/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_hex_view_set_property(GObject *, guint, const GValue *, GParamSpec *);
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_hex_view_get_property(GObject *, guint, GValue *, GParamSpec *);
/* Prend acte de la taille allouée au composant d'affichage. */
static void gtk_hex_view_size_allocate(GtkWidget *, int, int, int);
@@ -90,7 +106,7 @@ G_DEFINE_TYPE(GtkHexView, gtk_hex_view, GTK_TYPE_BUFFER_VIEW);
* *
* Paramètres : class = classe GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur générique. *
+* Description : Initialise la classe des afficheurs de tampons bruts. *
* *
* Retour : - *
* *
@@ -105,12 +121,26 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
object = G_OBJECT_CLASS(class);
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_hex_view_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_hex_view_finalize;
+ object->dispose = gtk_hex_view_dispose;
+ object->finalize = gtk_hex_view_finalize;
+ object->set_property = gtk_hex_view_set_property;
+ object->get_property = gtk_hex_view_get_property;
+
+ _hex_view_properties[PROP_SHOW_OFFSETS] =
+ g_param_spec_boolean("show-offsets", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ _hex_view_properties[PROP_CONTENT] =
+ g_param_spec_object("content", NULL, NULL,
+ G_TYPE_BIN_CONTENT,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _hex_view_properties);
widget = GTK_WIDGET_CLASS(class);
- gtk_widget_class_set_css_name(widget, "GtkHexView");
+ gtk_widget_class_set_css_name(widget, "hexview");
g_type_ensure(GTK_TYPE_COMPOSING_AREA);
@@ -131,7 +161,7 @@ static void gtk_hex_view_class_init(GtkHexViewClass *class)
* *
* Paramètres : view = composant GTK à initialiser. *
* *
-* Description : Procède à l'initialisation de l'afficheur générique. *
+* Description : Initialise une instance d'afficheur de tampons bruts. *
* *
* Retour : - *
* *
@@ -167,12 +197,14 @@ static void gtk_hex_view_init(GtkHexView *view)
view->generator = NULL;
+ gtk_hex_view_create(view, NULL);
+
}
/******************************************************************************
* *
-* Paramètres : view = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -182,20 +214,24 @@ static void gtk_hex_view_init(GtkHexView *view)
* *
******************************************************************************/
-static void gtk_hex_view_dispose(GtkHexView *view)
+static void gtk_hex_view_dispose(GObject *object)
{
- gtk_widget_dispose_template(GTK_WIDGET(view), GTK_TYPE_HEX_VIEW);
+ GtkHexView *view; /* Version spécialisée */
+
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_HEX_VIEW);
+
+ view = GTK_HEX_VIEW(object);
g_clear_object(&view->generator);
- G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(G_OBJECT(view));
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : view = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -205,9 +241,9 @@ static void gtk_hex_view_dispose(GtkHexView *view)
* *
******************************************************************************/
-static void gtk_hex_view_finalize(GtkHexView *view)
+static void gtk_hex_view_finalize(GObject *object)
{
- G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(G_OBJECT(view));
+ G_OBJECT_CLASS(gtk_hex_view_parent_class)->finalize(object);
}
@@ -263,13 +299,43 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content)
parent = GTK_BUFFER_VIEW(view);
- cache = g_buffer_cache_new(1, 2);
+ cache = g_buffer_cache_new(1 /* opt_count */, 2 /* reg_count */);
parent->view = g_buffer_view_new(cache, parent->style);
unref_object(cache);
- view->generator = g_hex_generator_new(content);
+
+
+ gtk_hex_view_set_content(view, content);
+
+
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : view = composant d'affichage à consulter. *
+* *
+* Description : Fournit le contenu associé au composant d'affichage. *
+* *
+* Retour : Contenu dans lequel puise le générateur pour les lignes. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GBinContent *gtk_hex_view_get_content(const GtkHexView *view)
+{
+ GBinContent *result; /* Référence à retourner */
+
+ if (view->generator != NULL)
+ result = g_hex_generator_get_content(view->generator);
+ else
+ result = NULL;
return result;
@@ -278,6 +344,61 @@ bool gtk_hex_view_create(GtkHexView *view, GBinContent *content)
/******************************************************************************
* *
+* Paramètres : view = composant d'affichage à modifier. *
+* content = nouveau contenu pour source de génération. *
+* *
+* Description : Définit le contenu associé au composant d'affichage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_hex_view_set_content(GtkHexView *view, GBinContent *content)
+{
+ GBinContent *old; /* Ancienne valeur */
+ GBufferCache *cache; /* Tampon à représenter */
+
+ old = gtk_hex_view_get_content(view);
+
+ assert((old == NULL && view->generator == NULL) || (old != NULL && view->generator != NULL));
+
+ if (old != content)
+ {
+ if (view->generator != NULL)
+ {
+ cache = g_buffer_view_get_cache(GTK_BUFFER_VIEW(view)->view);
+
+ g_buffer_cache_wlock(cache);
+
+ g_buffer_cache_truncate(cache, 0);
+
+ g_buffer_cache_wunlock(cache);
+
+ unref_object(cache);
+
+ g_clear_object(&view->generator);
+
+ }
+
+ if (content != NULL)
+ view->generator = g_hex_generator_new(content);
+
+ g_object_notify_by_pspec(G_OBJECT(view), _hex_view_properties[PROP_CONTENT]);
+
+ assert(content != NULL);
+ gtk_widget_queue_resize(GTK_WIDGET(view));
+
+ }
+
+ g_clear_object(&old);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : widget = composant GTK à redessiner. *
* snapshot = gestionnaire de noeuds de rendu à solliciter. *
* parent = composant GTK parent et cadre de l'appel. *
@@ -380,67 +501,108 @@ static void gtk_hex_view_populate_cache(GtkHexView *view)
/* Mise à jour de l'affichage ? */
+ /*
if (needed != count)
gtk_widget_queue_resize(GTK_WIDGET(view));
+ */
}
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
-
-void demo_snapshot (GtkWidget *widget, GtkSnapshot *snapshot, GtkWidget *parent)
+static void gtk_hex_view_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
- GdkRGBA red, green, yellow, blue;
- float w, h;
-
- gdk_rgba_parse (&red, "red");
- gdk_rgba_parse (&green, "green");
- gdk_rgba_parse (&yellow, "yellow");
- gdk_rgba_parse (&blue, "blue");
+ GtkHexView *view; /* Version spécialisée */
+ GObject *content; /* Contenu sous forme simple */
- w = gtk_widget_get_width (widget) / 2.0;
- h = gtk_widget_get_height (widget) / 2.0;
+ view = GTK_HEX_VIEW(object);
- h /= 2.0;
+ switch (prop_id)
+ {
+ case PROP_SHOW_OFFSETS:
+ g_display_options_set(GTK_CONTENT_VIEW(view)->options, HCO_OFFSET, g_value_get_boolean(value));
+ gtk_widget_set_visible(view->offsets, g_value_get_boolean(value));
+ break;
- gtk_snapshot_append_color (snapshot, &red,
- &GRAPHENE_RECT_INIT(0, 0, w, h));
- gtk_snapshot_append_color (snapshot, &green,
- &GRAPHENE_RECT_INIT(w, 0, w, h));
- gtk_snapshot_append_color (snapshot, &yellow,
- &GRAPHENE_RECT_INIT(0, h, w, h));
- gtk_snapshot_append_color (snapshot, &blue,
- &GRAPHENE_RECT_INIT(w, h, w, h));
+ case PROP_CONTENT:
+ content = g_value_get_object(value);
+ gtk_hex_view_set_content(view, G_BIN_CONTENT(content));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
}
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+static void gtk_hex_view_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkHexView *view; /* Version spécialisée */
+ view = GTK_HEX_VIEW(object);
+ switch (prop_id)
+ {
+ case PROP_SHOW_OFFSETS:
+ g_value_set_boolean(value, gtk_widget_get_visible(view->offsets));
+ break;
+ case PROP_CONTENT:
+ g_value_take_object(value, gtk_hex_view_get_content(view));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
-
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
-/* ---------------------------------------------------------------------------------- */
+}
/******************************************************************************
* *
-* Paramètres : widget = composant GTK à examiner. *
-* width = largeur affectée au composant graphique. *
-* height = hauteur affectée au composant graphique. *
+* Paramètres : widget = composant GTK à examiner. *
+* width = largeur affectée au composant graphique. *
+* height = hauteur affectée au composant graphique. *
* baseline = ligne de base affectée au composant graphique. *
* *
* Description : Prend acte de la taille allouée au composant d'affichage. *
@@ -467,7 +629,13 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height,
final_widths = alloca(_CHILDREN_COUNT * sizeof(int));
for (i = 0; i < _CHILDREN_COUNT; i++)
- gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL);
+ {
+ if (!gtk_widget_get_visible(view->children[i]))
+ min_widths[i] = 0;
+ else
+ gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min_widths[i], NULL, NULL, NULL);
+
+ }
/* Passe 1 : tentative sans défilement vertical */
@@ -491,7 +659,10 @@ static void gtk_hex_view_size_allocate(GtkWidget *widget, int width, int height,
for (i = 0; i < _CHILDREN_COUNT; i++)
{
- final_widths[i] += min_widths[i];
+ if (!gtk_widget_get_visible(view->children[i]))
+ final_widths[i] = 0;
+ else
+ final_widths[i] += min_widths[i];
g_width_tracker_set_column_min_width(tracker, i, final_widths[i]);
@@ -531,17 +702,6 @@ static GtkSizeRequestMode gtk_hex_view_get_request_mode(GtkWidget *widget)
}
-
-
-
-
-
-
-
-
-
-
-
/******************************************************************************
* *
* Paramètres : widget = composant GTK à examiner. *
@@ -580,8 +740,12 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation,
for (i = 0; i < _CHILDREN_COUNT; i++)
{
+ if (!gtk_widget_get_visible(view->children[i]))
+ continue;
+
gtk_widget_measure(view->children[i], GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL);
requested += min;
+
}
for_size -= requested;
@@ -593,11 +757,14 @@ static void gtk_hex_view_measure(GtkWidget *widget, GtkOrientation orientation,
GTK_BUFFER_VIEW(view)->style,
for_size);
- if (minimum != NULL) *minimum = 0;
+ if (minimum != NULL) *minimum = requested;
if (natural != NULL) *natural = requested;
for (i = 0; i < _CHILDREN_COUNT; i++)
{
+ if (!gtk_widget_get_visible(view->children[i]))
+ continue;
+
gtk_widget_measure(view->children[i], GTK_ORIENTATION_VERTICAL, -1, &min, &nat, NULL, NULL);
if (minimum != NULL && min > *minimum)
diff --git a/src/gtkext/hexview.h b/src/gtkext/hexview.h
index 2199786..0d2cd5a 100644
--- a/src/gtkext/hexview.h
+++ b/src/gtkext/hexview.h
@@ -41,6 +41,12 @@ DECLARE_GTYPE(GtkHexView, gtk_hex_view, GTK, HEX_VIEW);
/* Crée un composant d'affichage d'octets bruts et imprimables. */
GtkHexView *gtk_hex_view_new(GBinContent *);
+/* Fournit le contenu associé au composant d'affichage. */
+GBinContent *gtk_hex_view_get_content(const GtkHexView *);
+
+/* Définit le contenu associé au composant d'affichage. */
+void gtk_hex_view_set_content(GtkHexView *, GBinContent *);
+
#endif /* _GTKEXT_HEXVIEW_H */
diff --git a/src/gtkext/hexview.ui b/src/gtkext/hexview.ui
index ae4586c..9b42936 100644
--- a/src/gtkext/hexview.ui
+++ b/src/gtkext/hexview.ui
@@ -1,27 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <template class="GtkHexView" parent="GtkBufferView">
- <property name="css-name">GtkHexView</property>
- <child>
- <object class="GtkComposingArea" id="offsets">
- <style>
- <class name="gutter"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkComposingArea" id="hex">
- <property name="hexpand">true</property>
- <style>
- <class name="custom-view"/>
- </style>
- </object>
- </child>
- <child>
- <object class="GtkComposingArea" id="ascii">
- <style>
- <class name="custom-view"/>
- </style>
- </object>
- </child>
- </template>
+
+ <template class="GtkHexView" parent="GtkBufferView">
+ <child>
+ <object class="GtkComposingArea" id="offsets">
+ <style>
+ <class name="gutter"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="hex">
+ <property name="hexpand">true</property>
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ <child>
+ <object class="GtkComposingArea" id="ascii">
+ <style>
+ <class name="custom-view"/>
+ </style>
+ </object>
+ </child>
+ </template>
+
</interface>
diff --git a/src/gtkext/launcher-int.h b/src/gtkext/launcher-int.h
new file mode 100644
index 0000000..07152f0
--- /dev/null
+++ b/src/gtkext/launcher-int.h
@@ -0,0 +1,56 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak-int.h - définitions internes pour un lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_LAUNCHER_INT_H
+#define _GTKEXT_LAUNCHER_INT_H
+
+
+#include "launcher.h"
+
+
+
+/* Elément de lancement d'un panneau majeur pour l'interface (instance) */
+struct _GtkPanelLauncher
+{
+ GtkListBoxRow parent; /* A laisser en premier */
+
+ GtkImage *icon; /* Eventuelle image */
+ GtkLabel *title; /* Etiquette associée */
+ GtkLabel *desc; /* Description du panneau */
+
+};
+
+/* Elément de lancement d'un panneau majeur pour l'interface (classe) */
+struct _GtkPanelLauncherClass
+{
+ GtkListBoxRowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un nouveau lanceur de panneau majeur. */
+bool gtk_panel_launcher_create(GtkPanelLauncher *, const char *, const char *, const char *);
+
+
+
+#endif /* _GTKEXT_LAUNCHER_INT_H */
diff --git a/src/gtkext/launcher.c b/src/gtkext/launcher.c
new file mode 100644
index 0000000..5bb850b
--- /dev/null
+++ b/src/gtkext/launcher.c
@@ -0,0 +1,211 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * launcher.c - lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "launcher.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "helpers.h"
+#include "launcher-int.h"
+#include "../common/extstr.h"
+
+
+
+/* Initialise la classe des sections d'éléments paramétrables. */
+static void gtk_panel_launcher_class_init(GtkPanelLauncherClass *);
+
+/* Initialise une instance de lanceur de panneau majeur. */
+static void gtk_panel_launcher_init(GtkPanelLauncher *);
+
+/* Supprime toutes les références externes. */
+static void gtk_panel_launcher_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_panel_launcher_finalize(GObject *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkPanelLauncher, gtk_panel_launcher, GTK_TYPE_LIST_BOX_ROW);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des sections d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_class_init(GtkPanelLauncherClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = gtk_panel_launcher_dispose;
+ object->finalize = gtk_panel_launcher_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/launcher.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, icon);
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, title);
+ gtk_widget_class_bind_template_child(widget, GtkPanelLauncher, desc);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : launcher = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de lanceur de panneau majeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_init(GtkPanelLauncher *launcher)
+{
+ gtk_widget_init_template(GTK_WIDGET(launcher));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_dispose(GObject *object)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(object), GTK_TYPE_PANEL_LAUNCHER);
+
+ G_OBJECT_CLASS(gtk_panel_launcher_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_panel_launcher_finalize(GObject *object)
+{
+ G_OBJECT_CLASS(gtk_panel_launcher_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : icon = désignation de l'image de représentation. *
+* title = titre principal à afficher. *
+* desc = description du panneau ciblé. *
+* *
+* Description : Crée un nouveau lanceur de panneau majeur. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkPanelLauncher *gtk_panel_launcher_new(const char *icon, const char *title, const char *desc)
+{
+ GtkPanelLauncher *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_PANEL_LAUNCHER, NULL);
+
+ if (!gtk_panel_launcher_create(result, icon, title, desc))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : launcher = lanceur à initialiser pleinement. *
+* icon = désignation de l'image de représentation. *
+* title = titre principal à afficher. *
+* desc = description du panneau ciblé. *
+* *
+* Description : Met en place un nouveau lanceur de panneau majeur. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_launcher_create(GtkPanelLauncher *launcher, const char *icon, const char *title, const char *desc)
+{
+ bool result; /* Bilan à retourner */
+ char *bold; /* Titre sublimé */
+
+ result = true;
+
+ gtk_image_set_from_icon_name(launcher->icon, icon);
+
+ bold = strdup(title);
+ bold = strprep(bold, "<b>");
+ bold = stradd(bold, "</b>");
+
+ gtk_label_set_label(launcher->title, bold);
+
+ free(bold);
+
+ gtk_label_set_label(launcher->desc, desc);
+
+ return result;
+
+}
diff --git a/src/gtkext/launcher.h b/src/gtkext/launcher.h
new file mode 100644
index 0000000..3857216
--- /dev/null
+++ b/src/gtkext/launcher.h
@@ -0,0 +1,45 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * launcher.h - prototypes pour pour un lanceur de panneau majeur
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_LAUNCHER_H
+#define _GTKEXT_LAUNCHER_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_PANEL_LAUNCHER (gtk_panel_launcher_get_type())
+
+DECLARE_GTYPE(GtkPanelLauncher, gtk_panel_launcher, GTK, PANEL_LAUNCHER);
+
+
+/* Crée un nouveau lanceur de panneau majeur. */
+GtkPanelLauncher *gtk_panel_launcher_new(const char *, const char *, const char *);
+
+
+
+#endif /* _GTKEXT_LAUNCHER_H */
diff --git a/src/gtkext/launcher.ui b/src/gtkext/launcher.ui
new file mode 100644
index 0000000..f6f4fec
--- /dev/null
+++ b/src/gtkext/launcher.ui
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkPanelLauncher" parent="GtkListBoxRow">
+
+ <property name="child">
+
+ <object class="GtkGrid">
+ <property name="margin-bottom">12</property>
+ <property name="margin-end">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">12</property>
+ <property name="column-spacing">12</property>
+
+ <child>
+ <object class="GtkImage" id="icon">
+ <property name="icon-name"></property>
+ <property name="pixel-size">48</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="title">
+ <property name="label"></property>
+ <property name="use-markup">TRUE</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="desc">
+ <property name="label"></property>
+ <property name="hexpand">true</property>
+ <property name="xalign">0</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">1</property>
+ </layout>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="margin-start">12</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ <property name="row-span">2</property>
+ </layout>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+
+ </template>
+</interface>
diff --git a/src/gtkext/panel-int.h b/src/gtkext/panel-int.h
new file mode 100644
index 0000000..5398e51
--- /dev/null
+++ b/src/gtkext/panel-int.h
@@ -0,0 +1,180 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel-int.h - prototypes pour les définitions internes liées aux panneaux d'affichage
+ *
+ * Copyright (C) 2019-2024 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 _GTKEXT_PANEL_INT_H
+#define _GTKEXT_PANEL_INT_H
+
+
+#include "panel.h"
+
+
+
+/* Indique l'emplacement par défaut pour un affichage. */
+typedef char * (* get_tiled_panel_path) (const GtkTiledPanel *);
+
+/* Fournit les composants adaptés pour la barre de titre. */
+typedef GListStore * (* get_tiled_panel_widgets_cb) (const GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+typedef void (* notify_tiled_panel_state_cb) (GtkTiledPanel *, GtkTiledPanel *, bool);
+
+
+/* Elément réactif pour panneaux de l'éditeur (instance) */
+struct _GtkTiledPanel
+{
+ GtkBox parent; /* A laisser en premier */
+
+};
+
+/* Elément réactif pour panneaux de l'éditeur (classe) */
+struct _GtkTiledPanelClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+ get_tiled_panel_path get_default_path; /* Localisation de l'affichage */
+ get_tiled_panel_widgets_cb get_widgets; /* Récupération de composants */
+
+ notify_tiled_panel_state_cb notify; /* Note d'un ajout ou retrait */
+
+};
+
+
+
+
+
+
+
+
+#if 0
+
+#include <gtk/gtk.h>
+
+
+#include "item-int.h"
+#include "../glibext/delayed.h"
+
+
+
+/* ------------------------- COEUR DES PANNEAUX D'AFFICHAGE ------------------------- */
+
+
+/* Fournit une indication sur la personnalité du panneau. */
+typedef PanelItemPersonality (* get_panel_personality_fc) (const GPanelItemClass *);
+
+/* Fournit une indication d'accroche du panneau au démarrage. */
+typedef bool (* dock_panel_at_startup_fc) (const GPanelItemClass *);
+
+/* Détermine si un panneau peut être filtré. */
+typedef bool (* can_search_panel_fc) (const GPanelItemClass *);
+
+/* Indique le chemin initial de la localisation d'un panneau. */
+typedef char * (* get_panel_path_fc) (const GPanelItemClass *);
+
+/* Indique la définition d'un éventuel raccourci clavier. */
+typedef char * (* get_panel_bindings_fc) (const GPanelItemClass *);
+
+/* Place un panneau dans l'ensemble affiché. */
+typedef void (* ack_dock_process_fc) (GPanelItem *);
+
+/* Supprime un panneau de l'ensemble affiché. */
+typedef void (* ack_undock_process_fc) (GPanelItem *);
+
+/* Démarre l'actualisation du filtrage du contenu. */
+typedef void (* update_filtered_fc) (GPanelItem *);
+
+
+/* Elément réactif pour panneaux de l'éditeur (instance) */
+struct _GPanelItem
+{
+ GEditorItem parent; /* A laisser en premier */
+
+ bool docked; /* Panneau inscrusté ? */
+
+ GNamedWidget *widget; /* Composant avec noms */
+ GtkWidget *cached_widget; /* Composant GTK récupéré */
+
+ char *filter; /* Eventuel filtre textuel */
+
+ cairo_surface_t *surface; /* Copie d'écran préalable */
+ gdouble hadj_value; /* Sauvegarde de défilement #1 */
+ gdouble vadj_value; /* Sauvegarde de défilement #2 */
+ gint switched; /* Mémorise l'état de bascule */
+
+};
+
+/* Elément réactif pour panneaux de l'éditeur (classe) */
+struct _GPanelItemClass
+{
+ GEditorItemClass parent; /* A laisser en premier */
+
+ get_panel_personality_fc get_personality; /* Fourniture de nature */
+ dock_panel_at_startup_fc dock_at_startup; /* Recommandation d'accroche */
+ can_search_panel_fc can_search; /* Contenu fouillable ? */
+ get_panel_path_fc get_path; /* Chemin vers la place idéale */
+ get_panel_bindings_fc get_bindings; /* Raccourci clavier éventuel */
+
+ ack_dock_process_fc ack_dock; /* Prise en compte d'accroche */
+ ack_undock_process_fc ack_undock; /* Prise en compte de décroche */
+
+ update_filtered_fc update_filtered; /* Lancement du filtrage */
+
+ wgroup_id_t gid; /* Groupe de travail dédié */
+
+ /* Signaux */
+
+ void (* dock_request) (GPanelItem);
+ void (* undock_request) (GPanelItem);
+
+};
+
+
+/* Fournit une indication sur la personnalité du panneau. */
+PanelItemPersonality gtk_panel_item_class_get_personality_singleton(const GPanelItemClass *);
+
+/* Renvoie false lors d'une consultation de la classe. */
+bool gtk_panel_item_class_return_false(const GPanelItemClass *);
+
+/* Renvoie true lors d'une consultation de la classe. */
+bool gtk_panel_item_class_return_true(const GPanelItemClass *);
+
+
+
+/* ---------------------- MECANISMES DE MISE A JOUR DE PANNEAU ---------------------- */
+
+
+/* Obtient le groupe de travail dédié à une mise à jour. */
+wgroup_id_t g_panel_item_get_group(const GPanelItem *);
+
+/* Bascule l'affichage d'un panneau avant sa mise à jour. */
+void g_panel_item_switch_to_updating_mask(GPanelItem *);
+
+/* Bascule l'affichage d'un panneau après sa mise à jour. */
+void g_panel_item_switch_to_updated_content(GPanelItem *);
+
+
+#endif
+
+
+
+#endif /* _GTKEXT_PANEL_INT_H */
diff --git a/src/gtkext/panel.c b/src/gtkext/panel.c
new file mode 100644
index 0000000..f63cfa1
--- /dev/null
+++ b/src/gtkext/panel.c
@@ -0,0 +1,1321 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel.c - gestion des éléments réactifs spécifiques aux panneaux
+ *
+ * Copyright (C) 2019-2024 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 "panel-int.h"
+
+
+
+
+
+/* Initialise la classe des panneaux graphiques de l'éditeur. */
+static void gtk_tiled_panel_class_init(GtkTiledPanelClass *);
+
+/* Initialise une instance de panneau graphique pour l'éditeur. */
+static void gtk_tiled_panel_init(GtkTiledPanel *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tiled_panel_dispose(GtkTiledPanel *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tiled_panel_finalize(GtkTiledPanel *);
+
+
+
+
+
+
+
+
+/* Détermine le type du conteneur d'affichage en tuiles nommées. */
+G_DEFINE_TYPE(GtkTiledPanel, gtk_tiled_panel, GTK_TYPE_BOX)
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des panneaux graphiques de l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_class_init(GtkTiledPanelClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiled_panel_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_tiled_panel_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance GTK à initialiser. *
+* *
+* Description : Initialise une instance de panneau graphique pour l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_init(GtkTiledPanel *panel)
+{
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_dispose(GtkTiledPanel *panel)
+{
+ G_OBJECT_CLASS(gtk_tiled_panel_parent_class)->dispose(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tiled_panel_finalize(GtkTiledPanel *panel)
+{
+ G_OBJECT_CLASS(gtk_tiled_panel_parent_class)->finalize(G_OBJECT(panel));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* *
+* Description : Indique l'emplacement attendu pour un affichage. *
+* *
+* Retour : Chemin représenté ou NULL pour l'emplacement "M" par défaut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *gtk_tiled_panel_get_path(const GtkTiledPanel *panel)
+{
+ char *result; /* Chemin à retourner */
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->get_default_path != NULL)
+ result = class->get_default_path(panel);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à consulter. *
+* left = indication quant au côté ciblé. *
+* *
+* Description : Fournit les composants adaptés pour la barre de titre. *
+* *
+* Retour : Liste de Composants GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *panel, bool left)
+{
+ GListStore *result; /* Composant(s) à retourner */
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->get_widgets != NULL)
+ result = class->get_widgets(panel, left);
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : panel = panneau graphique à manipuler. *
+* main = panneau principal visé par l'opération. *
+* activated = nature du changement de statut : ajout, retrait ?*
+* *
+* Description : Note un ajout ou un retrait de panneau principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *panel, GtkTiledPanel *main, bool activated)
+{
+ GtkTiledPanelClass *class; /* Classe à actionner */
+
+ class = GTK_TILED_PANEL_GET_CLASS(panel);
+
+ if (class->notify != NULL)
+ class->notify(panel, main, activated);
+
+}
+
+
+
+
+
+
+#if 0
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#include "panel-int.h"
+#include "core/global.h"
+#include "core/items.h"
+#include "../common/extstr.h"
+#include "../core/params.h"
+#include "../gtkext/gtkdockable-int.h"
+#include "../gtkext/named.h"
+#include "../plugins/dt.h"
+#include "../plugins/pglist.h"
+
+
+
+/* ------------------------- COEUR DES PANNEAUX D'AFFICHAGE ------------------------- */
+
+
+/* Initialise la classe des panneaux graphiques de l'éditeur. */
+static void g_panel_item_class_init(GPanelItemClass *);
+
+/* Initialise une instance de panneau graphique pour l'éditeur. */
+static void g_panel_item_init(GPanelItem *);
+
+/* Procède à l'initialisation de l'interface d'incrustation. */
+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 *);
+
+/* Construit la chaîne d'accès à un élément de configuration. */
+static char *gtk_panel_item_class_build_configuration_key(const GPanelItemClass *, const char *);
+
+/* Fournit le nom court du composant encapsulable. */
+static char *gtk_panel_item_get_name(const GPanelItem *);
+
+/* Fournit le nom long du composant encapsulable. */
+static char *gtk_panel_item_get_desc(const GPanelItem *);
+
+/* Détermine si un panneau peut être filtré. */
+static bool gtk_panel_item_can_search(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 *, 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 : class = classe à initialiser. *
+* *
+* Description : Initialise la classe des panneaux graphiques de l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_class_init(GPanelItemClass *class)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GEditorItemClass *item; /* Encore une autre vision... */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_panel_item_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_panel_item_finalize;
+
+ item = G_EDITOR_ITEM_CLASS(class);
+
+ item->get_widget = (get_item_widget_fc)gtk_panel_item_get_widget;
+
+ class->get_personality = gtk_panel_item_class_get_personality_singleton;
+ class->dock_at_startup = gtk_panel_item_class_return_true;
+ class->can_search = gtk_panel_item_class_return_false;
+
+ 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);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance à initialiser. *
+* *
+* Description : Initialise une instance de panneau graphique pour l'éditeur. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_init(GPanelItem *item)
+{
+ item->docked = false;
+
+ item->widget = NULL;
+ item->cached_widget = NULL;
+
+ item->filter = NULL;
+
+ g_atomic_int_set(&item->switched, 0);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GTK à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface d'incrustation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_panel_item_dockable_interface_init(GtkDockableInterface *iface)
+{
+ 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->can_search = (can_dockable_search_fc)gtk_panel_item_can_search;
+
+ 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->widget);
+ g_clear_object(&item->cached_widget);
+
+ 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)
+{
+ 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 : class = classe à consulter. *
+* *
+* Description : Fournit une indication sur la personnalité du panneau. *
+* *
+* Retour : Identifiant lié à la nature du panneau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PanelItemPersonality gtk_panel_item_class_get_personality(const GPanelItemClass *class)
+{
+ PanelItemPersonality result; /* Personnalité à retourner */
+
+ result = class->get_personality(class);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à consulter. *
+* *
+* Description : Fournit une indication sur la personnalité du panneau. *
+* *
+* Retour : Identifiant lié à la nature unique du panneau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+PanelItemPersonality gtk_panel_item_class_get_personality_singleton(const GPanelItemClass *class)
+{
+ PanelItemPersonality result; /* Personnalité à retourner */
+
+ result = PIP_SINGLETON;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à consulter. *
+* *
+* Description : Fournit une indication d'accroche du panneau au démarrage. *
+* *
+* Retour : true si le panneau doit être affiché de prime abord. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_class_dock_at_startup(const GPanelItemClass *class)
+{
+ bool result; /* Statut à retourner */
+ GGenConfig *config; /* Configuration courante */
+ char *key; /* Clef d'accès à un paramètre */
+#ifndef NDEBUG
+ bool status; /* Bilan de consultation */
+#endif
+
+ config = get_main_configuration();
+
+ key = gtk_panel_item_class_build_configuration_key(class, "dock_at_startup");
+
+#ifndef NDEBUG
+ status = g_generic_config_get_value(config, key, &result);
+ assert(status);
+#else
+ g_generic_config_get_value(config, key, &result);
+#endif
+
+ free(key);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe associée à la consultation. *
+* *
+* Description : Renvoie false lors d'une consultation de la classe. *
+* *
+* Retour : false. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_class_return_false(const GPanelItemClass *class)
+{
+ bool result; /* Statut à retourner */
+
+ result = false;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe associée à la consultation. *
+* *
+* Description : Renvoie true lors d'une consultation de la classe. *
+* *
+* Retour : true. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_class_return_true(const GPanelItemClass *class)
+{
+ bool result; /* Statut à retourner */
+
+ result = true;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à consulter. *
+* *
+* Description : Détermine si un panneau peut être filtré. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_class_can_search(const GPanelItemClass *class)
+{
+ bool result; /* Statut à retourner */
+
+ result = class->can_search(class);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à consulter. *
+* *
+* Description : Indique le chemin initial de la localisation d'un panneau. *
+* *
+* Retour : Chemin fixé associé à la position initiale. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *gtk_panel_item_class_get_path(const GPanelItemClass *class)
+{
+ char *result; /* Emplacement à retourner */
+ GGenConfig *config; /* Configuration courante */
+ char *key; /* Clef d'accès à un paramètre */
+ const char *path; /* Nouveau chemin de placement */
+#ifndef NDEBUG
+ bool status; /* Statut de l'encapsulation */
+#endif
+
+ config = get_main_configuration();
+
+ key = gtk_panel_item_class_build_configuration_key(class, "path");
+
+#ifndef NDEBUG
+ status = g_generic_config_get_value(config, key, &path);
+ assert(status);
+#else
+ g_generic_config_get_value(config, key, &path);
+#endif
+
+ free(key);
+
+ result = strdup(path);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe à consulter. *
+* *
+* Description : Indique la définition d'un éventuel raccourci clavier. *
+* *
+* Retour : Description d'un raccourci ou NULL si aucun de défini. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+char *gtk_panel_item_class_get_key_bindings(const GPanelItemClass *class)
+{
+ char *result; /* Emplacement à retourner */
+
+ if (class->get_bindings != NULL)
+ result = class->get_bindings(class);
+
+ else
+ result = NULL;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe du type de panneau à traiter. *
+* 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_class_build_configuration_key(const GPanelItemClass *class, const char *attrib)
+{
+ char *result; /* Construction à renvoyer */
+ const char *name; /* Nom court du panneau */
+
+ name = g_editor_item_class_get_key(G_EDITOR_ITEM_CLASS(class));
+
+ asprintf(&result, "gui.panels.%s.%s", attrib, name);
+
+ result = strrpl(result, " ", "_");
+
+ result = strlower(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe de panneau à consulter. *
+* config = configuration à compléter. *
+* *
+* Description : Met en place les bases de la configuration d'un panneau. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_panel_item_class_setup_configuration(const GPanelItemClass *class, GGenConfig *config)
+{
+ bool result; /* Bilan à retourner */
+ char *key; /* Clef d'accès à un paramètre */
+ bool dock_at_startup; /* Affichage dès le départ ? */
+ char *path; /* Localisation du panneau */
+
+ key = gtk_panel_item_class_build_configuration_key(class, "dock_at_startup");
+
+ dock_at_startup = class->dock_at_startup(class);
+
+ result = g_generic_config_create_param_if_not_exist(config, key, CPT_BOOLEAN, dock_at_startup);
+
+ free(key);
+
+ if (!result)
+ goto exit;
+
+ key = gtk_panel_item_class_build_configuration_key(class, "path");
+
+ path = class->get_path(class);
+
+ result = g_generic_config_create_param_if_not_exist(config, key, CPT_STRING, path);
+
+ free(path);
+
+ free(key);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type de panneau à mettre en place. *
+* path = emplacement d'affichage ou NULL. *
+* *
+* Description : Crée un élément de panneau réactif. *
+* *
+* Retour : Adresse de la structure mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GPanelItem *g_panel_item_new(GType type, const char *path)
+{
+ GPanelItem *result; /* Structure à retourner */
+ GPanelItemClass *class; /* Classe associée au type */
+ PanelItemPersonality personality; /* Caractéristique de panneau */
+ GtkTiledGrid *grid; /* Composant d'affichage */
+
+ class = g_type_class_ref(type);
+
+ personality = gtk_panel_item_class_get_personality(class);
+ assert(path != NULL || personality == PIP_PERSISTENT_SINGLETON);
+
+ g_type_class_unref(class);
+
+ if (personality == PIP_PERSISTENT_SINGLETON || personality == PIP_SINGLETON)
+ {
+ result = G_PANEL_ITEM(find_editor_item_by_type(type));
+
+ if (result != NULL)
+ goto singleton;
+
+ }
+
+ result = create_object_from_type(type);
+
+ grid = get_tiled_grid();
+
+ g_signal_connect_swapped(result, "dock-request", G_CALLBACK(gtk_tiled_grid_add), grid);
+ g_signal_connect_swapped(result, "undock-request", G_CALLBACK(gtk_tiled_grid_remove), grid);
+
+ gtk_dockable_setup_dnd(GTK_DOCKABLE(result));
+
+ register_editor_item(G_EDITOR_ITEM(result));
+
+ notify_panel_creation(result);
+
+ singleton:
+
+ if (path != NULL)
+ {
+ if (path[0] != '\0')
+ gtk_panel_item_set_path(result, path);
+
+ g_panel_item_dock(result);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : item = instance de panneau à consulter. *
+* *
+* Description : Indique le composant graphique principal du panneau. *
+* *
+* Retour : Composant graphique avec nom constituant le panneau. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GNamedWidget *gtk_panel_item_get_named_widget(const GPanelItem *item)
+{
+ GNamedWidget *result; /* Composant nommé à retourner */
+
+ result = item->widget;
+
+ g_object_ref(G_OBJECT(result));
+
+ 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 char *gtk_panel_item_get_name(const GPanelItem *item)
+{
+ char *result; /* Désignation à retourner */
+
+ result = g_named_widget_get_name(G_NAMED_WIDGET(item->widget), false);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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 char *gtk_panel_item_get_desc(const GPanelItem *item)
+{
+ char *result; /* Description à retourner */
+
+ result = g_named_widget_get_name(G_NAMED_WIDGET(item->widget), true);
+
+ 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 = gtk_panel_item_class_can_search(class);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ GtkWidget *result; /* Composant à retourner */
+
+ if (item->cached_widget == NULL)
+ item->cached_widget = g_named_widget_get_widget(G_NAMED_WIDGET(item->widget));
+
+ result = item->cached_widget;
+
+ g_object_ref(G_OBJECT(result));
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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, const char *filter)
+{
+ assert(gtk_panel_item_can_search(item));
+
+ if (item->filter != NULL)
+ free(item->filter);
+
+ item->filter = (filter ? strdup(filter) : NULL);
+
+ G_PANEL_ITEM_GET_CLASS(item)->update_filtered(item);
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ GGenConfig *config; /* Configuration courante */
+ char *key; /* Clef d'accès à un paramètre */
+
+ config = get_main_configuration();
+
+ key = gtk_panel_item_class_build_configuration_key(G_PANEL_ITEM_GET_CLASS(item), "path");
+
+ g_generic_config_set_value(config, key, path);
+
+ free(key);
+
+}
+
+
+/******************************************************************************
+* *
+* 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);
+
+ notify_panel_docking(item, true);
+
+}
+
+
+/******************************************************************************
+* *
+* 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_at_startup(GPanelItem *item, bool status)
+{
+ char *key; /* Clef d'accès à un paramètre */
+
+ item->docked = status;
+
+ key = gtk_panel_item_class_build_configuration_key(G_PANEL_ITEM_GET_CLASS(item), "dock_at_startup");
+
+ g_generic_config_set_value(get_main_configuration(), key, status);
+
+ 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)
+{
+ bool result; /* Statut à retourner */
+
+ result = item->docked;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ PanelItemPersonality personality; /* Caractéristique de panneau */
+
+ 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);
+
+ notify_panel_docking(item, false);
+
+ personality = gtk_panel_item_class_get_personality(G_PANEL_ITEM_GET_CLASS(item));
+
+ if (personality != PIP_PERSISTENT_SINGLETON)
+ unregister_editor_item(G_EDITOR_ITEM(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)
+{
+ GtkBuilder *builder; /* Constructeur sous-jacent */
+ 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);
+
+ builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(item->widget));
+
+ content = GTK_WIDGET(gtk_builder_get_object(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(builder, "stack"));
+
+ mask = GTK_WIDGET(gtk_builder_get_object(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);
+
+ g_object_unref(G_OBJECT(builder));
+
+}
+
+
+/******************************************************************************
+* *
+* 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)
+{
+ GtkBuilder *builder; /* Constructeur sous-jacent */
+ 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 */
+
+ builder = gtk_built_named_widget_get_builder(GTK_BUILT_NAMED_WIDGET(item->widget));
+
+ content = GTK_WIDGET(gtk_builder_get_object(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(builder, "stack"));
+
+ gtk_stack_set_visible_child(stack, content);
+
+ mask = GTK_WIDGET(gtk_builder_get_object(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;
+ }
+
+ g_object_unref(G_OBJECT(builder));
+
+ skip:
+
+ g_atomic_int_dec_and_test(&item->switched);
+
+}
+
+#endif
diff --git a/src/gtkext/panel.h b/src/gtkext/panel.h
new file mode 100644
index 0000000..9b00657
--- /dev/null
+++ b/src/gtkext/panel.h
@@ -0,0 +1,142 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * panel.h - prototypes pour la gestion des éléments réactifs spécifiques aux panneaux
+ *
+ * Copyright (C) 2019-2024 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 _GTKEXT_PANEL_H
+#define _GTKEXT_PANEL_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_TILED_PANEL (gtk_tiled_panel_get_type())
+
+DECLARE_GTYPE(GtkTiledPanel, gtk_tiled_panel, GTK, TILED_PANEL);
+
+
+/* Indique l'emplacement attendu pour un affichage. */
+char *gtk_tiled_panel_get_path(const GtkTiledPanel *);
+
+/* Fournit les composants adaptés pour la barre de titre. */
+GListStore *gtk_tiled_panel_get_title_widgets(const GtkTiledPanel *, bool);
+
+/* Note un ajout ou un retrait de panneau principal. */
+void gtk_tiled_panel_notify_new_main_panel_state(GtkTiledPanel *, GtkTiledPanel *, bool);
+
+
+
+
+
+
+#if 0
+
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+#include "../glibext/configuration.h"
+#include "../glibext/named.h"
+
+
+
+#define G_TYPE_PANEL_ITEM g_panel_item_get_type()
+#define G_PANEL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_PANEL_ITEM, GPanelItem))
+#define G_IS_PANEL_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_PANEL_ITEM))
+#define G_PANEL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_PANEL_ITEM, GPanelItemClass))
+#define G_IS_PANEL_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_PANEL_ITEM))
+#define G_PANEL_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_PANEL_ITEM, GPanelItemClass))
+
+
+/* Elément réactif pour panneaux de l'éditeur (instance) */
+typedef struct _GPanelItem GPanelItem;
+
+/* Elément réactif pour panneaux de l'éditeur (classe) */
+typedef struct _GPanelItemClass GPanelItemClass;
+
+
+/* Types de panneaux pour éditeur */
+typedef enum _PanelItemPersonality
+{
+ PIP_INVALID, /* Information non initialisée */
+
+ PIP_SINGLETON, /* Instance unique */
+ PIP_PERSISTENT_SINGLETON, /* Instance unique permanente */
+ PIP_BINARY_VIEW, /* Affichage d'un binaire */
+ PIP_OTHER, /* Reste du monde */
+
+ PIP_COUNT
+
+} PanelItemPersonality;
+
+
+/* Indique le type défini pour un élément destiné à un panneau. */
+GType g_panel_item_get_type(void);
+
+/* Fournit une indication sur la personnalité du panneau. */
+PanelItemPersonality gtk_panel_item_class_get_personality(const GPanelItemClass *);
+
+/* Fournit une indication d'accroche du panneau au démarrage. */
+bool gtk_panel_item_class_dock_at_startup(const GPanelItemClass *);
+
+/* Détermine si un panneau peut être filtré. */
+bool gtk_panel_item_class_can_search(const GPanelItemClass *);
+
+/* Indique le chemin initial de la localisation d'un panneau. */
+char *gtk_panel_item_class_get_path(const GPanelItemClass *);
+
+/* Indique la définition d'un éventuel raccourci clavier. */
+char *gtk_panel_item_class_get_key_bindings(const GPanelItemClass *);
+
+/* Met en place les bases de la configuration du panneau. */
+bool gtk_panel_item_class_setup_configuration(const GPanelItemClass *, GGenConfig *);
+
+/* Crée un élément de panneau réactif. */
+GPanelItem *g_panel_item_new(GType, const char *);
+
+/* Indique le composant graphique principal du panneau. */
+GNamedWidget *gtk_panel_item_get_named_widget(const GPanelItem *);
+
+/* Définit le chemin d'accès à utiliser pour les encapsulations. */
+void gtk_panel_item_set_path(GPanelItem *, const char *);
+
+/* Place un panneau dans l'ensemble affiché. */
+void g_panel_item_dock(GPanelItem *);
+
+/* Définit si le composant repose sur un support de l'éditeur. */
+void g_panel_item_set_dock_at_startup(GPanelItem *, bool);
+
+/* Indique si le composant repose sur un support de l'éditeur. */
+bool g_panel_item_is_docked(const GPanelItem *);
+
+/* Supprime un panneau de l'ensemble affiché. */
+void g_panel_item_undock(GPanelItem *);
+
+
+#endif
+
+
+#endif /* _GTKEXT_PANEL_H */
diff --git a/src/gtkext/statusstack-int.h b/src/gtkext/statusstack-int.h
new file mode 100644
index 0000000..721b982
--- /dev/null
+++ b/src/gtkext/statusstack-int.h
@@ -0,0 +1,106 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * statusstack-int.h - définitions internes pour l'empilement d'informations de statut
+ *
+ * Copyright (C) 2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_STATUSSTACK_INT_H
+#define _GTKEXT_STATUSSTACK_INT_H
+
+
+#include "statusstack.h"
+#include "../glibext/secstorage.h"
+
+
+
+/* Navigation au sein d'assemblage */
+typedef struct _navigation_info_t navigation_info_t;
+
+/* Mémorisation des progressions au sein d'activités */
+typedef struct _activity_info_t activity_info_t;
+
+
+#define NETWORK_UPDATE_COUNT 10
+#define NETWORK_UPDATE_INTERVAL (1000 / NETWORK_UPDATE_COUNT)
+
+
+/* Gestion de barre de statut adaptable (instance) */
+struct _GtkStatusStack
+{
+ GtkBox parent; /* A laisser en premier */
+
+ GtkStack *main; /* Pile d'informations associée*/
+
+ GSourceFunc def_source; /* Appel en fin d'activité */
+
+ /* Message simple par défaut */
+
+ GtkLabel *def_label; /* Afficheur de message */
+
+ char *msg; /* Contenu associé */
+
+ /* Navigation */
+
+ GtkLabel *nav_segment; /* Désignation du segment */
+ GtkLabel *nav_phys; /* Adresse physique */
+ GtkLabel *nav_virt; /* Adresse virtuelle */
+ GtkLabel *nav_offset; /* Position dans le binaire */
+ GtkLabel *nav_format; /* Architecture du binaire */
+ GtkLabel *nav_details; /* Détails sur l'architecture */
+ GtkEntry *zoom; /* Degré de zoom courant */
+
+ navigation_info_t *nav_info; /* Informations brutes liées */
+
+ /* Activité */
+
+ GtkLabel *activity_message; /* Nature de l'activité */
+ GtkProgressBar *activity_progress; /* Barre de progression */
+
+ activity_info_t *activity_info; /* Informations brutes liées */
+
+ /* Tronc commun */
+
+ GSecretStorage *storage; /* Stockage des secrets */
+ GtkToggleButton *lock_update; /* Activation des accès */
+
+ GtkLabel *net_recv_speed; /* Débit en réception */
+ GtkLabel *net_send_speed; /* Débit en émission */
+
+ size_t last_bytes_received[NETWORK_UPDATE_COUNT]; /* Octets reçus */
+ size_t last_bytes_sent[NETWORK_UPDATE_COUNT]; /* Octets émis */
+ gint64 last_timestamps[NETWORK_UPDATE_COUNT]; /* Dates des mesures */
+ size_t next_index; /* Indice d'écriture */
+
+ guint network_update_tag; /* Identifiant de mise à jour */
+
+ GtkToggleButton *bottom_toggler; /* Bascule de panneaux inf. */
+
+};
+
+/* Gestion de barre de statut adaptable (classe) */
+struct _GtkStatusStackClass
+{
+ GtkBoxClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GTKEXT_STATUSSTACK_INT_H */
diff --git a/src/gtkext/statusstack.c b/src/gtkext/statusstack.c
new file mode 100644
index 0000000..92c296a
--- /dev/null
+++ b/src/gtkext/statusstack.c
@@ -0,0 +1,1383 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * statusstack.c - empilement d'informations de statut
+ *
+ * Copyright (C) 2015-2024 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "statusstack.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include <i18n.h>
+
+
+#include "helpers.h"
+#include "statusstack-int.h"
+#include "../core/global.h"
+
+
+
+/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _StatusStackProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_SHOW_BOTTOM, /* Affichage de la zone inf. */
+
+ N_PROPERTIES
+
+} StatusStackProperty;
+
+static GParamSpec *_status_stack_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Source d'affichage par défaut */
+#define gtk_status_stack_default_source gtk_status_stack_show_simple_message
+
+
+/* Initialise la classe des barres de statut améliorées. */
+static void gtk_status_stack_class_init(GtkStatusStackClass *);
+
+/* Initialise une instance de barre de statut améliorée. */
+static void gtk_status_stack_init(GtkStatusStack *);
+
+/* Supprime toutes les références externes. */
+static void gtk_status_stack_dispose(GtkStatusStack *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_status_stack_finalize(GtkStatusStack *);
+
+/* Note le changement de verrouillage du stockage sécurisé. */
+static void gtk_status_stack_on_secret_storage_lock_update(GSecretStorage *, GtkStatusStack *);
+
+/* Met à jour dans la barre les débits réseau observés. */
+static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Met à jour une propriété d'instance GObject. */
+static void gtk_status_stack_set_property(GObject *, guint, const GValue *, GParamSpec *);
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_status_stack_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */
+
+
+/* S'assure de l'affichage à jour de la partie "default". */
+static gboolean gtk_status_stack_show_simple_message(gpointer);
+
+
+
+/* -------------------- STATUT DES INFORMATIONS DE DESASSEMBLAGE -------------------- */
+
+
+/* Navigation au sein d'assemblage */
+struct _navigation_info_t
+{
+ char *segment; /* Segment d'appartenance */
+
+ mrange_t current; /* Emplacement correspondant */
+
+ VMPA_BUFFER(phys); /* Localisation physique */
+ VMPA_BUFFER(virt); /* Localisation virtuelle */
+
+ char *symbol; /* Eventuel symbole concerné */
+
+ char *format; /* Architecture et format */
+ char *details; /* Encodage de l'instruction */
+
+};
+
+
+/* Met en place le suivi d'informations de navigation. */
+static void init_navigation_info(navigation_info_t *);
+
+/* Supprime l'empreinte mémoire d'informations de navigation. */
+static void fini_navigation_info(navigation_info_t *);
+
+/* S'assure de l'affichage à jour de la partie "navigation". */
+static gboolean gtk_status_stack_show_current_location(gpointer);
+
+/* Réagit à un clic sur l'icône de zoom. */
+static void gtk_status_stack_on_zoom_icon_press(GtkEntry *, GtkEntryIconPosition, GtkStatusStack *);
+
+
+
+/* -------------------------- STATUT DES SUIVIS D'ACTIVITE -------------------------- */
+
+
+/* Informations de progression */
+typedef struct _activity_status_t
+{
+ activity_id_t id; /* Identifiant unique */
+
+ char *message; /* Indication à faire valoir */
+
+ unsigned long current; /* Position courante */
+ unsigned long max; /* Couverture à parcourir */
+
+ double last_updated; /* Dernière valeur poussée */
+
+} activity_status_t;
+
+
+/* Mémorisation des progressions au sein d'activités */
+struct _activity_info_t
+{
+ GMutex access; /* Accès à la pile */
+
+ activity_id_t generator; /* Générateur de séquence */
+
+ activity_status_t *statuses; /* Statuts de progression */
+ size_t count; /* Nombre de ces statuts */
+
+ guint tag; /* Identifiant de mise à jour */
+
+};
+
+
+/* Met en place le suivi d'informations d'activité. */
+static void init_activity_info(activity_info_t *);
+
+/* Supprime l'empreinte mémoire d'informations d'activité. */
+static void fini_activity_info(activity_info_t *);
+
+/* Recherche les indications de statut d'une activité donnée. */
+static activity_status_t *find_activity_status_by_id(activity_info_t *, activity_id_t);
+
+/* S'assure de l'affichage à jour de la partie "activité". */
+static gboolean gtk_status_stack_show_current_activity(gpointer);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GESTION GENERALE DES STATUTS */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkStatusStack, gtk_status_stack, GTK_TYPE_BOX);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des barres de statut améliorées. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_class_init(GtkStatusStackClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_status_stack_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_status_stack_finalize;
+ object->set_property = gtk_status_stack_set_property;
+ object->get_property = gtk_status_stack_get_property;
+
+ _status_stack_properties[PROP_SHOW_BOTTOM] =
+ g_param_spec_boolean("show-bottom", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _status_stack_properties);
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/statusstack.ui");
+
+ gtk_widget_class_bind_template_callback_full(widget, BUILDER_CB(gtk_status_stack_on_zoom_icon_press));
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, main);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, def_label);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_segment);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_phys);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_virt);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_offset);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_format);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, nav_details);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, zoom);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_message);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, activity_progress);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, lock_update);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_recv_speed);
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, net_send_speed);
+
+ gtk_widget_class_bind_template_child(widget, GtkStatusStack, bottom_toggler);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de barre de statut améliorée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_init(GtkStatusStack *stack)
+{
+ gtk_widget_init_template(GTK_WIDGET(stack));
+
+ stack->def_source = gtk_status_stack_default_source;
+
+ stack->msg = NULL;
+
+ stack->nav_info = calloc(1, sizeof(navigation_info_t));
+ init_navigation_info(stack->nav_info);
+
+ stack->activity_info = calloc(1, sizeof(activity_info_t));
+ init_activity_info(stack->activity_info);
+
+ /* Suivi des évolutions relatives au stockage sécurisé */
+
+ stack->storage = get_secret_storage();
+
+ g_signal_connect(stack->storage, "lock-update",
+ G_CALLBACK(gtk_status_stack_on_secret_storage_lock_update), stack);
+
+ gtk_status_stack_on_secret_storage_lock_update(stack->storage, stack);
+
+ /* Suivi des débits de connexion */
+
+ stack->next_index = 0;
+
+ stack->network_update_tag = g_timeout_add(NETWORK_UPDATE_INTERVAL,
+ G_SOURCE_FUNC(gtk_status_stack_update_network_stats), stack);
+
+ /* Premier affichage... */
+
+ gtk_status_stack_reset_to_default(stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_dispose(GtkStatusStack *stack)
+{
+ if (stack->storage != NULL)
+ g_signal_handlers_disconnect_by_func(stack->storage,
+ gtk_status_stack_on_secret_storage_lock_update, stack);
+
+ g_clear_object(&stack->storage);
+
+ g_source_remove(stack->network_update_tag);
+
+ gtk_widget_dispose_template(GTK_WIDGET(stack), GTK_TYPE_STATUS_STACK);
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->dispose(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_finalize(GtkStatusStack *stack)
+{
+ if (stack->msg != NULL)
+ free(stack->msg);
+
+ fini_navigation_info(stack->nav_info);
+ free(stack->nav_info);
+
+ fini_activity_info(stack->activity_info);
+ free(stack->activity_info);
+
+ G_OBJECT_CLASS(gtk_status_stack_parent_class)->finalize(G_OBJECT(stack));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle instance de barre de statut. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkStatusStack *gtk_status_stack_new(void)
+{
+ GtkStatusStack *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_STATUS_STACK, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Réinitialise la barre de statut à son stade par défaut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_reset_to_default(GtkStatusStack *stack)
+{
+ /**
+ * Une amélioration possible serait de passer à g_idle_add_once(),
+ * et de s'affranchir des retours G_SOURCE_REMOVE systématiques,
+ * mais la fonction n'est disponible qu'à partir de la GLib 2.74.
+ */
+
+ g_idle_add(stack->def_source, stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gardien des secrets impliqué. *
+* stack = barre de statut à actualiser. *
+* *
+* Description : Note le changement de verrouillage du stockage sécurisé. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_on_secret_storage_lock_update(GSecretStorage *storage, GtkStatusStack *stack)
+{
+ if (!g_secret_storage_has_key(stack->storage))
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(stack->lock_update), false);
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "nolock-symbolic");
+ }
+ else
+ {
+ gtk_widget_set_sensitive(GTK_WIDGET(stack->lock_update), true);
+
+ if (g_secret_storage_is_locked(stack->storage))
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "locked-symbolic");
+ else
+ gtk_button_set_icon_name(GTK_BUTTON(stack->lock_update), "unlocked-symbolic");
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Met à jour dans la barre les débits réseau observés. *
+* *
+* Retour : G_SOURCE_CONTINUE pour poursuivre les mises à jour. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_update_network_stats(GtkStatusStack *stack)
+{
+ gboolean result; /* Indication à retourner */
+ gint64 timestamp; /* Position temporelle */
+ size_t received; /* Quantité d'octets reçus */
+ size_t sent; /* Quantité d'octets émis */
+ gint64 diff_time; /* Différentiel de temps */
+ size_t diff_bytes; /* Différentiel de volume */
+ double speed; /* Débit de transfert constaté */
+ size_t i; /* Boucle de parcours */
+ char *value; /* Valeur à afficher */
+
+ const char *units[] = { _("b/s"), _("kb/s"), _("Mb/s"), _("Gb/s"), _("Tb/s") };
+
+ result = G_SOURCE_CONTINUE;
+
+ /* Mémorisation des données */
+
+ timestamp = g_get_monotonic_time();
+
+ get_network_stats(&received, &sent);
+
+ if (stack->next_index < NETWORK_UPDATE_COUNT)
+ {
+ stack->last_bytes_received[stack->next_index] = received;
+ stack->last_bytes_sent[stack->next_index] = sent;
+ stack->last_timestamps[stack->next_index] = timestamp;
+
+ stack->next_index++;
+
+ }
+ else
+ {
+ memcpy(stack->last_bytes_received, stack->last_bytes_received + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t));
+
+ memcpy(stack->last_bytes_sent, stack->last_bytes_sent + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(size_t));
+
+ memcpy(stack->last_timestamps, stack->last_timestamps + 1,
+ (NETWORK_UPDATE_COUNT - 1) * sizeof(gint64));
+
+ stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] = received;
+ stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] = sent;
+ stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] = timestamp;
+
+ }
+
+ if (stack->next_index < NETWORK_UPDATE_COUNT)
+ goto done;
+
+ diff_time = stack->last_timestamps[NETWORK_UPDATE_COUNT - 1] - stack->last_timestamps[0];
+
+ /* Débit de réception */
+
+ diff_bytes = stack->last_bytes_received[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_received[0];
+
+ speed = (diff_bytes * 1000000) / diff_time;
+
+ for (i = 0; i < G_N_ELEMENTS(units); i++)
+ {
+ if (speed < 1024)
+ break;
+
+ speed /= 1024;
+
+ }
+
+ if (i == 0)
+ asprintf(&value, "%d %s", (int)speed, units[i]);
+ else
+ asprintf(&value, "%.1f %s", speed, units[i]);
+
+ gtk_label_set_label(stack->net_recv_speed, value);
+
+ free(value);
+
+ /* Débit de émission */
+
+ diff_bytes = stack->last_bytes_sent[NETWORK_UPDATE_COUNT - 1] - stack->last_bytes_sent[0];
+
+ speed = (diff_bytes * 1000000) / diff_time;
+
+ for (i = 0; i < G_N_ELEMENTS(units); i++)
+ {
+ if (speed < 1024)
+ break;
+
+ speed /= 1024;
+
+ }
+
+ if (i == 0)
+ asprintf(&value, "%d %s", (int)speed, units[i]);
+ else
+ asprintf(&value, "%.1f %s", speed, units[i]);
+
+ gtk_label_set_label(stack->net_send_speed, value);
+
+ free(value);
+
+ done:
+
+ return result;
+
+}
+
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à prendre en compte. *
+* pspec = définition de la propriété. *
+* *
+* Description : Met à jour une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ gtk_toggle_button_set_active(stack->bottom_toggler, g_value_get_boolean(value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(object);
+
+ switch (prop_id)
+ {
+ case PROP_SHOW_BOTTOM:
+ g_value_set_boolean(value, gtk_toggle_button_get_active(stack->bottom_toggler));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+
+ }
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* MISE EN AVANT DES MESSAGES SIMPLES */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* msg = simple message à faire paraître. *
+* *
+* Description : Inscrit un message simple dans la barre de statut. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_display_message(GtkStatusStack *stack, const char *msg)
+{
+ if (stack->msg != NULL)
+ free(stack->msg);
+
+ if (msg != NULL)
+ stack->msg = strdup(msg);
+ else
+ stack->msg = NULL;
+
+ gtk_status_stack_show_simple_message(stack);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "default". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_simple_message(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+
+ stack = GTK_STATUS_STACK(data);
+
+ stack->def_source = gtk_status_stack_show_simple_message;
+
+ gtk_label_set_text(stack->def_label, stack->msg != NULL ? stack->msg : "");
+
+ gtk_stack_set_visible_child_name(stack->main, "default");
+
+ return G_SOURCE_REMOVE;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* STATUT DES INFORMATIONS DE DESASSEMBLAGE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à initialiser. *
+* *
+* Description : Met en place le suivi d'informations de navigation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_navigation_info(navigation_info_t *info)
+{
+ info->segment = NULL;
+
+ info->symbol = NULL;
+
+ info->format = NULL;
+ info->details = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à libérer de la mémoire. *
+* *
+* Description : Supprime l'empreinte mémoire d'informations de navigation. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fini_navigation_info(navigation_info_t *info)
+{
+ if (info->segment != NULL)
+ free(info->segment);
+
+ if (info->symbol != NULL)
+ free(info->symbol);
+
+ if (info->format != NULL)
+ free(info->format);
+
+ if (info->details != NULL)
+ free(info->details);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* range = emplacement à mettre en valeur. *
+* segment = zone de binaire d'appartenance. *
+* symbol = éventuelle position par rapport à un symbole. *
+* format = format du binaire manipulé *
+* details = détails supplémentaires (liés à l'encodage ?) *
+* *
+* Description : Actualise les informations liées une position d'assemblage. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_current_location(GtkStatusStack *stack, const mrange_t *range, const char *segment, const char *symbol, const char *format, const char *details)
+{
+ navigation_info_t *info; /* Informations à constituer */
+ const vmpa2t *addr; /* Localisation de départ */
+
+ info = stack->nav_info;
+
+ if (cmp_mrange(&info->current, range) == 0)
+ goto useless;
+
+ /* Zone d'appartenance */
+
+ if (segment != NULL)
+ info->segment = strdup(segment);
+ else
+ info->segment = NULL;
+
+ /* Adresses de base */
+
+ copy_mrange(&info->current, range);
+
+ addr = get_mrange_addr(range);
+
+ vmpa2_phys_to_string(addr, MDS_UNDEFINED, info->phys, NULL);
+
+ vmpa2_virt_to_string(addr, MDS_UNDEFINED, info->virt, NULL);
+
+ /* Symbole concerné */
+
+ if (symbol != NULL)
+ info->symbol = strdup(symbol);
+ else
+ info->symbol = NULL;
+
+ /* Architecture & format */
+
+ info->format = strdup(format);
+
+ if (details != NULL)
+ info->details = strdup(details);
+ else
+ info->details = NULL;
+
+ /* Nettoyage et conclusion */
+
+ gtk_status_stack_show_current_location(stack);
+
+ useless:
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "navigation". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_current_location(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+ navigation_info_t *info; /* Informations à constituer */
+ char raw_pos[6 + VMPA_MAX_LEN + 1]; /* Formatage final en direct */
+
+ stack = GTK_STATUS_STACK(data);
+
+ stack->def_source = gtk_status_stack_show_current_location;
+
+ info = stack->nav_info;
+
+ /* Première partie : navigation */
+
+ gtk_label_set_text(stack->nav_segment, info->segment != NULL ? info->segment : "");
+
+ snprintf(raw_pos, sizeof(raw_pos), "phys: %s", info->phys);
+
+ gtk_label_set_text(stack->nav_phys, raw_pos);
+
+ snprintf(raw_pos, sizeof(raw_pos), "virt: %s", info->virt);
+
+ gtk_label_set_text(stack->nav_virt, raw_pos);
+
+ gtk_label_set_text(stack->nav_offset, info->symbol != NULL ? info->symbol : "");
+
+ /* Seconde partie : format & architecture */
+
+ gtk_label_set_text(stack->nav_format, info->format);
+
+ gtk_label_set_text(stack->nav_details, info->details != NULL ? info->details : "");
+
+ /* Conclusion */
+
+ gtk_stack_set_visible_child_name(stack->main, "navigation");
+
+ return G_SOURCE_REMOVE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = zone de texte visée par la procédure. *
+* icon_pos = position de l'image associée à l'entrée. *
+* stack = composant graphique de gestion des statuts. *
+* *
+* Description : Réagit à un clic sur l'icône de zoom. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_status_stack_on_zoom_icon_press(GtkEntry *entry, GtkEntryIconPosition icon_pos, GtkStatusStack *stack)
+{
+#if 0
+ GtkWidget *popup; /* Popup à faire surgir */
+ GdkRectangle rect; /* Zone précise à cibler */
+
+ popup = gtk_popover_new();
+
+ gtk_entry_get_icon_area(entry, GTK_ENTRY_ICON_SECONDARY, &rect);
+ gtk_popover_set_pointing_to(GTK_POPOVER(popup), &rect);
+
+ gtk_widget_show(popup);
+#endif
+}
+
+
+/* ---------------------------------------------------------------------------------- */
+/* STATUT DES SUIVIS D'ACTIVITE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à initialiser. *
+* *
+* Description : Met en place le suivi d'informations d'activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void init_activity_info(activity_info_t *info)
+{
+ g_mutex_init(&info->access);
+
+ info->generator = NO_ACTIVITY_ID;
+
+ info->statuses = NULL;
+ info->count = 0;
+
+ info->tag = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations à libérer de la mémoire. *
+* *
+* Description : Supprime l'empreinte mémoire d'informations d'activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void fini_activity_info(activity_info_t *info)
+{
+ size_t i; /* Boucle de parcours */
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = 0;
+
+ for (i = 0; i < info->count; i++)
+ {
+ if (info->statuses[i].message != NULL)
+ free(info->statuses[i].message);
+ }
+
+ if (info->statuses != NULL)
+ {
+ free(info->statuses);
+ info->statuses = NULL;
+ }
+
+ info->count = 0;
+
+ g_mutex_clear(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations relatives aux activités à consulter. *
+* id = identifiant de l'activité à cibler. *
+* *
+* Description : Recherche les indications de statut d'une activité donnée. *
+* *
+* Retour : Structure d'encadrement trouvée ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static activity_status_t *find_activity_status_by_id(activity_info_t *info, activity_id_t id)
+{
+ activity_status_t *result; /* Statut trouvé à renvoyer */
+ size_t i; /* Boucle de parcours */
+
+ result = NULL;
+
+ assert(!g_mutex_trylock(&info->access));
+
+ for (i = 0; i < info->count; i++)
+ if (info->statuses[i].id == id)
+ {
+ result = info->statuses + i;
+ break;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* msg = nouveau message de statut à copier. *
+* max = taille de la plage à parcourir. *
+* *
+* Description : Démarre le suivi d'une nouvelle activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+activity_id_t gtk_status_stack_add_activity(GtkStatusStack *stack, const char *msg, unsigned long max)
+{
+ activity_id_t result; /* Numéro unique à renvoyer */
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *new; /* Nouveau suivi d'activité */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ while (1)
+ {
+ result = ++info->generator;
+
+ if (find_activity_status_by_id(info, result) == NULL)
+ break;
+
+ }
+ while (0);
+
+ info->statuses = realloc(info->statuses, ++info->count * sizeof(activity_status_t));
+
+ new = info->statuses + info->count - 1;
+
+ /* Identifiant */
+
+ new->id = result;
+
+ /* Intitulé */
+
+ if (msg == NULL)
+ new->message = NULL;
+ else
+ new->message = strdup(msg);
+
+ /* Valeur */
+
+ new->current = 0;
+ new->max = max;
+ new->last_updated = 0;
+
+ /* Actualisation */
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ g_mutex_unlock(&info->access);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* msg = nouveau message de statut à copier. *
+* *
+* Description : Actualise les informations concernant une activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_activity_message(GtkStatusStack *stack, activity_id_t id, const char *msg)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ bool msg_changed; /* Changement d'intitulé */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Intitulé */
+
+ if (status->message != NULL)
+ {
+ if (msg == NULL)
+ msg_changed = true;
+ else
+ msg_changed = (strcmp(status->message, msg) != 0);
+
+ free(status->message);
+
+ }
+ else
+ msg_changed = (msg != NULL);
+
+ if (msg == NULL)
+ status->message = NULL;
+ else
+ status->message = strdup(msg);
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count && msg_changed)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* inc = nouvelle valeur pour une progression donnée. *
+* *
+* Description : Actualise la progression d'une activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_update_activity_value(GtkStatusStack *stack, activity_id_t id, unsigned long inc)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ double new; /* Nouvelle progression */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Valeur */
+
+ status->current += inc;
+
+ new = (status->current * 1.0) / status->max;
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count && (new - status->last_updated) > 0.1)
+ {
+ status->last_updated = new;
+
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* id = identifiant de l'activité à cibler. *
+* extra = nouvelle échéance supplémentaire des traitements. *
+* *
+* Description : Etend la portée des travaux d'une nouvelle activité. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_extend_activity_max(GtkStatusStack *stack, activity_id_t id, unsigned long extra)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ /* Valeur */
+
+ status->max += extra;
+
+ /* On n'actualise que le sommet de la pile */
+
+ if ((status - info->statuses + 1) == info->count)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ }
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : stack = barre de statut à actualiser. *
+* *
+* Description : Met fin au suivi d'une activité donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void gtk_status_stack_remove_activity(GtkStatusStack *stack, activity_id_t id)
+{
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *status; /* Suivi d'activité à traiter */
+ bool is_last; /* Dernière position ? */
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ status = find_activity_status_by_id(info, id);
+
+ assert(status != NULL);
+
+ if (status == NULL)
+ goto exit;
+
+ is_last = ((status - info->statuses + 1) == info->count);
+
+ /* Suppression des données */
+
+ if (is_last)
+ {
+ if (info->tag != 0)
+ g_source_remove(info->tag);
+ }
+
+ if (status->message != NULL)
+ free(status->message);
+
+ /* Réajustement des enregistrements */
+
+ if (!is_last)
+ memmove(status, status + 1,
+ (((info->statuses + info->count) - status) - 1) * sizeof(activity_status_t));
+
+ info->statuses = realloc(info->statuses, --info->count * sizeof(activity_status_t));
+
+ /* Bascule vers un autre affichage ou actualisation ? */
+
+ if (info->count == 0)
+ {
+ info->tag = 0;
+ gtk_status_stack_reset_to_default(stack);
+ }
+ else if (is_last)
+ info->tag = g_idle_add(gtk_status_stack_show_current_activity, stack);
+
+ exit:
+
+ g_mutex_unlock(&info->access);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : data = pile de statuts à manipuler. *
+* *
+* Description : S'assure de l'affichage à jour de la partie "activité". *
+* *
+* Retour : G_SOURCE_REMOVE pour une exécution unique. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static gboolean gtk_status_stack_show_current_activity(gpointer data)
+{
+ GtkStatusStack *stack; /* Version spécialisée */
+ activity_info_t *info; /* Informations à consulter */
+ activity_status_t *last; /* Dernier statut à traiter */
+
+ stack = GTK_STATUS_STACK(data);
+
+ info = stack->activity_info;
+
+ g_mutex_lock(&info->access);
+
+ if (!g_source_is_destroyed(g_main_current_source()))
+ {
+ if (info->count > 0)
+ {
+ last = &info->statuses[info->count - 1];
+
+ gtk_label_set_text(stack->activity_message, last->message);
+
+ gtk_progress_bar_set_fraction(stack->activity_progress, (last->current * 1.0) / last->max);
+
+ gtk_stack_set_visible_child_name(stack->main, "activity");
+
+ }
+
+ info->tag = 0;
+
+ }
+
+ g_mutex_unlock(&info->access);
+
+ return G_SOURCE_REMOVE;
+
+}
diff --git a/src/gtkext/gtkstatusstack.h b/src/gtkext/statusstack.h
index f419014..96d008c 100644
--- a/src/gtkext/gtkstatusstack.h
+++ b/src/gtkext/statusstack.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * gtkstatusstack.h - prototypes pour un empilement d'informations de statut
+ * statusstack.h - prototypes pour l'empilement d'informations de statut
*
- * Copyright (C) 2015-2019 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,40 +21,39 @@
*/
-#ifndef _GTKEXT_GTKSTATUSSTACK_H
-#define _GTKEXT_GTKSTATUSSTACK_H
+#ifndef _GTKEXT_STATUSSTACK_H
+#define _GTKEXT_STATUSSTACK_H
#include <gtk/gtk.h>
#include "../arch/vmpa.h"
+#include "../glibext/helpers.h"
-/* ------------------------- GESTION EXTERIEURE DE LA BARRE ------------------------- */
+/* -------------------------- GESTION GENERALE DES STATUTS -------------------------- */
-#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type())
-#define GTK_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_STATUS_STACK, GtkStatusStack))
-#define GTK_STATUS_STACK_CLASS(klass) (G_LOADED_BINARY_GET_CLASS(klass, GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
-#define GTK_IS_STATUS_STACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
-#define GTK_IS_STATUS_STACK_CLASS(obj) (G_TYPE_CHECK_INSTANCE_TYPE(obj, GTK_TYPE_STATUS_STACK))
-#define GTK_STATUS_STACK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_STATUS_STACK, GtkStatusStackClass))
+#define GTK_TYPE_STATUS_STACK (gtk_status_stack_get_type())
+DECLARE_GTYPE(GtkStatusStack, gtk_status_stack, GTK, STATUS_STACK);
-/* Abstration d'une gestion de barre de statut (instance) */
-typedef struct _GtkStatusStack GtkStatusStack;
-/* Abstration d'une gestion de barre de statut (classe) */
-typedef struct _GtkStatusStackClass GtkStatusStackClass;
+/* Crée une nouvelle instance de barre de statut. */
+GtkStatusStack *gtk_status_stack_new(void);
+/* Réinitialise la barre de statut à son stade par défaut. */
+void gtk_status_stack_reset_to_default(GtkStatusStack *);
-/* Détermine le type de la barre de statut améliorée. */
-GType gtk_status_stack_get_type(void);
-/* Crée une nouvelle instance de barre de statut. */
-GtkStatusStack *gtk_status_stack_new(void);
+
+/* ----------------------- MISE EN AVANT DES MESSAGES SIMPLES ----------------------- */
+
+
+/* Inscrit un message simple dans la barre de statut. */
+void gtk_status_stack_display_message(GtkStatusStack *, const char *);
@@ -62,10 +61,7 @@ GtkStatusStack *gtk_status_stack_new(void);
/* Actualise les informations liées une position d'assemblage. */
-void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *);
-
-/* Réinitialise les informations associées une position. */
-void gtk_status_stack_reset_current_location(GtkStatusStack *);
+void gtk_status_stack_update_current_location(GtkStatusStack *, const mrange_t *, const char *, const char *, const char *, const char *);
@@ -82,18 +78,18 @@ typedef unsigned long activity_id_t;
/* Démarre le suivi d'une nouvelle activité. */
activity_id_t gtk_status_stack_add_activity(GtkStatusStack *, const char *, unsigned long);
-/* Etend la portée des travaux d'une nouvelle activité. */
-void gtk_status_stack_extend_activity(GtkStatusStack *, activity_id_t, unsigned long);
-
/* Actualise les informations concernant une activité. */
-void gtk_status_stack_update_activity(GtkStatusStack *, activity_id_t, const char *);
+void gtk_status_stack_update_activity_message(GtkStatusStack *, activity_id_t, const char *);
/* Actualise la progression d'une activité. */
void gtk_status_stack_update_activity_value(GtkStatusStack *, activity_id_t, unsigned long);
+/* Etend la portée des travaux d'une nouvelle activité. */
+void gtk_status_stack_extend_activity_max(GtkStatusStack *, activity_id_t, unsigned long);
+
/* Met fin au suivi d'une activité donnée. */
void gtk_status_stack_remove_activity(GtkStatusStack *, activity_id_t);
-#endif /* _GTKEXT_GTKSTATUSSTACK_H */
+#endif /* _GTKEXT_STATUSSTACK_H */
diff --git a/src/gtkext/statusstack.ui b/src/gtkext/statusstack.ui
new file mode 100644
index 0000000..0b7cd6d
--- /dev/null
+++ b/src/gtkext/statusstack.ui
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkStatusStack" parent="GtkBox">
+
+ <!--property name="show-bottom" bind-source="bottom_toggler" bind-property="active" bind-flags="bidirectional|sync-create"/-->
+
+ <child>
+ <object class="GtkStack" id="main">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="hexpand">true</property>
+
+ <!-- Vide par défaut -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">default</property>
+ <property name="child">
+
+ <object class="GtkLabel" id="def_label">
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">baseline</property>
+ <property name="xalign">0</property>
+ <property name="label"></property>
+ <style>
+ <class name="dim-label"/>
+ </style>
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <!-- Informations pendant une navigation dans du contenu -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">navigation</property>
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+
+ <!-- Première partie : navigation -->
+
+ <child>
+ <object class="GtkLabel" id="nav_segment">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_phys">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_virt">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_offset">
+ <property name="xalign">0</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <!-- Seconde partie : architecture -->
+
+ <child>
+ <object class="GtkLabel" id="nav_format">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="nav_details">
+ <property name="xalign">0</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <!-- Troisième partie : affichage -->
+
+ <child>
+ <object class="GtkEntry" id="zoom">
+ <property name="secondary-icon-name">go-up-symbolic</property>
+ <signal name="icon-press" handler="gtk_status_stack_on_zoom_icon_press"/>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <!-- Informations liées à une activité en cours -->
+ <child>
+ <object class="GtkStackPage">
+ <property name="name">activity</property>
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+
+ <child>
+ <object class="GtkLabel" id="activity_message">
+ <property name="xalign">0</property>
+ <property name="margin-end">8</property>
+ <property name="label">-</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkProgressBar" id="activity_progress">
+ <property name="hexpand">true</property>
+ <property name="halign">fill</property>
+ <property name="valign">center</property>
+ <property name="fraction">0</property>
+ </object>
+ </child>
+
+ </object>
+
+ </property>
+ </object>
+ </child>
+
+ <property name="visible-child-name">default</property>
+ </object>
+ </child>
+
+ <!-- Tronc commun -->
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkToggleButton" id="lock_update">
+ <property name="sensitive">false</property>
+ <property name="has-frame">false</property>
+ <property name="icon-name">nolock-symbolic</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="margin-start">8</property>
+ <property name="icon-name">pan-down-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="net_recv_speed">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="xalign">0</property>
+ <property name="label">0 b/s</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage">
+ <property name="icon-name">pan-up-symbolic</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkLabel" id="net_send_speed">
+ <property name="margin-start">8</property>
+ <property name="margin-end">8</property>
+ <property name="xalign">0</property>
+ <property name="label">0 b/s</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkSeparator">
+ <property name="orientation">vertical</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkToggleButton" id="bottom_toggler">
+ <property name="has-frame">false</property>
+ <property name="icon-name">dock-station-bottom-symbolic</property>
+ <property name="action-name">win.toggle-bottom</property>
+ </object>
+ </child>
+
+ </template>
+</interface>
diff --git a/src/gtkext/tiledgrid.c b/src/gtkext/tiledgrid.c
deleted file mode 100644
index 22b2680..0000000
--- a/src/gtkext/tiledgrid.c
+++ /dev/null
@@ -1,1143 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * tiledgrid.c - composant d'affichage avec des chemins vers les composants contenus
- *
- * Copyright (C) 2018-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "tiledgrid.h"
-
-
-#include <assert.h>
-#include <ctype.h>
-#include <malloc.h>
-#include <string.h>
-
-
-#include "../core/logs.h"
-
-
-
-/* -------------------------- GESTION DES TUILES AFFICHEES -------------------------- */
-
-
-/* Informations concernant une tuile */
-typedef struct _grid_tile_t
-{
- struct _grid_tile_t *parent; /* Tuile parente */
-
- GtkWidget *widget; /* Support d'affichage */
-
- char *path; /* Chemin d'accès */
-
- struct _grid_tile_t *children[2]; /* Tuiles encastrées ou 2xNULL */
-
-} grid_tile_t;
-
-
-#define IS_LEAF_TILE(t) \
- ({ \
- bool __result; \
- __result = GTK_IS_DOCK_STATION((t)->widget); \
- assert(__result || GTK_IS_PANED((t)->widget)); \
- __result; \
- })
-
-
-/* Valide un chemin d'accès à une tuile. */
-static bool is_valid_tile_path(const char *);
-
-/* Crée une tuile finale d'affichage de panneaux. */
-static grid_tile_t *create_leaf_tile(const char *, GtkTiledGrid *);
-
-/* Crée une tuile intermédiaire d'affichage de panneaux. */
-static grid_tile_t *create_inter_tile(grid_tile_t *, bool, grid_tile_t *, grid_tile_t *);
-
-/* Supprime une tuile de la mémoire. */
-static void delete_tile(grid_tile_t *);
-
-/* Calcule la taille comme entre un chemin et celui d'une tuile. */
-static size_t compute_tile_score(const grid_tile_t *, const char *);
-
-/* Indique la tuile adaptée pour un chemin donné. */
-static grid_tile_t *find_suitable_tile(grid_tile_t **, const char *, GtkTiledGrid *);
-
-/* Découpe une tuile pour y insérer une zone. */
-static grid_tile_t *split_tile(grid_tile_t **, const char *, char, GtkTiledGrid *);
-
-/* Tente de mettre la main sur une station d'accueil. */
-static grid_tile_t *find_tile_for_widget(grid_tile_t *, GtkWidget *);
-
-/* Retire une moitié de tuile vide au plein profit de l'autre. */
-static void collapse_tile(grid_tile_t *, grid_tile_t *);
-
-
-
-/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
-
-
-/* Conteneur pour un affichage en tuiles nommées (instance) */
-struct _GtkTiledGrid
-{
- GtkBin parent; /* A laisser en premier */
-
- grid_tile_t *tiles; /* Tuiles représentées */
-
- GPanelItem *def_panel; /* Panneau principal par défaut*/
-
-};
-
-/* Conteneur pour un affichage en tuiles nommées (classe) */
-struct _GtkTiledGridClass
-{
- GtkBinClass parent; /* A laisser en premier */
-
- /* Signaux */
-
- void (* station_created) (GtkTiledGrid *, GtkDockStation *, gpointer);
-
-};
-
-
-/* Initialise la classe des conteneurs d'affichage en tuiles. */
-static void gtk_tiled_grid_class_init(GtkTiledGridClass *);
-
-/* Initialise une instance de conteneur d'affichage en tuiles. */
-static void gtk_tiled_grid_init(GtkTiledGrid *);
-
-/* Supprime toutes les références externes. */
-static void gtk_tiled_grid_dispose(GtkTiledGrid *);
-
-/* Procède à la libération totale de la mémoire. */
-static void gtk_tiled_grid_finalize(GtkTiledGrid *);
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* GESTION DES TUILES AFFICHEES */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-* *
-* Paramètres : path = chemin destiné à sélectionner une tuile. *
-* *
-* Description : Valide un chemin d'accès à une tuile. *
-* *
-* Retour : true si le chemin est utilisable, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_valid_tile_path(const char *path)
-{
- bool result; /* Bilan à retourner */
- size_t len; /* Taille du chemin */
- size_t i; /* Boucle de parcours */
- char c; /* Caractère de chemin analysé */
-
- /**
- * M[NESWnesw]*
- */
-
- len = strlen(path);
-
- result = (len >= 1);
-
- if (result)
- result = (path[0] == 'M');
-
- for (i = 1; i < len && result; i++)
- {
- c = path[i];
-
- if (c == '\0')
- break;
-
- result = (c == 'N' || c == 'n'
- || c == 'E' || c == 'e'
- || c == 'S' || c == 's'
- || c == 'W' || c == 'w');
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : path = chemin d'accès à la future tuile. *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Crée une tuile finale d'affichage de panneaux. *
-* *
-* Retour : Structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *create_leaf_tile(const char *path, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Structure à retourner */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = NULL;
-
- result->widget = gtk_dock_station_new();
- gtk_widget_show(result->widget);
-
- result->path = strdup(path);
-
- result->children[0] = NULL;
- result->children[1] = NULL;
-
- g_signal_emit_by_name(tgrid, "station-created", result->widget);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : parent = tuile parente ou NULL si aucune. *
-* horiz = indique le type d'orientation désiré. *
-* first = première tuile à intégrer. *
-* second = seconde tuile à intégrer. *
-* *
-* Description : Crée une tuile intermédiaire d'affichage de panneaux. *
-* *
-* Retour : Structure mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *create_inter_tile(grid_tile_t *parent, bool horiz, grid_tile_t *first, grid_tile_t *second)
-{
- grid_tile_t *result; /* Structure à retourner */
- GtkWidget *container; /* Conteneur à vider */
-
- result = (grid_tile_t *)malloc(sizeof(grid_tile_t));
-
- result->parent = parent;
-
- if (horiz)
- result->widget = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
- else
- result->widget = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
-
- gtk_widget_show(result->widget);
-
- result->path = NULL;
-
- result->children[0] = first;
- result->children[1] = second;
-
- /* Changement de propriétaire */
-
- container = gtk_widget_get_parent(first->widget);
-
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), first->widget);
-
- g_object_ref(G_OBJECT(first->widget));
- gtk_paned_pack1(GTK_PANED(result->widget), first->widget, TRUE, FALSE);
-
- container = gtk_widget_get_parent(second->widget);
-
- if (container != NULL)
- gtk_container_remove(GTK_CONTAINER(container), second->widget);
-
- g_object_ref(G_OBJECT(second->widget));
- gtk_paned_pack2(GTK_PANED(result->widget), second->widget, TRUE, FALSE);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à supprimer. *
-* *
-* Description : Supprime une tuile de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void delete_tile(grid_tile_t *tile)
-{
- if (!IS_LEAF_TILE(tile))
- {
- delete_tile(tile->children[0]);
- delete_tile(tile->children[1]);
- }
-
- else
- free(tile->path);
-
- g_object_unref(G_OBJECT(tile->widget));
-
- free(tile);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à analyser. *
-* path = chemin final complet recherché. *
-* *
-* Description : Calcule la taille comme entre un chemin et celui d'une tuile.*
-* *
-* Retour : Quantité de caractères communs. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static size_t compute_tile_score(const grid_tile_t *tile, const char *path)
-{
- size_t result; /* Nombre de points à renvoyer */
- size_t max; /* Taille du chemin de la tuile*/
- size_t i; /* Boucle de parcours */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
-
- if (IS_LEAF_TILE(tile))
- {
- max = strlen(tile->path);
-
- if (strlen(path) < max)
- result = 0;
-
- else
- {
- result = 0;
-
- for (i = 0; i < max; i++)
- {
- if (tolower((unsigned char)tile->path[i]) == tolower((unsigned char)path[i]))
- result++;
- else
- break;
- }
-
- }
-
- }
- else
- {
- score_0 = compute_tile_score(tile->children[0], path);
- score_1 = compute_tile_score(tile->children[1], path);
-
- result = score_0 > score_1 ? score_0 : score_1;
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile ou NULL si aucune. [OUT] *
-* path = chemin d'accès à la tuile visée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Indique la tuile adaptée pour un chemin donné. *
-* *
-* Retour : Structure d'acceuil à disposition. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *find_suitable_tile(grid_tile_t **tile, const char *path, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Structure à renvoyer */
- size_t best_len; /* Taille du chemin associé */
- size_t score_0; /* Score du sous-élément #1 */
- size_t score_1; /* Score du sous-élément #2 */
- char *sub_path; /* Nouvelle tentative d'accès */
- grid_tile_t **best; /* Direction à prendre */
- unsigned char next; /* Prochaine étape */
-
- /* Cas d'école : appel initial */
- if (*tile == NULL)
- {
- assert(path[0] == 'M' && path[1] == '\0');
-
- result = create_leaf_tile("M", tgrid);
- *tile = result;
-
- }
-
- else
- {
- if (IS_LEAF_TILE(*tile))
- {
- best_len = compute_tile_score(*tile, path);
-
- assert(best_len > 0);
-
- if (path[best_len] == '\0')
- result = *tile;
-
- else
- result = split_tile(tile, path, path[best_len], tgrid);
-
- }
-
- else
- {
- score_0 = compute_tile_score((*tile)->children[0], path);
- score_1 = compute_tile_score((*tile)->children[1], path);
-
- assert(score_0 > 0 || score_0 > 0);
-
- if (score_0 == score_1)
- {
- sub_path = strndup(path, score_0);
-
- score_0 = compute_tile_score((*tile)->children[0], sub_path);
- score_1 = compute_tile_score((*tile)->children[1], sub_path);
-
- free(sub_path);
-
- }
-
- if (score_0 == score_1)
- result = split_tile(tile, path, path[score_0], tgrid);
-
- else
- {
- if (score_0 > score_1)
- {
- best = &(*tile)->children[0];
- best_len = score_0;
- }
- else
- {
- best = &(*tile)->children[1];
- best_len = score_1;
- }
-
- /**
- * Si on vient de tomber une feuille, trois cas de figure :
- * - soit c'est elle qui est visée.
- * - soit on veut la diviser.
- * - soit on veut la diviser en englobant ses voisines.
- */
-
- if (IS_LEAF_TILE(*best))
- {
- assert(best_len <= strlen(path));
-
- next = path[best_len];
-
- /* Premier cas */
- if (next == '\0')
- result = *best;
-
- else
- {
- /* Second cas */
- if (islower(next))
- result = find_suitable_tile(best, path, tgrid);
-
- /* Troisième cas */
- else
- result = split_tile(tile, path, next, tgrid);
-
- }
-
- }
-
- else
- result = find_suitable_tile(best, path, tgrid);
-
- }
-
- }
-
- }
-
- assert(IS_LEAF_TILE(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile à découper en deux. [OUT] *
-* path = chemin d'accès à la future tuile. *
-* endpoint = désignation de la zone représentée. *
-* tgrid = conteneur d'affichage en tuiles à manipuler. *
-* *
-* Description : Découpe une tuile pour y insérer une zone. *
-* *
-* Retour : Structure fille mise en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *split_tile(grid_tile_t **tile, const char *path, char endpoint, GtkTiledGrid *tgrid)
-{
- grid_tile_t *result; /* Création à retourner */
- GtkWidget *container; /* Conteneur à vider */
- grid_tile_t *new; /* Nouvelle tuile intermédiaire*/
-
- container = gtk_widget_get_parent((*tile)->widget);
-
- /* Création */
-
- result = create_leaf_tile(path, tgrid);
-
- /* Encapsulation */
-
- switch (endpoint)
- {
- case 'N':
- case 'n':
- new = create_inter_tile((*tile)->parent, false, result, *tile);
- break;
-
- case 'E':
- case 'e':
- new = create_inter_tile((*tile)->parent, true, *tile, result);
- break;
-
- case 'S':
- case 's':
- new = create_inter_tile((*tile)->parent, false, *tile, result);
- break;
-
- case 'W':
- case 'w':
- new = create_inter_tile((*tile)->parent, true, result, *tile);
- break;
-
- default:
- assert(false);
- new = NULL;
- break;
-
- }
-
- /* Connexions */
-
- *tile = new;
-
- result->parent = new;
-
- if (container != NULL)
- {
- g_object_ref(G_OBJECT(new->widget));
- gtk_container_add(GTK_CONTAINER(container), new->widget);
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = tuile parente, prochaine victime de promotion. *
-* side = côté de tuile amené à disparaître. *
-* *
-* Description : Retire une moitié de tuile vide au plein profit de l'autre. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void collapse_tile(grid_tile_t *tile, grid_tile_t *side)
-{
- grid_tile_t *promoted; /* Tuile à faire remonter */
- GtkWidget *container; /* Conteneur à vider */
-
- assert(!IS_LEAF_TILE(tile));
-
- /* Sélection du remplaçant */
-
- if (side == tile->children[0])
- promoted = tile->children[1];
- else
- promoted = tile->children[0];
-
- /* Etablissement d'une place nette */
-
- gtk_container_remove(GTK_CONTAINER(tile->widget), promoted->widget);
-
- container = gtk_widget_get_parent(tile->widget);
- gtk_container_remove(GTK_CONTAINER(container), tile->widget);
-
- delete_tile(side);
-
- /* Promotion effective */
-
- tile->widget = promoted->widget;
-
- tile->path = promoted->path;
-
- tile->children[0] = promoted->children[0];
- tile->children[1] = promoted->children[1];
-
- g_object_ref(G_OBJECT(promoted->widget));
- gtk_container_add(GTK_CONTAINER(container), tile->widget);
-
- free(promoted);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tile = point de départ des recherches locales. *
-* widget = composant graphique à retrouver. *
-* *
-* Description : Tente de mettre la main sur une station d'accueil. *
-* *
-* Retour : Eventuelle tuile trouvée ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static grid_tile_t *find_tile_for_widget(grid_tile_t *tile, GtkWidget *widget)
-{
- grid_tile_t *result; /* Tuile à retourner */
-
- if (IS_LEAF_TILE(tile))
- result = tile->widget == widget ? tile : NULL;
-
- else
- {
- result = find_tile_for_widget(tile->children[0], widget);
-
- if (result == NULL)
- result = find_tile_for_widget(tile->children[1], widget);
-
- }
-
- return result;
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/* INTERFACE DU COMPOSANT GTK */
-/* ---------------------------------------------------------------------------------- */
-
-
-/* Détermine le type du conteneur d'affichage en tuiles nommées. */
-G_DEFINE_TYPE(GtkTiledGrid, gtk_tiled_grid, GTK_TYPE_BIN)
-
-
-/******************************************************************************
-* *
-* Paramètres : klass = classe GTK à initialiser. *
-* *
-* Description : Initialise la classe des conteneurs d'affichage en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_class_init(GtkTiledGridClass *klass)
-{
- GObjectClass *object; /* Autre version de la classe */
-
- object = G_OBJECT_CLASS(klass);
-
- object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tiled_grid_dispose;
- object->finalize = (GObjectFinalizeFunc)gtk_tiled_grid_finalize;
-
- g_signal_new("station-created",
- GTK_TYPE_TILED_GRID,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(GtkTiledGridClass, station_created),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_DOCK_STATION);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance GTK à initialiser. *
-* *
-* Description : Initialise une instance de conteneur d'affichage en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_init(GtkTiledGrid *tgrid)
-{
- tgrid->tiles = NULL;
-
- tgrid->def_panel = NULL;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance d'objet GLib à traiter. *
-* *
-* Description : Supprime toutes les références externes. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_dispose(GtkTiledGrid *tgrid)
-{
- if (tgrid->tiles != NULL)
- {
- delete_tile(tgrid->tiles);
- tgrid->tiles = NULL;
- }
-
- g_clear_object(&tgrid->def_panel);
-
- G_OBJECT_CLASS(gtk_tiled_grid_parent_class)->dispose(G_OBJECT(tgrid));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = instance d'objet GLib à traiter. *
-* *
-* Description : Procède à la libération totale de la mémoire. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void gtk_tiled_grid_finalize(GtkTiledGrid *tgrid)
-{
- G_OBJECT_CLASS(gtk_tiled_grid_parent_class)->finalize(G_OBJECT(tgrid));
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Crée une nouvelle instance de conteneur avec tuiles. *
-* *
-* Retour : Composant GTK mis en place. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GtkWidget *gtk_tiled_grid_new(void)
-{
- return g_object_new(GTK_TYPE_TILED_GRID, NULL);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* *
-* Description : Donne le panneau fourni par défaut pour la zone principale. *
-* *
-* Retour : Panneau d'affichage par défault ou NULL. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *tgrid)
-{
- GPanelItem *result; /* Panneau à retourner */
-
- result = tgrid->def_panel;
-
- if (result != NULL)
- g_object_ref(G_OBJECT(result));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage par défault ou NULL. *
-* *
-* Description : Fournit le panneau par défaut pour la zone principale. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- GtkWidget *widget; /* Composant GTK à retirer */
- GtkWidget *parent; /* Conteneur à vider */
- grid_tile_t *tile; /* Première tuile d'accueil */
-
- if (tgrid->def_panel != NULL)
- {
- widget = gtk_dockable_build_widget(GTK_DOCKABLE(tgrid->def_panel));
-
- parent = gtk_widget_get_parent(widget);
-
- if (parent != NULL)
- gtk_container_remove(GTK_CONTAINER(parent), widget);
-
- g_object_unref(G_OBJECT(widget));
-
- g_object_unref(G_OBJECT(tgrid->def_panel));
-
- }
-
- tgrid->def_panel = panel;
-
- if (panel != NULL)
- {
- g_object_ref(G_OBJECT(panel));
-
- if (tgrid->tiles == NULL)
- gtk_tiled_grid_add(tgrid, panel);
-
- else
- {
- tile = find_suitable_tile(&tgrid->tiles, "M", tgrid);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(tile->widget)) == 0)
- gtk_tiled_grid_add(tgrid, panel);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à intégrer. *
-* *
-* Description : Incorpore un nouveau panneau dans le conteneur en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_add(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- char *path; /* Chemin d'accès */
- char *name; /* Nom à donner à l'onglet */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- path = gtk_panel_item_class_get_path(G_PANEL_ITEM_GET_CLASS(panel));
-
- if (!is_valid_tile_path(path))
- {
- name = gtk_dockable_get_name(GTK_DOCKABLE(panel));
- log_variadic_message(LMT_ERROR, _("Invalid path '%s' for panel '%s'"), path, name);
- free(name);
- }
-
- else
- {
- tile = find_suitable_tile(&tgrid->tiles, path, tgrid);
- assert(tile != NULL);
-
- gtk_dock_station_add_dockable(GTK_DOCK_STATION(tile->widget), GTK_DOCKABLE(panel));
-
- g_panel_item_set_dock_at_startup(panel, true);
-
- /* Si c'est la toute première fois... */
- if (gtk_widget_get_parent(tile->widget) == NULL)
- {
- assert(tile == tgrid->tiles);
- assert(tile->path[0] == 'M' && tile->path[1] == '\0');
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_add(GTK_CONTAINER(tgrid), tile->widget);
- }
-
- /* Si on n'a plus besoin du panneau par défaut */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- {
- /* Si ce n'est pas le panneau qu'on vient de rajouter...*/
- if (panel != tgrid->def_panel)
- {
- /* Enfin : si ce panneau par défaut est réellement en place */
- if (g_panel_item_is_docked(tgrid->def_panel))
- gtk_tiled_grid_remove(tgrid, tgrid->def_panel);
-
- }
-
- }
-
- }
-
- free(path);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à modifier. *
-* panel = panneau d'affichage à supprimer. *
-* *
-* Description : Retire un panneau dans le conteneur en tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_remove(GtkTiledGrid *tgrid, GPanelItem *panel)
-{
- GtkWidget *station; /* Support courant */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- assert(g_panel_item_is_docked(panel));
-
- gtk_dockable_decompose(GTK_DOCKABLE(panel), &station);
-
- tile = find_tile_for_widget(tgrid->tiles, station);
- assert(tile != NULL);
-
- gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(panel));
-
- g_panel_item_set_dock_at_startup(panel, false);
-
- if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0)
- {
- /* Si le panneau par défaut devient nécessaire */
- if (tgrid->def_panel != NULL && tile->path[0] == 'M' && tile->path[1] == '\0')
- gtk_tiled_grid_add(tgrid, tgrid->def_panel);
-
- else
- {
- /* La racine est concernée ! */
- if (tile->parent == NULL)
- {
- assert(tile == tgrid->tiles);
-
- g_object_ref(G_OBJECT(tile->widget));
- gtk_container_remove(GTK_CONTAINER(tgrid), tile->widget);
-
- delete_tile(tile);
- tgrid->tiles = NULL;
-
- }
-
- else
- collapse_tile(tile->parent, tile);
-
- }
-
- }
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* station = station d'accueil à retrouver. *
-* *
-* Description : Indique le chemin correspondant à une station intégrée. *
-* *
-* Retour : Copie de chemin trouvé, à libérer ensuite, ou NULL si échec. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-char *gtk_tiled_grid_get_path_for_station(const GtkTiledGrid *tgrid, GtkDockStation *station)
-{
- char *result; /* Chemin d'accès à renvoyer */
- grid_tile_t *tile; /* Tuile d'accueil */
-
- tile = find_tile_for_widget(tgrid->tiles, GTK_WIDGET(station));
-
- if (tile == NULL)
- result = NULL;
-
- else
- result = strdup(tile->path);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à mettre à jour. *
-* config = configuration à consulter. *
-* *
-* Description : Replace les positions des séparateurs de tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_restore_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
-{
-
- void visit_tiles_for_restoring(grid_tile_t *tile, const char *vpath)
- {
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
-
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
-
- asprintf(&key, "%s%c", vpath, hint);
-
- if (g_generic_config_get_value(config, key, &position))
- gtk_paned_set_position(GTK_PANED(tile->widget), position);
-
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
-
- visit_tiles_for_restoring(tile->children[i], child_key);
-
- free(child_key);
-
- }
-
- free(key);
-
- }
-
- }
-
-
- visit_tiles_for_restoring(tgrid->tiles, "gui.panels.positions.R");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : tgrid = conteneur d'affichage en tuiles à consulter. *
-* config = configuration à mettre à jour. *
-* *
-* Description : Sauvegarde les positions des séparateurs de tuiles. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void gtk_tiled_grid_save_positions(const GtkTiledGrid *tgrid, GGenConfig *config)
-{
-
- void visit_tiles_for_saving(grid_tile_t *tile, const char *vpath)
- {
- GtkOrientation orientation; /* Direction de la tuile */
- char hint; /* Inutile donc indispensable */
- char *key; /* Clef d'accès à un paramètre */
- gint position; /* Nouvelle position de barre */
- size_t i; /* Boucle de parcours */
- char *child_key; /* Clef d'accès des suivants */
-
- if (!IS_LEAF_TILE(tile))
- {
- orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(tile->widget));
-
- hint = orientation == GTK_ORIENTATION_HORIZONTAL ? 'h' : 'v';
-
- asprintf(&key, "%s%c", vpath, hint);
-
- position = gtk_paned_get_position(GTK_PANED(tile->widget));
- g_generic_config_create_or_udpdate_param(config, key, CPT_INTEGER, -1, position);
-
- for (i = 0; i < 2; i++)
- {
- asprintf(&child_key, "%s%zu", key, i);
-
- visit_tiles_for_saving(tile->children[i], child_key);
-
- free(child_key);
-
- }
-
- free(key);
-
- }
-
- }
-
-
- visit_tiles_for_saving(tgrid->tiles, "gui.panels.positions.R");
-
-}
diff --git a/src/gtkext/tweak-int.h b/src/gtkext/tweak-int.h
new file mode 100644
index 0000000..0d2c213
--- /dev/null
+++ b/src/gtkext/tweak-int.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak-int.h - définitions internes pour une section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_TWEAK_INT_H
+#define _GTKEXT_TWEAK_INT_H
+
+
+#include "tweak.h"
+
+
+
+/* Section de paramétrage pour liste d'éléments à configurer (instance) */
+struct _GtkTweakSection
+{
+ GtkListBoxRow parent; /* A laisser en premier */
+
+ GtkImage *icon; /* Eventuelle image */
+ GtkLabel *label; /* Etiquette associée */
+ GtkWidget *next; /* Eventuelle progression */
+
+ char *category; /* Groupe de rassemblement */
+
+ union
+ {
+ GType panel; /* Accès à la page de config. */
+ char *sub; /* Sous-ensemble à presenter */
+ };
+ bool has_sub_section; /* Choix du champ valide */
+
+};
+
+/* Section de paramétrage pour liste d'éléments à configurer (classe) */
+struct _GtkTweakSectionClass
+{
+ GtkListBoxRowClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une nouvelle section de configuration. */
+bool gtk_tweak_section_create(GtkTweakSection *, const tweak_info_t *);
+
+
+
+#endif /* _GTKEXT_TWEAK_INT_H */
diff --git a/src/gtkext/tweak.c b/src/gtkext/tweak.c
new file mode 100644
index 0000000..b03cf17
--- /dev/null
+++ b/src/gtkext/tweak.c
@@ -0,0 +1,319 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak.c - section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tweak.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+
+
+#include "helpers.h"
+#include "tweak-int.h"
+
+
+
+/* Initialise la classe des sections d'éléments paramétrables. */
+static void gtk_tweak_section_class_init(GtkTweakSectionClass *);
+
+/* Initialise une instance de section d'éléments paramétrables. */
+static void gtk_tweak_section_init(GtkTweakSection *);
+
+/* Supprime toutes les références externes. */
+static void gtk_tweak_section_dispose(GtkTweakSection *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_tweak_section_finalize(GtkTweakSection *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkTweakSection, gtk_tweak_section, GTK_TYPE_LIST_BOX_ROW);
+
+
+/******************************************************************************
+* *
+* Paramètres : class = classe GTK à initialiser. *
+* *
+* Description : Initialise la classe des sections d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_class_init(GtkTweakSectionClass *class)
+{
+ GObjectClass *object; /* Plus haut niveau équivalent */
+ GtkWidgetClass *widget; /* Classe de haut niveau */
+
+ object = G_OBJECT_CLASS(class);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_tweak_section_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_tweak_section_finalize;
+
+ widget = GTK_WIDGET_CLASS(class);
+
+ gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gtkext/tweak.ui");
+
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, icon);
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, label);
+ gtk_widget_class_bind_template_child(widget, GtkTweakSection, next);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = composant GTK à initialiser. *
+* *
+* Description : Initialise une instance de section d'éléments paramétrables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_init(GtkTweakSection *section)
+{
+ gtk_widget_init_template(GTK_WIDGET(section));
+
+ section->category = NULL;
+
+ section->sub = NULL;
+ section->has_sub_section = true;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_dispose(GtkTweakSection *section)
+{
+ gtk_widget_dispose_template(GTK_WIDGET(section), GTK_TYPE_TWEAK_SECTION);
+
+ G_OBJECT_CLASS(gtk_tweak_section_parent_class)->dispose(G_OBJECT(section));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_tweak_section_finalize(GtkTweakSection *section)
+{
+ if (section->category != NULL)
+ free(section->category);
+
+ if (section->has_sub_section && section->sub != NULL)
+ free(section->sub);
+
+ G_OBJECT_CLASS(gtk_tweak_section_parent_class)->finalize(G_OBJECT(section));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = informations associées à la section. *
+* *
+* Description : Crée une nouvelle section de configuration. *
+* *
+* Retour : Composant GTK mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkTweakSection *gtk_tweak_section_new(const tweak_info_t *info)
+{
+ GtkTweakSection *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_TWEAK_SECTION, NULL);
+
+ if (!gtk_tweak_section_create(result, info))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à initialiser pleinement. *
+* info = informations associées à la section. *
+* *
+* Description : Met en place une nouvelle section de configuration. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tweak_section_create(GtkTweakSection *section, const tweak_info_t *info)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ gtk_image_set_from_icon_name(section->icon, info->image);
+ gtk_label_set_label(section->label, info->label);
+
+ gtk_widget_set_visible(section->next, info->has_sub_section);
+
+ section->category = strdup(info->category);
+
+ if (info->has_sub_section)
+ {
+ section->sub = strdup(info->sub);
+ section->has_sub_section = true;
+ }
+ else
+ {
+ section->panel = info->panel;
+ section->has_sub_section = false;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit l'étiquette associée à une section de configuration. *
+* *
+* Retour : Désignation humaine de la section. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_tweak_section_get_label(const GtkTweakSection *section)
+{
+ const char *result; /* Texte à retourner */
+
+ result = gtk_label_get_text(section->label);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Indique si la section renvoie vers une sous-section. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool gtk_tweak_section_has_sub_section(const GtkTweakSection *section)
+{
+ bool result; /* Statut à retourner */
+
+ result = section->has_sub_section;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit le type d'un éventuel panneau de configuration lié. *
+* *
+* Retour : Bilan de la consultation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GType gtk_tweak_section_get_panel(const GtkTweakSection *section)
+{
+ GType result; /* Type d'objet à retourner */
+
+ assert(!section->has_sub_section);
+
+ result = section->panel;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : section = section à consulter. *
+* *
+* Description : Fournit la désignation d'une éventuelle sous-section liée. *
+* *
+* Retour : Désignation associée à la sous-section. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+const char *gtk_tweak_section_get_sub_section(const GtkTweakSection *section)
+{
+ const char *result; /* Désignation à renvoyer */
+
+ assert(section->has_sub_section);
+
+ result = section->sub;
+
+ return result;
+
+}
diff --git a/src/gtkext/tweak.h b/src/gtkext/tweak.h
new file mode 100644
index 0000000..8c44844
--- /dev/null
+++ b/src/gtkext/tweak.h
@@ -0,0 +1,90 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tweak.h - prototypes pour pour une section d'éléments à paramétrer
+ *
+ * Copyright (C) 2025 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GTKEXT_TWEAK_H
+#define _GTKEXT_TWEAK_H
+
+
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+
+#include "../glibext/helpers.h"
+
+
+
+/* Définition d'une section de configuration */
+typedef struct _tweak_info_t
+{
+ const char *parent; /* Ensemble d'appartenance */
+
+ const char *category; /* Groupe de rassemblement */
+
+ const char *image; /* Eventuelle image associée */
+ const char *key; /* Désignation de la section */
+ const char *label; /* Désignation humaine */
+
+ union
+ {
+ GType panel; /* Accès à la page de config. */
+ const char *sub; /* Sous-ensemble à presenter */
+ };
+ bool has_sub_section; /* Choix du champ valide */
+
+} tweak_info_t;
+
+
+#define TWEAK_SIMPLE_DEF(p, c, i, k, l, t) \
+ { \
+ .parent = p, \
+ .category = c, \
+ .image = i, \
+ .key = k, \
+ .label = l, \
+ .panel = t, \
+ .has_sub_section = false, \
+ }
+
+#define GTK_TYPE_TWEAK_SECTION (gtk_tweak_section_get_type())
+
+DECLARE_GTYPE(GtkTweakSection, gtk_tweak_section, GTK, TWEAK_SECTION);
+
+
+/* Crée une nouvelle section de configuration. */
+GtkTweakSection *gtk_tweak_section_new(const tweak_info_t *);
+
+/* Fournit l'étiquette associée à une section de configuration. */
+const char *gtk_tweak_section_get_label(const GtkTweakSection *);
+
+/* Indique si la section renvoie vers une sous-section. */
+bool gtk_tweak_section_has_sub_section(const GtkTweakSection *);
+
+/* Fournit le type d'un éventuel panneau de configuration lié. */
+GType gtk_tweak_section_get_panel(const GtkTweakSection *);
+
+/* Fournit la désignation d'une éventuelle sous-section liée. */
+const char *gtk_tweak_section_get_sub_section(const GtkTweakSection *);
+
+
+
+#endif /* _GTKEXT_TWEAK_H */
diff --git a/src/gtkext/tweak.ui b/src/gtkext/tweak.ui
new file mode 100644
index 0000000..576e25e
--- /dev/null
+++ b/src/gtkext/tweak.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <template class="GtkTweakSection" parent="GtkListBoxRow">
+
+ <property name="child">
+
+ <object class="GtkBox">
+ <property name="orientation">horizontal</property>
+ <property name="margin-top">14</property>
+ <property name="margin-bottom">14</property>
+
+ <child>
+ <object class="GtkImage" id="icon">
+ <property name="icon-name">security-high-symbolic</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Security</property>
+ <property name="hexpand">true</property>
+ </object>
+ </child>
+
+ <child>
+ <object class="GtkImage" id="next">
+ <property name="icon-name">go-next-symbolic</property>
+ <property name="margin-start">12</property>
+ <property name="margin-end">12</property>
+ <style>
+ <class name="icon-dropshadow"/>
+ </style>
+ </object>
+ </child>
+
+ </object>
+ </property>
+
+ </template>
+</interface>