diff options
Diffstat (limited to 'src/gtkext')
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>  | 
