From c863d2d9093e7205107b5a6e56bd616c0703d4e4 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Fri, 23 Aug 2024 23:36:25 +0200
Subject: Restore an About dialog box.

---
 src/gui/Makefile.am           |   4 +-
 src/gui/dialogs/Makefile.am   |  51 ++++-----
 src/gui/dialogs/about-int.h   |  69 ++++++++++++
 src/gui/dialogs/about.c       | 180 +++++++++++++++++++-----------
 src/gui/dialogs/about.h       |  12 +-
 src/gui/dialogs/about.ui      | 247 +++++++++++++++++-------------------------
 src/gui/dialogs/gresource.xml |   2 +-
 src/gui/style.css             |   8 ++
 src/gui/window.c              |  43 +++++++-
 src/gui/window.ui             |  28 +++++
 10 files changed, 404 insertions(+), 240 deletions(-)
 create mode 100644 src/gui/dialogs/about-int.h

diff --git a/src/gui/Makefile.am b/src/gui/Makefile.am
index 5ec43d2..42761c4 100644
--- a/src/gui/Makefile.am
+++ b/src/gui/Makefile.am
@@ -18,7 +18,6 @@ libgui_la_SOURCES =						\
 
 libgui_la_LIBADD =						\
 	core/libguicore.la					\
-	dialogs/libguidialogs.la			\
 	menus/libguimenus.la				\
 	panels/libguipanels.la				\
 	tb/libguitb.la
@@ -35,6 +34,7 @@ libgui4_la_SOURCES =						\
 
 libgui4_la_LIBADD =							\
 	core/libguicore4.la						\
+	dialogs/libguidialogs.la				\
 	panels/libguipanels4.la
 
 libgui4_la_CFLAGS = $(LIBGTK4_CFLAGS)
@@ -45,7 +45,7 @@ devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
 dev_HEADERS = $(libgui_la_SOURCES:%c=)
 
 
-SUBDIRS = core panels # dialogs menus panels tb
+SUBDIRS = core dialogs panels # menus panels tb
 
 
 RES_FILES = 								\
diff --git a/src/gui/dialogs/Makefile.am b/src/gui/dialogs/Makefile.am
index 5716f14..5a77b99 100644
--- a/src/gui/dialogs/Makefile.am
+++ b/src/gui/dialogs/Makefile.am
@@ -4,34 +4,35 @@ BUILT_SOURCES = resources.h resources.c
 noinst_LTLIBRARIES  = libguidialogs.la
 
 UI_FILES =								\
-	about.ui							\
-	bookmark.ui							\
-	export_graph.ui						\
-	identity.ui							\
-	loading.ui							\
-	preferences.ui						\
-	prefs_fgraph.ui						\
-	prefs_labels.ui						\
-	snapshots.ui						\
-	storage.ui
+	about.ui
+# bookmark.ui							\
+# export_graph.ui						\
+# identity.ui							\
+# loading.ui							\
+# preferences.ui						\
+# prefs_fgraph.ui						\
+# prefs_labels.ui						\
+# snapshots.ui						\
+# storage.ui
 
 libguidialogs_la_SOURCES =				\
+	about-int.h							\
 	about.h about.c						\
-	bookmark.h bookmark.c				\
-	export_disass.h export_disass.c		\
-	export_graph.h export_graph.c		\
-	goto.h goto.c						\
-	gotox.h gotox.c						\
-	identity.h identity.c				\
-	loading.h loading.c					\
-	preferences.h preferences.c			\
-	prefs_fgraph.h prefs_fgraph.c		\
-	prefs_labels.h prefs_labels.c		\
-	resources.h resources.c				\
-	snapshots.h snapshots.c				\
-	storage.h storage.c
-
-libguidialogs_la_CFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS)
+	resources.h resources.c
+# bookmark.h bookmark.c				\
+# export_disass.h export_disass.c		\
+# export_graph.h export_graph.c		\
+# goto.h goto.c						\
+# gotox.h gotox.c						\
+# identity.h identity.c				\
+# loading.h loading.c					\
+# preferences.h preferences.c			\
+# prefs_fgraph.h prefs_fgraph.c		\
+# prefs_labels.h prefs_labels.c		\
+# snapshots.h snapshots.c				\
+# storage.h storage.c
+
+libguidialogs_la_CFLAGS = $(LIBGTK4_CFLAGS)
 
 
 devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%)
diff --git a/src/gui/dialogs/about-int.h b/src/gui/dialogs/about-int.h
new file mode 100644
index 0000000..382859b
--- /dev/null
+++ b/src/gui/dialogs/about-int.h
@@ -0,0 +1,69 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * about.h - définitions internes pour la boîte de dialogue d'information sur le programme
+ *
+ * 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 _GUI_DIALOGS_ABOUT_INT_H
+#define _GUI_DIALOGS_ABOUT_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "about-int.h"
+
+
+
+/* Boîte "A propos de" dédiée à l'application (instance) */
+struct _GtkAppAboutDialog
+{
+    GtkWindow parent;                       /* A laisser en premier        */
+
+    union
+    {
+        struct
+        {
+            GtkPicture *revision_0;         /* Numéro #0                   */
+            GtkPicture *revision_1;         /* Numéro #1                   */
+            GtkPicture *revision_2;         /* Numéro #2                   */
+            GtkPicture *revision_3;         /* Numéro #3                   */
+            GtkPicture *revision_4;         /* Numéro #4                   */
+            GtkPicture *revision_5;         /* Numéro #5                   */
+        };
+        GtkPicture *revisions[6];           /* Tous les numéros d'un coup  */
+    };
+
+};
+
+/* Boîte "A propos de" dédiée à l'application (classe) */
+struct _GtkAppAboutDialogClass
+{
+    GtkWindowClass parent;                  /* A laisser en premier        */
+
+};
+
+
+/* Met en place la fenêtre d'informations sur le logiciel. */
+bool gtk_app_about_dialog_create(GtkAppAboutDialog *, GtkWindow *);
+
+
+
+#endif  /* _GUI_DIALOGS_ABOUT_INT_H */
diff --git a/src/gui/dialogs/about.c b/src/gui/dialogs/about.c
index 574c7f2..5c938ad 100644
--- a/src/gui/dialogs/about.c
+++ b/src/gui/dialogs/about.c
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * about.h - boîte de dialogue d'information sur le programme
  *
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -33,50 +33,87 @@
 #include <config.h>
 
 
-#include "../../gtkext/easygtk.h"
+#include "about-int.h"
 
 
 
-/* Réagit à l'appui d'une touche sur la fenêtre 'A propos'. */
-static gboolean close_about_window_on_escape(GtkWidget *, GdkEventKey *, gpointer);
+/* Procède à l'initialisation de la boîte "A propos de". */
+static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *);
 
-/* Dessine un fond adapté pour la fenêtre sans toucher au thème. */
-static gboolean draw_black_background(GtkWidget *, cairo_t *, gpointer);
+/* Procède à l'initialisation de la boîte "A propos de". */
+static void gtk_app_about_dialog_init(GtkAppAboutDialog *);
 
+/* Supprime toutes les références externes. */
+static void gtk_app_about_dialog_dispose(GtkAppAboutDialog *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_app_about_dialog_finalize(GtkAppAboutDialog *);
+
+
+
+/* Détermine le type du composant d'affichage générique. */
+G_DEFINE_TYPE(GtkAppAboutDialog, gtk_app_about_dialog, GTK_TYPE_WINDOW);
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : parent = fenêtre parente à surpasser.                        *
-*                outb   = constructeur à détruire après usage. [OUT]          *
+*  Paramètres  : class = classe GTK à initialiser.                            *
 *                                                                             *
-*  Description : Construit la fenêtre d'informations sur le logiciel.         *
+*  Description : Procède à l'initialisation de la boîte "A propos de".        *
 *                                                                             *
-*  Retour      : Adresse de la fenêtre mise en place.                         *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_app_about_dialog_class_init(GtkAppAboutDialogClass *class)
+{
+    GObjectClass *object;                   /* Plus haut niveau équivalent */
+    GtkWidgetClass *widget;                 /* Classe de haut niveau       */
+
+    object = G_OBJECT_CLASS(class);
+
+    object->dispose = (GObjectFinalizeFunc/* ! */)gtk_app_about_dialog_dispose;
+    object->finalize = (GObjectFinalizeFunc)gtk_app_about_dialog_finalize;
+
+    widget = GTK_WIDGET_CLASS(class);
+
+    gtk_widget_class_add_binding_action(widget, GDK_KEY_Escape, 0, "window.close", NULL);
+
+    gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/dialogs/about.ui");
+
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_0);
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_1);
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_2);
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_3);
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_4);
+    gtk_widget_class_bind_template_child(widget, GtkAppAboutDialog, revision_5);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dialog = composant GTK à initialiser.                        *
+*                                                                             *
+*  Description : Procède à l'initialisation de la boîte "A propos de".        *
+*                                                                             *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GtkWidget *create_about_dialog(GtkWindow *parent, GtkBuilder **outb)
+static void gtk_app_about_dialog_init(GtkAppAboutDialog *dialog)
 {
-    GtkWidget *result;                      /* Fenêtre à renvoyer          */
-    GtkBuilder *builder;                    /* Constructeur utilisé        */
     unsigned int revision;                  /* Numéro de révision          */
     unsigned int max;                       /* Nbre. de boucles à effectuer*/
     unsigned int i;                         /* Boucle de parcours          */
     unsigned int level;                     /* Unité la plus importante    */
     char buffer[64];                        /* Nom d'image à forger        */
-    GtkImage *img;                          /* Composant d'affichage       */
-
-    builder = gtk_builder_new_from_resource("/org/chrysalide/gui/dialogs/about.ui");
-    *outb = builder;
-
-    result = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
-
-    gtk_window_set_transient_for(GTK_WINDOW(result), parent);
 
-    /* Numéro de révision */
+    gtk_widget_init_template(GTK_WIDGET(dialog));
 
     revision = REVISION;
     max = log(revision) / log(10);
@@ -85,91 +122,110 @@ GtkWidget *create_about_dialog(GtkWindow *parent, GtkBuilder **outb)
 
     for (i = 0; i <= max; i++)
     {
-        snprintf(buffer, 64, "revision_%u", i);
-
-        img = GTK_IMAGE(gtk_builder_get_object(builder, buffer));
-
         level = pow(10, max - i);
 
         snprintf(buffer, 64, "/org/chrysalide/gui/dialogs/about/revision_%u.png", revision / level);
 
-        gtk_image_set_from_resource(img, buffer);
+        gtk_picture_set_resource(dialog->revisions[i], buffer);
 
         revision %= level;
 
     }
 
-    /* Connexion des signaux */
+    for (; i < 6; i++)
+        gtk_widget_set_visible(GTK_WIDGET(dialog->revisions[i]), FALSE);
 
-    gtk_builder_add_callback_symbols(builder,
-                                     BUILDER_CALLBACK(close_about_window_on_escape),
-                                     BUILDER_CALLBACK(draw_black_background),
-                                     NULL);
+}
 
-    gtk_builder_connect_signals(builder, builder);
 
-    return result;
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : dialog = instance d'objet GLib à traiter.                    *
+*                                                                             *
+*  Description : Supprime toutes les références externes.                     *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_app_about_dialog_dispose(GtkAppAboutDialog *dialog)
+{
+    gtk_widget_dispose_template(GTK_WIDGET(dialog), GTK_TYPE_APP_ABOUT_DIALOG);
+
+    G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->dispose(G_OBJECT(dialog));
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : widget = fenêtre visée par la procédure.                     *
-*                event  = informations liées à l'événement.                   *
-*                dummy  = donnée non utilisée ici.                            *
+*  Paramètres  : dialog = instance d'objet GLib à traiter.                    *
 *                                                                             *
-*  Description : Réagit à l'appui d'une touche sur la fenêtre 'A propos'.     *
+*  Description : Procède à la libération totale de la mémoire.                *
 *                                                                             *
-*  Retour      : TRUE pour interrompre la propagation, FALSE autrement.       *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static gboolean close_about_window_on_escape(GtkWidget *widget, GdkEventKey *event, gpointer dummy)
+static void gtk_app_about_dialog_finalize(GtkAppAboutDialog *dialog)
 {
-    gboolean result;                        /* Ordre à retourner           */
+    G_OBJECT_CLASS(gtk_app_about_dialog_parent_class)->finalize(G_OBJECT(dialog));
 
-    if (event->keyval == GDK_KEY_Escape)
-    {
-        gtk_widget_destroy(widget);
-        result = TRUE;
-    }
-    else result = FALSE;
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : parent = fenêtre parente à surpasser.                        *
+*                                                                             *
+*  Description : Construit la fenêtre d'informations sur le logiciel.         *
+*                                                                             *
+*  Retour      : Adresse de la fenêtre mise en place.                         *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkWindow *gtk_app_about_dialog_new(GtkWindow *parent)
+{
+    GtkWindow *result;                      /* Boite de dialogue à renvoyer*/
+
+    result = g_object_new(GTK_TYPE_APP_ABOUT_DIALOG, NULL);
+
+    if (!gtk_app_about_dialog_create(GTK_APP_ABOUT_DIALOG(result), parent))
+        g_clear_object(&result);
 
     return result;
 
 }
 
 
+
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : widget = fenêtre visée par la procédure.                     *
-*                event  = informations liées à l'événement.                   *
-*                dummy  = donnée non utilisée ici.                            *
+*  Paramètres  : dialog  = boîte de dialogue à initialiser pleinement.        *
+*                content = contenu binaire à exposer de façon brute.          *
 *                                                                             *
-*  Description : Dessine un fond adapté pour la fenêtre sans toucher au thème.*
+*  Description : Met en place la fenêtre d'informations sur le logiciel.      *
 *                                                                             *
-*  Retour      : TRUE pour interrompre la propagation, FALSE autrement.       *
+*  Retour      : Bilan de l'opération.                                        *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static gboolean draw_black_background(GtkWidget *widget, cairo_t *cr, gpointer dummy)
+bool gtk_app_about_dialog_create(GtkAppAboutDialog *dialog, GtkWindow *parent)
 {
-    int width;                              /* Largeur du composant        */
-    int height;                             /* Hauteur du composant        */
+    bool result;                            /* Bilan à retourner           */
 
-    width = gtk_widget_get_allocated_width(widget);
-    height = gtk_widget_get_allocated_height(widget);
+    result = true;
 
-    cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
+    gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
 
-    cairo_rectangle(cr, 0, 0, width, height);
-    cairo_fill(cr);
-
-    return FALSE;
+    return result;
 
 }
diff --git a/src/gui/dialogs/about.h b/src/gui/dialogs/about.h
index f119f67..e569ad3 100644
--- a/src/gui/dialogs/about.h
+++ b/src/gui/dialogs/about.h
@@ -2,7 +2,7 @@
 /* Chrysalide - Outil d'analyse de fichiers binaires
  * about.h - prototypes pour la boîte de dialogue d'information sur le programme
  *
- * Copyright (C) 2015-2020 Cyrille Bagard
+ * Copyright (C) 2015-2024 Cyrille Bagard
  *
  *  This file is part of Chrysalide.
  *
@@ -28,9 +28,17 @@
 #include <gtk/gtk.h>
 
 
+#include "../../glibext/helpers.h"
+
+
+
+#define GTK_TYPE_APP_ABOUT_DIALOG (gtk_app_about_dialog_get_type())
+
+DECLARE_GTYPE(GtkAppAboutDialog, gtk_app_about_dialog, GTK, APP_ABOUT_DIALOG);
+
 
 /* Construit la fenêtre d'informations sur le logiciel. */
-GtkWidget *create_about_dialog(GtkWindow *, GtkBuilder **);
+GtkWindow *gtk_app_about_dialog_new(GtkWindow *);
 
 
 
diff --git a/src/gui/dialogs/about.ui b/src/gui/dialogs/about.ui
index 0170508..892b468 100644
--- a/src/gui/dialogs/about.ui
+++ b/src/gui/dialogs/about.ui
@@ -1,151 +1,106 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.37.0 -->
 <interface>
-  <requires lib="gtk+" version="3.12"/>
-  <object class="GtkWindow" id="window">
-    <property name="width-request">350</property>
-    <property name="height-request">430</property>
-    <property name="can-focus">False</property>
-    <property name="border-width">0</property>
-    <property name="title" translatable="yes">About</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="window-position">center-on-parent</property>
-    <property name="default-width">350</property>
-    <property name="default-height">430</property>
-    <property name="type-hint">dialog</property>
-    <signal name="key-press-event" handler="close_about_window_on_escape" swapped="no"/>
-    <child>
-      <object class="GtkFixed">
-        <property name="visible">True</property>
-        <property name="can-focus">False</property>
-        <signal name="draw" handler="draw_black_background" swapped="no"/>
+
+    <template class="GtkAppAboutDialog" parent="GtkWindow">
+        <property name="title" translatable="yes">About</property>
+        <property name="default-width">350</property>
+        <property name="default-height">430</property>
+        <property name="modal">true</property>
+        <property name="resizable">false</property>
+
+        <style>
+            <class name="black-bg"/>
+        </style>
+
         <child>
-          <object class="GtkLabel">
-            <property name="width-request">350</property>
-            <property name="height-request">20</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="margin-bottom">10</property>
-            <property name="label" translatable="yes">&lt;span fgcolor='white'&gt;Copyright (C) 2008-2020 Cyrille Bagard&lt;/span&gt;</property>
-            <property name="use-markup">True</property>
-          </object>
-          <packing>
-            <property name="y">400</property>
-          </packing>
+            <object class="GtkBox">
+                <property name="orientation">vertical</property>
+                <child>
+                    <object class="GtkPicture" id="logo">
+                        <property name="margin-top">10</property>
+                        <property name="file">resource://org/chrysalide/gui/dialogs/about/chrysalide-full.png</property>
+                    </object>
+                </child>
+
+                <!--
+                    Etage intermédiaire pour ne pas que l'image se voie allouer la largeur entière
+                    de la fenêtre. Sinon des marges sont placées autour du rendu lors que l'image
+                    n'est pas étendue pour couvrir cette largeur entière.
+                -->
+                <child>
+                    <object class="GtkBox">
+                        <property name="orientation">horizontal</property>
+                        <property name="halign">center</property>
+                        <property name="margin-top">14</property>
+                        <child>
+                            <object class="GtkPicture" id="text">
+                                <property name="width-request">253</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/chrysalide_text.png</property>
+                            </object>
+                        </child>
+                    </object>
+                </child>
+
+                <child>
+                    <object class="GtkBox">
+                        <property name="orientation">horizontal</property>
+                        <property name="margin-start">149</property>
+                        <child>
+                            <object class="GtkPicture" id="revision">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_0">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_1">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_2">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_3">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_4">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                        <child>
+                            <object class="GtkPicture" id="revision_5">
+                                <property name="width-request">14</property>
+                                <property name="file">resource:///org/chrysalide/gui/dialogs/about/revision.png</property>
+                            </object>
+                        </child>
+                    </object>
+                </child>
+
+                <child>
+                    <object class="GtkLabel">
+                        <property name="margin-top">22</property>
+                        <property name="margin-bottom">10</property>
+                        <property name="label" translatable="yes">&lt;span fgcolor='white'&gt;Copyright (C) 2008-2024 Cyrille Bagard&lt;/span&gt;</property>
+                        <property name="use-markup">True</property>
+                    </object>
+                </child>
+
+            </object>
         </child>
-        <child>
-          <object class="GtkImage" id="logo">
-            <property name="width-request">330</property>
-            <property name="height-request">300</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="resource">/org/chrysalide/gui/dialogs/about/chrysalide-full.png</property>
-          </object>
-          <packing>
-            <property name="x">10</property>
-            <property name="y">10</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="text">
-            <property name="width-request">253</property>
-            <property name="height-request">42</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="resource">/org/chrysalide/gui/dialogs/about/chrysalide_text.png</property>
-          </object>
-          <packing>
-            <property name="x">48</property>
-            <property name="y">324</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-            <property name="resource">/org/chrysalide/gui/dialogs/about/revision.png</property>
-          </object>
-          <packing>
-            <property name="x">149</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_0">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">163</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_1">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">177</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_2">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">191</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_3">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">205</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_4">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">219</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkImage" id="revision_5">
-            <property name="width-request">14</property>
-            <property name="height-request">18</property>
-            <property name="visible">True</property>
-            <property name="can-focus">False</property>
-          </object>
-          <packing>
-            <property name="x">233</property>
-            <property name="y">360</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
+
+    </template>
 </interface>
diff --git a/src/gui/dialogs/gresource.xml b/src/gui/dialogs/gresource.xml
index 0e12ef2..b9bc7e2 100644
--- a/src/gui/dialogs/gresource.xml
+++ b/src/gui/dialogs/gresource.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <gresources>
-    <gresource prefix="/org/chrysalide/gui/dialogs">
+    <gresource prefix="/re/chrysalide/framework/gui/dialogs">
         <file compressed="true">about.ui</file>
         <file compressed="true">bookmark.ui</file>
         <file compressed="true">export_graph.ui</file>
diff --git a/src/gui/style.css b/src/gui/style.css
index b0853ab..44161f7 100644
--- a/src/gui/style.css
+++ b/src/gui/style.css
@@ -25,6 +25,14 @@ list.boxed-list, list.boxed-list > row:last-child {
 }
 
 
+/* about.css */
+
+.black-bg {
+
+    background-color: black;
+
+}
+
 
 /* welcome.css */
 
diff --git a/src/gui/window.c b/src/gui/window.c
index 432a8a1..1f10a15 100644
--- a/src/gui/window.c
+++ b/src/gui/window.c
@@ -27,7 +27,9 @@
 
 #include "window-int.h"
 #include "core/panels.h"
+#include "dialogs/about.h"
 #include "panels/welcome.h"
+#include "../gtkext/helpers.h"
 
 
 
@@ -43,6 +45,9 @@ static void gtk_framework_window_dispose(GtkFrameworkWindow *);
 /* Procède à la libération totale de la mémoire. */
 static void gtk_framework_window_finalize(GtkFrameworkWindow *);
 
+/* Réagit à une activation du menu "A propos de" de la fenetre. */
+static void gtk_framework_window_activate_about(GSimpleAction *, GVariant *, gpointer);
+
 
 
 /* Indique le type défini pour une fenêtre graphique principale de Chrysalide. */
@@ -73,8 +78,6 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class)
 
     widget = GTK_WIDGET_CLASS(class);
 
-    //g_type_ensure(GTK_TYPE_TILING_GRID);
-
     gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/window.ui");
 
     gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, grid);
@@ -99,6 +102,10 @@ static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class)
 
 static void gtk_framework_window_init(GtkFrameworkWindow *window)
 {
+    static GActionEntry app_entries[] = {
+        { "about", gtk_framework_window_activate_about, NULL, NULL, NULL },
+    };
+
     gtk_widget_init_template(GTK_WIDGET(window));
 
     window->settings = g_settings_new(FRAMEWORK_WINDOW_ID);
@@ -107,6 +114,10 @@ static void gtk_framework_window_init(GtkFrameworkWindow *window)
     g_settings_bind(window->settings, "window-height", G_OBJECT(window), "default-height", G_SETTINGS_BIND_DEFAULT);
     g_settings_bind(window->settings, "window-maximized", G_OBJECT(window), "maximized", G_SETTINGS_BIND_DEFAULT);
 
+    g_action_map_add_action_entries(G_ACTION_MAP(window),
+                                    app_entries, G_N_ELEMENTS(app_entries),
+                                    window);
+
 }
 
 
@@ -240,6 +251,34 @@ bool gtk_framework_window_create(GtkFrameworkWindow *window, GtkApplication *app
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : action  = désignation de l'action concernée par l'appel.     *
+*                unused  = adresse non utilisée ici.                          *
+*                _window = instance de fenêtre principale à manipuler.        *
+*                                                                             *
+*  Description : Réagit à une activation du menu "A propos de" de la fenetre. *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void gtk_framework_window_activate_about(GSimpleAction *action, GVariant *unused, gpointer _window)
+{
+    GtkFrameworkWindow *window;             /* Fenêtre principale associée */
+    GtkWindow *dialog;                      /* Boîte de dialogue à afficher*/
+
+    window = _window;
+
+    dialog = gtk_app_about_dialog_new(GTK_WINDOW(window));
+
+    gtk_window_present(dialog);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : window = instance de fenêtre principale à remplir.           *
 *                panel  = nouveau panneau à afficher.                         *
 *                                                                             *
diff --git a/src/gui/window.ui b/src/gui/window.ui
index d9ca32c..7055695 100644
--- a/src/gui/window.ui
+++ b/src/gui/window.ui
@@ -1,10 +1,36 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
+
+    <menu id="main_menu_model">
+        <section>
+            <item>
+                <attribute name="label" translatable="yes">Preferences</attribute>
+            </item>
+            <item>
+                <attribute name="label" translatable="yes">About</attribute>
+                <attribute name="action">win.about</attribute>
+            </item>
+        </section>
+    </menu>
+
     <template class="GtkFrameworkWindow" parent="GtkApplicationWindow">
         <property name="title" translatable="no">Chrysalide</property>
         <property name="default-width">800</property>
         <property name="default-height">600</property>
         <property name="icon-name">chrysalide-logo</property>
+
+        <child type="titlebar">
+            <object class="GtkHeaderBar">
+                <child type="end">
+                    <object class="GtkMenuButton">
+                        <property name="icon-name">open-menu-symbolic</property>
+                        <property name="menu-model">main_menu_model</property>
+                    </object>
+                </child>
+
+            </object>
+        </child>
+
         <child>
             <object class="GtkBox">
                 <property name="orientation">vertical</property>
@@ -15,5 +41,7 @@
                 </child>
             </object>
         </child>
+
     </template>
+
 </interface>
-- 
cgit v0.11.2-87-g4458