From 45c220eb6c7cb1076788307ace4b6f3df2e5e941 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sat, 11 Aug 2018 10:40:45 +0200
Subject: Created a new widget to handle tiled panels.

---
 src/core/logs.c             |    3 +
 src/gtkext/Makefile.am      |    1 +
 src/gtkext/gtkdockstation.c |   49 +--
 src/gtkext/tiledgrid.c      | 1029 +++++++++++++++++++++++++++++++++++++++++++
 src/gtkext/tiledgrid.h      |   81 ++++
 src/gui/core/core.c         |   44 +-
 src/gui/core/global.c       |   41 ++
 src/gui/core/global.h       |    7 +
 src/gui/core/panels.c       |   27 +-
 src/gui/core/panels.h       |    5 +-
 src/gui/editor.c            |  825 +---------------------------------
 src/gui/menus/view.c        |   20 +-
 src/gui/menus/view.h        |    3 +
 src/gui/panels/bintree.c    |    2 +-
 src/gui/panels/bookmarks.c  |    2 +-
 src/gui/panels/errors.c     |    2 +-
 src/gui/panels/glance.c     |    2 +-
 src/gui/panels/history.c    |    2 +-
 src/gui/panels/log.c        |    2 +-
 src/gui/panels/regedit.c    |    2 +-
 src/gui/panels/strings.c    |    2 +-
 src/gui/panels/symbols.c    |    2 +-
 src/gui/panels/welcome.c    |    4 +-
 src/main.c                  |    6 +-
 24 files changed, 1277 insertions(+), 886 deletions(-)
 create mode 100644 src/gtkext/tiledgrid.c
 create mode 100644 src/gtkext/tiledgrid.h

diff --git a/src/core/logs.c b/src/core/logs.c
index ae69758..417039b 100644
--- a/src/core/logs.c
+++ b/src/core/logs.c
@@ -106,7 +106,10 @@ void log_simple_message(LogMessageType type, const char *msg)
         item = get_panel_item_by_name(PANEL_LOG_ID);
 
         if (item != NULL)
+        {
             g_log_panel_add_message(G_LOG_PANEL(item), type, msg);
+            g_object_unref(G_OBJECT(item));
+        }
 
         else
             print_message_without_gui(type, msg);
diff --git a/src/gtkext/Makefile.am b/src/gtkext/Makefile.am
index 42905fb..00ce40b 100644
--- a/src/gtkext/Makefile.am
+++ b/src/gtkext/Makefile.am
@@ -16,6 +16,7 @@ libgtkext_la_SOURCES =						\
 	gtkstatusstack.h gtkstatusstack.c		\
 	rendering.h rendering.c					\
 	support.h support.c						\
+	tiledgrid.h tiledgrid.c					\
 	tmgt.h tmgt.c
 
 libgtkext_la_LIBADD = 					\
diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c
index 634b007..688fe4b 100644
--- a/src/gtkext/gtkdockstation.c
+++ b/src/gtkext/gtkdockstation.c
@@ -271,28 +271,15 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl
     GtkWidget *label;                       /* Etiquette d'onglet          */
     GtkNotebook *notebook;                  /* Autre version du composant  */
 
-    /* Récupération des éléments utiles */
 
-    widget = gtk_dockable_build_widget(dockable);
 
 
-    if (strcmp(gtk_dockable_get_name(dockable), "History") == 0)
-    {
-        GtkRequisition req;
 
-        gtk_widget_get_preferred_size(widget, &req, NULL);
-        fprintf(stderr, "Histo req :: %d x %d\n", req.width, req.height);
 
-    }
 
-    /*
-    if (!GTK_IS_SCROLLED_WINDOW(widget)
-        && (
-            strcmp(gtk_dockable_get_name(dockable), "History2") != 0
-            )
-        )
-        widget = gtk_button_new_with_label("123");
-    */
+    /* Récupération des éléments utiles */
+
+    widget = gtk_dockable_build_widget(dockable);
 
     //widget = gtk_button_new_with_label("123");
     gtk_widget_show(widget);
@@ -318,7 +305,8 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl
     g_signal_handlers_disconnect_by_func(notebook,
                                          G_CALLBACK(gtk_dock_station_switch_panel), station);
 
-    gtk_notebook_insert_page(notebook, widget, label, -1);
+    gtk_notebook_append_page(notebook, widget, label);
+
     gtk_widget_set_tooltip_text(label, desc);
 
     if (gtk_notebook_get_n_pages(notebook) > 1)
@@ -330,33 +318,6 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl
     if (gtk_notebook_get_n_pages(notebook) > 1)
         gtk_notebook_set_current_page(notebook, -1);
 
-
-    // Renéociation des tailles
-    //gtk_widget_queue_resize(GTK_WIDGET(notebook));
-
-
-    if (false)
-    {
-        GtkRequisition req;
-
-        gtk_widget_get_preferred_size(GTK_WIDGET(notebook), &req, NULL);
-        fprintf(stderr, "=== SUPPORT req :: %d x %d\n", req.width, req.height);
-
-
-        gtk_widget_set_size_request(GTK_WIDGET(notebook), req.width, req.height);
-
-
-
-    }
-
-
-
-
-
-
-
-
-
     //g_signal_emit_by_name(station, "dock-widget", widget);
 
 }
diff --git a/src/gtkext/tiledgrid.c b/src/gtkext/tiledgrid.c
new file mode 100644
index 0000000..31358f7
--- /dev/null
+++ b/src/gtkext/tiledgrid.c
@@ -0,0 +1,1029 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tiledgrid.c - compsoant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2018 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 "gtkdockstation.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 *);
+
+
+
+/* --------------------------- 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;
+
+    }
+
+    /* 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   = 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  : stack = 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)
+{
+    const char *path;                       /* Chemin d'accès              */
+    grid_tile_t *tile;                      /* Tuile d'accueil             */
+
+    path = gtk_panel_item_get_path(panel);
+
+    if (!is_valid_tile_path(path))
+    {
+        log_variadic_message(LMT_ERROR, _("Invalid path '%s' for panel '%s'"),
+                             path, gtk_dockable_get_name(GTK_DOCKABLE(panel)));
+    }
+
+    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_status(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);
+
+            }
+
+        }
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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_status(panel, false);
+
+    if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0)
+    {
+        //delete_panel_node(node);
+
+        /* 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);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  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/tiledgrid.h b/src/gtkext/tiledgrid.h
new file mode 100644
index 0000000..25d3b26
--- /dev/null
+++ b/src/gtkext/tiledgrid.h
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tiledgrid.h - prototypes pour un compsoant d'affichage avec des chemins vers les composants contenus
+ *
+ * Copyright (C) 2018 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_TILEDGRID_H
+#define _GTKEXT_TILEDGRID_H
+
+
+#include <gtk/gtk.h>
+
+
+#include "../glibext/configuration.h"
+#include "../gui/panels/panel.h"
+
+
+
+/* --------------------------- INTERFACE DU COMPOSANT GTK --------------------------- */
+
+
+#define GTK_TYPE_TILED_GRID            gtk_tiled_grid_get_type()
+#define GTK_TILED_GRID(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_TILED_GRID, GtkTiledGrid))
+#define GTK_IS_TILED_GRID(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_TILED_GRID))
+#define GTK_TILED_GRID_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_TILED_GRID, GtkTiledGridClass))
+#define GTK_IS_TILED_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_TILED_GRID))
+#define GTK_TILED_GRID_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_TILED_GRID, GtkTiledGridClass))
+
+
+
+/* Conteneur pour un affichage en tuiles nommées (instance) */
+typedef struct _GtkTiledGrid GtkTiledGrid;
+
+/* Conteneur pour un affichage en tuiles nommées (classe) */
+typedef struct _GtkTiledGridClass GtkTiledGridClass;
+
+
+/* Détermine le type du conteneur d'affichage en tuiles nommées. */
+GType gtk_tiled_grid_get_type(void);
+
+/* Crée une nouvelle instance de conteneur avec tuiles. */
+GtkWidget *gtk_tiled_grid_new(void);
+
+/* Donne le panneau fourni par défaut pour la zone principale. */
+GPanelItem *gtk_tiled_grid_get_default_main_panel(const GtkTiledGrid *);
+
+/* Fournit le panneau par défaut pour la zone principale. */
+void gtk_tiled_grid_set_default_main_panel(GtkTiledGrid *, GPanelItem *);
+
+/* Incorpore un nouveau panneau dans le conteneur en tuiles. */
+void gtk_tiled_grid_add(GtkTiledGrid *, GPanelItem *);
+
+/* Retire un panneau dans le conteneur en tuiles. */
+void gtk_tiled_grid_remove(GtkTiledGrid *, GPanelItem *);
+
+/* Replace les positions des séparateurs de tuiles. */
+void gtk_tiled_grid_restore_positions(const GtkTiledGrid *, GGenConfig *);
+
+/* Sauvegarde les positions des séparateurs de tuiles. */
+void gtk_tiled_grid_save_positions(const GtkTiledGrid *, GGenConfig *);
+
+
+
+#endif  /* _GTKEXT_TILEDGRID_H */
diff --git a/src/gui/core/core.c b/src/gui/core/core.c
index 598a8eb..2cb75b1 100644
--- a/src/gui/core/core.c
+++ b/src/gui/core/core.c
@@ -24,12 +24,15 @@
 #include "core.h"
 
 
+#include "global.h"
 #include "panels.h"
-
-
 #include "theme.h"
+#include "../menus/menubar.h"
+#include "../menus/view.h"
+#include "../panels/welcome.h"
 #include "../../core/params.h"
 #include "../../glibext/linesegment.h"
+#include "../../gtkext/tiledgrid.h"
 
 
 
@@ -48,6 +51,9 @@
 bool load_all_gui_components(void)
 {
     bool result;                            /* Bilan à retourner           */
+    GObject *ref;                           /* Espace de référencements    */
+    GMenuBar *bar;                          /* Gestion des menus           */
+    GtkMenuItem *submenuitem;               /* Sous-élément de menu        */
 
     load_main_panels();
 
@@ -55,6 +61,17 @@ bool load_all_gui_components(void)
 
     result = load_segment_rendering_parameters();
 
+    /**
+     * Charge une liste initiale pour activer les raccourcis clavier.
+     */
+
+    ref = get_global_ref();
+
+    bar = G_MENU_BAR(g_object_get_data(ref, "menubar"));
+    submenuitem = GTK_MENU_ITEM(g_object_get_data(ref, "mnu_view_side_panels"));
+
+    mcb_view_update_side_panels_list(submenuitem, bar);
+
     return result;
 
 }
@@ -75,8 +92,29 @@ bool load_all_gui_components(void)
 bool complete_loading_of_all_gui_components(GGenConfig *config)
 {
     bool result;                            /* Bilan à faire remonter      */
+    GtkTiledGrid *grid;                     /* Composant d'affichage       */
+    GPanelItem *welcome;                    /* Panneau d'accueil           */
+
+    grid = get_tiled_grid();
+
+    welcome = get_panel_item_by_name(PANEL_WELCOME_ID);
+    gtk_tiled_grid_set_default_main_panel(grid, welcome);
+    g_object_unref(G_OBJECT(welcome));
+
+    /**
+     * Le fait d'avoir défini le panneau d'accueil par défaut va l'afficher,
+     * comme il n'y a encore aucun autre panneau. Ce qui va mémoriser son
+     * paramètre d'affichage par défaut au démarrage à vrai.
+     *
+     * Or gtk_panel_item_apply_configuration() s'occupe précisément de
+     * restaurer les affichages de panneaux au démarrage.
+     *
+     * Donc on doit sauter ce panneau d'accueil lors de l'appel suivant.
+     */
+
+    result = _browse_all_item_panels(true, (handle_panel_item_fc)gtk_panel_item_apply_configuration, config);
 
-    result = browse_all_item_panels((handle_panel_item_fc)gtk_panel_item_apply_configuration, config);
+    gtk_tiled_grid_restore_positions(grid, config);
 
     return result;
 
diff --git a/src/gui/core/global.c b/src/gui/core/global.c
index dadece0..bfc2426 100644
--- a/src/gui/core/global.c
+++ b/src/gui/core/global.c
@@ -31,6 +31,9 @@ static GtkWindow *_editor = NULL;
 /* Gestion des raccourcis clavier */
 static GtkAccelGroup *_accgroup = NULL;
 
+/* Composant d'affichage en tuile */
+static GtkTiledGrid *_grid = NULL;
+
 /* Barre de statut principale */
 static GtkStatusStack *_status = NULL;
 
@@ -143,6 +146,44 @@ GtkAccelGroup *get_accel_group(void)
 
 /******************************************************************************
 *                                                                             *
+*  Paramètres  : grid = composant GTK à conserver.                            *
+*                                                                             *
+*  Description : Note l'adresse du composant d'affichage en tuiles.           *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void set_tiled_grid(GtkTiledGrid *grid)
+{
+    _grid = grid;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : -                                                            *
+*                                                                             *
+*  Description : Fournit l'adresse du composant d'affichage en tuiles.        *
+*                                                                             *
+*  Retour      : Composant GTK à manipuler.                                   *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GtkTiledGrid *get_tiled_grid(void)
+{
+    return _grid;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
 *  Paramètres  : status = barre de statut à tenir informée.                   *
 *                                                                             *
 *  Description : Note l'adresse de la barre de statut principale.             *
diff --git a/src/gui/core/global.h b/src/gui/core/global.h
index c80bcb5..86a1ea4 100644
--- a/src/gui/core/global.h
+++ b/src/gui/core/global.h
@@ -28,6 +28,7 @@
 #include "../../analysis/loaded.h"
 #include "../../glibext/gloadedpanel.h"
 #include "../../gtkext/gtkstatusstack.h"
+#include "../../gtkext/tiledgrid.h"
 
 
 
@@ -46,6 +47,12 @@ void set_accel_group(GtkAccelGroup *);
 /* Fournit le groupe de raccourcis clavier globaux. */
 GtkAccelGroup *get_accel_group(void);
 
+/* Note l'adresse du composant d'affichage en tuiles. */
+void set_tiled_grid(GtkTiledGrid *);
+
+/* Fournit l'adresse du composant d'affichage en tuiles. */
+GtkTiledGrid *get_tiled_grid(void);
+
 /* Note l'adresse de la barre de statut principale. */
 void set_global_status(GtkStatusStack *);
 
diff --git a/src/gui/core/panels.c b/src/gui/core/panels.c
index 9d11e58..60ff6f2 100644
--- a/src/gui/core/panels.c
+++ b/src/gui/core/panels.c
@@ -25,6 +25,7 @@
 #include "panels.h"
 
 
+#include "global.h"
 #include "items.h"
 #include "../panels/bintree.h"
 #include "../panels/bookmarks.h"
@@ -115,6 +116,7 @@ void load_main_panels(void)
 void register_panel_item(GPanelItem *item, GGenConfig *config)
 {
     GEditorItem *parent;                    /* Autre version de l'élément  */
+    GtkTiledGrid *grid;                     /* Composant d'affichage       */
 
     parent = G_EDITOR_ITEM(item);
 
@@ -122,11 +124,10 @@ void register_panel_item(GPanelItem *item, GGenConfig *config)
     register_editor_item(parent);
     panels_list_add_tail(item, &_panels_list);
 
-    extern void on_panel_item_dock_request(GPanelItem *item, void *data);
-    extern void on_panel_item_undock_request(GPanelItem *item, void *data);
+    grid = get_tiled_grid();
 
-    g_signal_connect(item, "dock-request", G_CALLBACK(on_panel_item_dock_request), NULL);
-    g_signal_connect(item, "undock-request", G_CALLBACK(on_panel_item_undock_request), NULL);
+    g_signal_connect_swapped(item, "dock-request", G_CALLBACK(gtk_tiled_grid_add), grid);
+    g_signal_connect_swapped(item, "undock-request", G_CALLBACK(gtk_tiled_grid_remove), grid);
 
     gtk_dockable_setup_dnd(GTK_DOCKABLE(item));
 
@@ -137,7 +138,8 @@ void register_panel_item(GPanelItem *item, GGenConfig *config)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : handle = routine à appeler pour chaque panneau.              *
+*  Paramètres  : skip   = saute le panneau d'accueil lors du parcours ?       *
+*                handle = routine à appeler pour chaque panneau.              *
 *                data   = données fournies pour accompagner cet appel.        *
 *                                                                             *
 *  Description : Effectue le parcours de tous les panneaux chargés.           *
@@ -148,21 +150,31 @@ void register_panel_item(GPanelItem *item, GGenConfig *config)
 *                                                                             *
 ******************************************************************************/
 
-bool browse_all_item_panels(handle_panel_item_fc handle, void *data)
+bool _browse_all_item_panels(bool skip, handle_panel_item_fc handle, void *data)
 {
     bool result;                            /* Résultat à renvoyer         */
+    GPanelItem *welcome;                    /* Panneau d'accueil           */
     GPanelItem *iter;                       /* Boucle de parcours          */
 
     result = true;
 
+    if (skip)
+        welcome = get_panel_item_by_name(PANEL_WELCOME_ID);
+
     panels_list_for_each(iter, _panels_list)
     {
+        if (skip && iter == welcome)
+            continue;
+
         result = handle(iter, data);
 
         if (!result) break;
 
     }
 
+    if (skip)
+        g_object_unref(G_OBJECT(welcome));
+
     return result;
 
 }
@@ -208,6 +220,9 @@ GPanelItem *get_panel_item_by_name(const char *name)
 
     browse_all_item_panels((handle_panel_item_fc)look_for_named_panel, &result);
 
+    if (result != NULL)
+        g_object_ref(G_OBJECT(result));
+
     return result;
 
 }
diff --git a/src/gui/core/panels.h b/src/gui/core/panels.h
index 0c55417..477c1e0 100644
--- a/src/gui/core/panels.h
+++ b/src/gui/core/panels.h
@@ -44,7 +44,10 @@ void register_panel_item(GPanelItem *, GGenConfig *);
 typedef bool (* handle_panel_item_fc) (GPanelItem *, void *);
 
 /* Effectue le parcours de tous les panneaux chargés. */
-bool browse_all_item_panels(handle_panel_item_fc, void *);
+bool _browse_all_item_panels(bool, handle_panel_item_fc, void *);
+
+#define browse_all_item_panels(h, d) \
+    _browse_all_item_panels(false, h, d)
 
 /* Recherche un panneau à partir de son nom court. */
 GPanelItem *get_panel_item_by_name(const char *);
diff --git a/src/gui/editor.c b/src/gui/editor.c
index faf98a4..b4e13b0 100644
--- a/src/gui/editor.c
+++ b/src/gui/editor.c
@@ -42,8 +42,6 @@
 #include "core/panels.h"
 #include "core/global.h"
 #include "core/items.h"
-#include "panels/panel.h"
-#include "panels/welcome.h"
 #include "tb/portions.h"
 #include "../common/extstr.h"
 #include "../core/global.h"
@@ -53,6 +51,7 @@
 #include "../gtkext/gtkdisplaypanel.h"
 #include "../gtkext/gtkdockable.h"
 #include "../gtkext/gtkdockstation.h"
+#include "../gtkext/tiledgrid.h"
 #include "../gtkext/support.h"
 
 
@@ -90,11 +89,6 @@ static gboolean on_key_event(GtkWidget *, GdkEventKey *, GObject *);
 
 
 
-
-
-
-
-
 /* ------------------------ INTEGRATION DE LA BARRE D'OUTILS ------------------------ */
 
 
@@ -103,94 +97,11 @@ static GtkWidget *build_editor_toolbar(GObject *);
 
 
 
-
-
-/* -------------------- MECANISMES DE (DE)PLACEMENT DES PANNEAUX -------------------- */
-
-
-/* Elément de la hiérarchie des panneaux */
-typedef struct _panel_node
-{
-    struct _panel_node *parent;             /* Noeud parent                */
-
-    char *path;                             /* Chemin du nom courant       */
-
-    union
-    {
-        GtkWidget *widget;                  /* Accès généraliste           */
-        GtkWidget *station;                 /* Station d'accueil simple    */
-        GtkWidget *paned;                   /* Station d'accueil composée  */
-
-    };
-
-    union
-    {
-        /* Version simple */
-        /* ... */
-
-        /* Version composée */
-        struct
-        {
-            struct _panel_node *first;      /* Premier sous élément        */
-            struct _panel_node *second;     /* Second sous élément         */
-        };
-
-    };
-
-} panel_node;
-
-
-#define IS_SIMPLE_NODE(nd)                              \
-    ({                                                  \
-        bool __result;                                  \
-        __result = GTK_IS_DOCK_STATION(nd->station);    \
-        assert(__result || GTK_IS_PANED(nd->paned));    \
-        __result;                                       \
-    })
-
-
-/* Support de fond pour les composants. */
-static GtkWidget *_support = NULL;
-static panel_node *_nodes = NULL;
-
-
-/* Crée un nouveau noeud pour un panneau particulier. */
-static panel_node *create_simple_panel_node_for_item(GPanelItem *, const char *);
-
-/* Prépare une nouvelle sous-division pour deux panneaux. */
-static void switch_panel_node_into_paned(panel_node *, bool, bool);
-
-/* Met en place un nouveau noeud dans une division. */
-static void attach_panel_node_to_paned(panel_node *, panel_node *, bool);
-
-/* Met à jour en cascade les chemins d'accès aux noeuds. */
-static void update_path_of_paned_nodes(panel_node *, const char *, const char *);
-
-/* Détermine la plus grande longueur commune entre éléments. */
-static size_t compute_path_common_length(const panel_node *, const char *);
-
-/* Place au bon endroit un panneau donné. */
-static panel_node *insert_item_as_panel_node(GPanelItem *, panel_node *, const char *, size_t);
-
-/* Tente de mettre la main sur une station d'accueil. */
-static panel_node *find_node_for_station(panel_node *, GtkWidget *);
-
-/* Tente de mettre la main sur un panneau de division graphique. */
-static panel_node *find_node_for_paned(panel_node *, GtkWidget *);
-
-/* Efface de l'organisation un noeud donné en place. */
-static void delete_panel_node(panel_node *);
-
-
-
 /* ------------------- INTERACTIONS GRAPHIQUES LIEES AUX PANNEAUX ------------------- */
 
 
-/* Réagit à une demande de placement d'un panneau d'affichage. */
-void on_panel_item_dock_request(GPanelItem *, gpointer);
-
-/* Réagit à une demande de suppression d'un panneau d'affichage. */
-void on_panel_item_undock_request(GPanelItem *, gpointer);
+/* Réagit à la mise en place d'une nouvelle station d'accueil. */
+static void on_dock_station_created(GtkTiledGrid *, GtkDockStation *, gpointer);
 
 /* Réagit au changement d'onglet d'un panneau quelconque. */
 static void on_dock_item_switch(GtkDockStation *, GtkWidget *, gpointer);
@@ -204,9 +115,6 @@ static void on_dock_menu_request(GtkDockStation *, GtkWidget *, gpointer);
 /* Réagit à une demande de fermeture du panneau courant. */
 static void on_dock_close_request(GtkDockStation *, GtkWidget *, gpointer);
 
-/* Réagit à une variation dans une séparation de panneaux. */
-static void notify_paned_handle_position_change(GObject *, GParamSpec *, gpointer);
-
 
 
 /* ------------------------- INTEGRATION ET SUIVI DE PROJET ------------------------- */
@@ -288,6 +196,7 @@ GtkWidget *create_editor(void)
     GtkWidget *menuboard;                   /* Barre de menus principale   */
 
     GtkWidget *toolbar;                     /* Barre d'outils              */
+    GtkWidget *grid;                        /* Affichage en tuiles         */
 
     GtkWidget *vbox1;
 
@@ -347,29 +256,26 @@ GtkWidget *create_editor(void)
     menuboard = g_editor_item_get_widget(editem);
     gtk_box_pack_start(GTK_BOX(vbox1), menuboard, FALSE, FALSE, 0);
 
+    g_object_set_data(ref, "menubar", editem);
     g_object_set_data(ref, "menuboard", menuboard);
 
     gtk_widget_hide(menuboard);
 
-
     /* Barre d'outils */
 
     toolbar = build_editor_toolbar(ref);
     gtk_box_pack_start(GTK_BOX(vbox1), toolbar, FALSE, FALSE, 0);
 
-    do
-    {
-        _support = gtk_event_box_new();
-        gtk_widget_show(_support);
-
-        //_support = init_panels2(G_CALLBACK(on_dock_item_switch), ref);
-        gtk_box_pack_start(GTK_BOX(vbox1), _support, TRUE, TRUE, 0);
-
+    /* Coeur de la fenêtre principale */
 
-    } while(0);
+    grid = gtk_tiled_grid_new();
+    gtk_widget_show(grid);
 
+    set_tiled_grid(GTK_TILED_GRID(grid));
 
+    g_signal_connect(grid, "station-created", G_CALLBACK(on_dock_station_created), NULL);
 
+    gtk_box_pack_start(GTK_BOX(vbox1), grid, TRUE, TRUE, 0);
 
     /* Barre de statut générale */
 
@@ -487,6 +393,8 @@ static void on_destroy_editor(GtkWidget *widget, GObject *ref)
 {
     /* Fermeture propre */
 
+    gtk_tiled_grid_save_positions(get_tiled_grid(), get_main_configuration());
+
     /* ... */
 
     on_focus_out(widget, NULL, ref);
@@ -676,694 +584,39 @@ static GtkWidget *build_editor_toolbar(GObject *ref)
     gtk_widget_show(result);
     g_object_set_data(ref, "toolbar", result);
 
-
     item = create_portions_tb_item(ref);
     register_editor_item(item);
 
-
     return result;
 
 }
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /* ---------------------------------------------------------------------------------- */
-/*                      MECANISMES DE (DE)PLACEMENT DES PANNEAUX                      */
+/*                     INTERACTIONS GRAPHIQUES LIEES AUX PANNEAUX                     */
 /* ---------------------------------------------------------------------------------- */
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : item = composant à présenter à l'affichage.                  *
-*                path = partie du chemin représentée ici.                     *
+*  Paramètres  : grid    = composant d'affichage en tuiles concerné.          *
+*                station = nouvelle station créée.                            *
+*                unused  = adresse non utilisée ici.                          *
 *                                                                             *
-*  Description : Crée un nouveau noeud pour un panneau particulier.           *
+*  Description : Réagit à la mise en place d'une nouvelle station d'accueil.  *
 *                                                                             *
-*  Retour      : Structure d'accueil mise en place.                           *
+*  Retour      : -                                                            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const char *path)
+static void on_dock_station_created(GtkTiledGrid *grid, GtkDockStation *station, gpointer unused)
 {
-    panel_node *result;                     /* Structure à retourner       */
-    GtkWidget *station;                     /* Premier support concentré   */
-
-    /* Partie graphique */
-
-    station = gtk_dock_station_new();
     g_signal_connect(station, "switch-widget", G_CALLBACK(on_dock_item_switch), NULL);
     g_signal_connect(station, "menu-requested", G_CALLBACK(on_dock_menu_request), NULL);
     g_signal_connect(station, "close-requested", G_CALLBACK(on_dock_close_request), NULL);
-    gtk_widget_show(station);
-
-    gtk_dock_station_add_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(item));
-
-    /* Partie invisible */
-
-    result = (panel_node *)calloc(1, sizeof(panel_node));
-
-    result->station = station;
-
-    result->path = strdup(path);
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node  = noeud à diviser.                                     *
-*                horiz = indique le type d'orientation désiré.                *
-*                first = indication sur l'emplacement à utiliser.             *
-*                                                                             *
-*  Description : Prépare une nouvelle sous-division pour deux panneaux.       *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void switch_panel_node_into_paned(panel_node *node, bool horiz, bool first)
-{
-    GtkWidget *widget;                      /* Composant à traiter         */
-    panel_node *parent;                     /* Lien de parenté à conserver */
-    panel_node *moved;                      /* Noeud descendu d'un étage   */
-
-    /* Décroche graphiquement le support */
-
-    widget = node->widget;
-
-    g_object_ref(G_OBJECT(widget));
-    gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
-
-    /* Descend l'élément actuel */
-
-    parent = node->parent;
-
-    moved = (panel_node *)calloc(1, sizeof(panel_node));
-
-    memcpy(moved, node, sizeof(panel_node));
-
-    node->path = NULL;
-
-    if (!IS_SIMPLE_NODE(moved))
-    {
-        moved->first->parent = moved;
-        moved->second->parent = moved;
-    }
-
-    /* Création du nouveau niveau intermédiaire */
-
-    if (horiz)
-        node->paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
-    else
-        node->paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
-
-    g_signal_connect(node->paned, "notify::position", G_CALLBACK(notify_paned_handle_position_change), NULL);
-
-    gtk_widget_show(node->paned);
-
-    if (parent == NULL)
-        attach_panel_node_to_paned(parent, node, true);
-    else
-        attach_panel_node_to_paned(parent, node, parent->first == node);
-
-    /* Replace le composant d'origine */
-
-    attach_panel_node_to_paned(node, moved, first);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : parent = noeud d'accueil pour le nouveau noeud.              *
-*                node   = nouveau noeud à intégrer dans l'ensemble.           *
-*                first  = indication sur l'emplacement à utiliser.            *
-*                                                                             *
-*  Description : Met en place un nouveau noeud dans une division.             *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, bool first)
-{
-    node->parent = parent;
-
-    /* On se trouve à la racine... */
-
-    if (parent == NULL)
-    {
-        gtk_container_add(GTK_CONTAINER(_support), node->widget);
-
-        update_path_of_paned_nodes(node, "", "R");
-
-    }
-
-    else
-    {
-        /* Raccordement hiérarchique */
-
-        if (first)
-            parent->first = node;
-        else
-            parent->second = node;
-
-        /* Raccordement graphique */
-
-        assert(!IS_SIMPLE_NODE(parent));
-
-        if (first)
-            gtk_paned_pack1(GTK_PANED(parent->paned), node->widget, TRUE, FALSE);
-        else
-            gtk_paned_pack2(GTK_PANED(parent->paned), node->widget, TRUE, FALSE);
-
-        /* Mise à jour des chemins */
-
-        update_path_of_paned_nodes(node, parent->path, first ? "1" : "2");
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node = noeud dont le chemin est à mettre à jour.             *
-*                root = chemin menant au niveau précédent.                    *
-*                sub  = sous-chemin vers lequel l'orientation penche.         *
-*                                                                             *
-*  Description : Met à jour en cascade les chemins d'accès aux noeuds.        *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void update_path_of_paned_nodes(panel_node *node, const char *root, const char *sub)
-{
-    GtkOrientation orientation;             /* Orientation du support      */
-    char *key;                              /* Clef d'accès à un paramètre */
-    gint position;                          /* Nouvelle position de barre  */
-
-    if (!IS_SIMPLE_NODE(node))
-    {
-        /* Reconstruction locale */
-
-        if (node->path != NULL)
-            free(node->path);
-
-        node->path = strdup(root);
-        node->path = stradd(node->path, sub);
-
-        orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(node->paned));
-
-        if (orientation == GTK_ORIENTATION_HORIZONTAL)
-            node->path = stradd(node->path, "h");
-        else
-            node->path = stradd(node->path, "v");
-
-        /* Rechargement de la position ? */
-
-        asprintf(&key, "gui.panels.positions.%s", node->path);
-
-        if (g_generic_config_get_value(get_main_configuration(), key, &position))
-            gtk_paned_set_position(GTK_PANED(node->paned), position);
-
-        free(key);
-
-        /* Propagation de la mise à jour */
-
-        if (node->first)
-            update_path_of_paned_nodes(node->first, node->path, "1");
-
-        if (node->second != NULL)
-            update_path_of_paned_nodes(node->second, node->path, "2");
-
-    }
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node   = noeud d'où lancer les recherches.                   *
-*                target = identifiant de la position visée.                   *
-*                                                                             *
-*  Description : Détermine la plus grande longueur commune entre éléments.    *
-*                                                                             *
-*  Retour      : Bilan de l'évaluation.                                       *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static size_t compute_path_common_length(const panel_node *node, const char *target)
-{
-    size_t result;                          /* Taille à retourner          */
-    size_t len;                             /* Longueur de comparaison     */
-    size_t common1;                         /* Tron common avec le côté #1 */
-    size_t common2;                         /* Tron common avec le côté #2 */
-
-    if (IS_SIMPLE_NODE(node))
-    {
-        len = MIN(strlen(node->path), strlen(target));
-
-        /**
-         * Il n'y a pas forcément de base commune entre deux branches,
-         * donc on parcourt les chemins depuis leur base respective.
-         */
-        for (result = 0; result < len; result++)
-            if (node->path[result] != target[result])
-                break;
-
-    }
-
-    else
-    {
-        common1 = compute_path_common_length(node->first, target);
-        common2 = compute_path_common_length(node->second, target);
-
-        result = MAX(common1, common2);
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : item     = composant à présenter à l'affichage.              *
-*                node     = point d'insertion courant.                        *
-*                path     = partie du chemin représentée ici.                 *
-*                consumed = profondeur du chemin utilisé.                     *
-*                                                                             *
-*  Description : Place au bon endroit un panneau donné.                       *
-*                                                                             *
-*  Retour      : Noeud final inséré dans la liste.                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static panel_node *insert_item_as_panel_node(GPanelItem *item, panel_node *node, const char *path, size_t consumed)
-{
-    panel_node *result;                     /* Noeud ultime à renvoyer     */
-    char div;                               /* Division demandée           */
-    bool horiz;                             /* Traduction en composant     */
-    bool first;                             /* Point d'insertion           */
-    size_t common1;                         /* Tron common avec le côté #1 */
-    size_t common2;                         /* Tron common avec le côté #2 */
-
-
-    fprintf(stderr, "=== INSERTING '%s' (%zu)... -> '%s'\n", path, consumed,
-            IS_SIMPLE_NODE(node) ? node->path : "-");
-
-
-
-    if (IS_SIMPLE_NODE(node))
-    {
-        /* Le parcours s'arrête ici ! */
-        if (strcmp(node->path, path) == 0)
-        {
-            gtk_dock_station_add_dockable(GTK_DOCK_STATION(node->station), GTK_DOCKABLE(item));
-            result = node;
-        }
-
-        /* On ne peut aller plus loin, on doit diviser... */
-        else
-        {
-            div = toupper(path[consumed]);
-            first = (div == 'W' || div == 'N');
-            horiz = (div == 'W' || div == 'E');
-
-            fprintf(stderr, "---%%<--- first=%d horiz=%d\n", first, horiz);
-
-            fprintf(stderr, "--- cutting %p\n", node->station);
-
-            switch_panel_node_into_paned(node, horiz, !first);
-
-            result = create_simple_panel_node_for_item(item, path);
-
-            attach_panel_node_to_paned(node, result, first);
-
-
-            fprintf(stderr, "1# [%p] widget = %p --- split :: %p // %p\n",
-                    node, node->station, node->first, node->second);
-
-        }
-
-    }
-
-    /* On regarde des autres côtés... */
-
-    else
-    {
-        common1 = compute_path_common_length(node->first, path);
-        common2 = compute_path_common_length(node->second, path);
-
-
-
-        fprintf(stderr, " - L1 :: %zu <-> '%s'\n", common1, node->first->path);
-        fprintf(stderr, " - L2 :: %zu <-> '%s'\n", common2, node->second->path);
-
-
-        /* Si une descente est possible... */
-        if (common1 > 0 || common2 > 0)
-        {
-            if (common1 > common2)
-                result = insert_item_as_panel_node(item, node->first, path, common1);
-
-            else
-                result = insert_item_as_panel_node(item, node->second, path, common2);
-
-        }
-
-        /* Sinon, on doit diviser qqch... */
-        else
-        {
-            div = toupper(path[consumed]);
-            first = (div == 'W' || div == 'N');
-            horiz = (div == 'W' || div == 'E');
-
-            fprintf(stderr, "---%%<--- first=%d horiz=%d\n", first, horiz);
-
-            switch_panel_node_into_paned(node, horiz, !first);
-
-            result = create_simple_panel_node_for_item(item, path);
-
-            attach_panel_node_to_paned(node, result, first);
-
-
-                fprintf(stderr, "2# [%p] split :: %p-%p // %p-%p\n", node,
-                        node->first, node->first->widget,
-                        node->second, node->second->widget);
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node    = point de départ des recherches locales.            *
-*                station = composant graphique à retrouver.                   *
-*                                                                             *
-*  Description : Tente de mettre la main sur une station d'accueil.           *
-*                                                                             *
-*  Retour      : Eventuel noeud trouvé ou NULL.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static panel_node *find_node_for_station(panel_node *node, GtkWidget *station)
-{
-    panel_node *result;                     /* Bilan à remonter            */
-
-    if (IS_SIMPLE_NODE(node))
-        result = (node->station == station ? node : NULL);
-
-    else
-    {
-        result = find_node_for_station(node->first, station);
-
-        if (result == NULL)
-            result = find_node_for_station(node->second, station);
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node  = point de départ des recherches locales.              *
-*                paned = composant graphique à retrouver.                     *
-*                                                                             *
-*  Description : Tente de mettre la main sur un panneau de division graphique.*
-*                                                                             *
-*  Retour      : Eventuel noeud trouvé ou NULL.                               *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static panel_node *find_node_for_paned(panel_node *node, GtkWidget *paned)
-{
-    panel_node *result;                     /* Bilan à remonter            */
-
-    if (IS_SIMPLE_NODE(node))
-        result = NULL;
-
-    else
-    {
-        if (node->paned == paned)
-            result = node;
-
-        else
-        {
-            result = find_node_for_paned(node->first, paned);
-
-            if (result == NULL)
-                result = find_node_for_paned(node->second, paned);
-
-        }
-
-    }
-
-    return result;
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : node = noeud à supprimer de l'arbre des noeuds.              *
-*                                                                             *
-*  Description : Efface de l'organisation un noeud donné en place.            *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void delete_panel_node(panel_node *node)
-{
-    panel_node *parent;                     /* Noeud parent à transformer  */
-    GtkWidget *widget;                      /* Composant à traiter         */
-    panel_node *grandparent;                /* Noeud supérieur au parent   */
-    panel_node *remaining;                  /* Noeud restant               */
-
-    assert(IS_SIMPLE_NODE(node));
-
-    parent = node->parent;
-
-    /* Destruction du noeud */
-
-    widget = node->station;
-    gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
-
-    free(node->path);
-
-    free(node);
-
-    /* Suppression du niveau intermédiaire */
-
-    if (parent != NULL)
-    {
-        remaining = (node == parent->first ? parent->second : parent->first);
-
-        /* Décroche graphiquement le support */
-
-        widget = remaining->widget;
-
-        g_object_ref(G_OBJECT(widget));
-        gtk_container_remove(GTK_CONTAINER(parent->paned), widget);
-
-        /* Supprime le composant graphique intermédiaire */
-
-        gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(parent->paned)), parent->paned);
-
-        /* Réinsère la partie restante */
-
-        grandparent = parent->parent;
-
-        memcpy(parent, remaining, sizeof(panel_node));
-
-        if (!IS_SIMPLE_NODE(parent))
-        {
-            parent->first->parent = parent;
-            parent->second->parent = parent;
-        }
-
-        free(remaining);
-
-        if (grandparent == NULL)
-            attach_panel_node_to_paned(grandparent, parent, true);
-        else
-            attach_panel_node_to_paned(grandparent, parent, grandparent->first == parent);
-
-    }
-
-}
-
-
-
-/* ---------------------------------------------------------------------------------- */
-/*                     INTERACTIONS GRAPHIQUES LIEES AUX PANNEAUX                     */
-/* ---------------------------------------------------------------------------------- */
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel  = composant à placer dans l'affichage.                *
-*                unused = adresse non utilisée ici.                           *
-*                                                                             *
-*  Description : Réagit à une demande de placement d'un panneau d'affichage.  *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void on_panel_item_dock_request(GPanelItem *panel, gpointer unused)
-{
-    const char *path;                       /* Chemin d'accès              */
-    panel_node *node;                       /* Noeud à supprimer           */
-    const char *name;                       /* Nom du dernier panneau      */
-    GPanelItem *welcome;                    /* Panneau d'accueil           */
-
-    path = gtk_panel_item_get_path(panel);
-
-    /* Tout est à faire... */
-    if (_nodes == NULL)
-    {
-        _nodes = create_simple_panel_node_for_item(panel, path);
-        gtk_container_add(GTK_CONTAINER(_support), _nodes->widget);
-    }
-    else
-    {
-        node = insert_item_as_panel_node(panel, _nodes, path, 0);
-
-        if (strncmp(node->path, "N", 1) == 0)
-        {
-            name = g_editor_item_get_name(G_EDITOR_ITEM(panel));
-
-            if (strcmp(name, PANEL_WELCOME_ID) != 0)
-            {
-                welcome = get_panel_item_by_name(PANEL_WELCOME_ID);
-
-                if (!g_welcome_panel_get_user_origin(G_WELCOME_PANEL(welcome)))
-                {
-                    /* Equivalent d'un appel "g_panel_item_undock(welcome)", avec effet immédiat */
-                    /////on_panel_item_undock_request(welcome, NULL);
-                }
-
-            }
-
-        }
-
-    }
-
-    g_panel_item_set_dock_status(panel, true);
-
-}
-
-
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : panel  = composant à retirer de l'affichage.                 *
-*                unused = adresse non utilisée ici.                           *
-*                                                                             *
-*  Description : Réagit à une demande de suppression d'un panneau d'affichage.*
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-void on_panel_item_undock_request(GPanelItem *panel, gpointer unused)
-{
-    GtkWidget *station;                     /* Support courant             */
-    GtkNotebook *notebook;                  /* Version parente de station  */
-    panel_node *node;                       /* Noeud à supprimer           */
-    bool allowed;                           /* Fermture permise ?          */
-    const char *name;                       /* Nom du dernier panneau      */
-    GPanelItem *welcome;                    /* Panneau d'accueil           */
-
-    gtk_dockable_decompose(GTK_DOCKABLE(panel), &station);
-
-    notebook = GTK_NOTEBOOK(station);
-
-    node = find_node_for_station(_nodes, station);
-    assert(node != NULL);
-
-    allowed = true;
-
-    if (strcmp(node->path, "N") == 0 && gtk_notebook_get_n_pages(notebook) == 1)
-    {
-        name = g_editor_item_get_name(G_EDITOR_ITEM(panel));
-
-        if (strcmp(name, PANEL_WELCOME_ID) == 0)
-            allowed = false;
-
-        else
-        {
-            welcome = get_panel_item_by_name(PANEL_WELCOME_ID);
-            g_welcome_panel_set_user_origin(G_WELCOME_PANEL(welcome), false);
-
-            /* Equivalent d'un appel "g_panel_item_dock(welcome)", avec effet immédiat */
-            on_panel_item_dock_request(welcome, NULL);
-
-        }
-
-    }
-
-    if (allowed)
-    {
-        gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(panel));
-
-        if (gtk_notebook_get_n_pages(notebook) == 0)
-            delete_panel_node(node);
-
-        g_panel_item_set_dock_status(panel, false);
-
-    }
 
 }
 
@@ -1558,42 +811,6 @@ static void on_dock_close_request(GtkDockStation *station, GtkWidget *button, gp
 }
 
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : obj    = objet à l'origine de la procédure.                  *
-*                pspec  = spécification de l'attribut qui a varié.            *
-*                unused = adresse non utilisée ici.                           *
-*                                                                             *
-*  Description : Réagit à une variation dans une séparation de panneaux.      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void notify_paned_handle_position_change(GObject *obj, GParamSpec *pspec, gpointer unused)
-{
-    GtkPaned *paned;                        /* Panneau concerné            */
-    panel_node *node;                       /* Noeud hiérarchique associé  */
-    gint position;                          /* Nouvelle position de barre  */
-    char *key;                              /* Clef d'accès à un paramètre */
-
-    paned = GTK_PANED(obj);
-
-    node = find_node_for_paned(_nodes, GTK_WIDGET(paned));
-
-    position = gtk_paned_get_position(paned);
-
-    asprintf(&key, "gui.panels.positions.%s", node->path);
-
-    g_generic_config_create_or_udpdate_param(get_main_configuration(), key, CPT_INTEGER, position);
-
-    free(key);
-
-}
-
-
 
 /* ---------------------------------------------------------------------------------- */
 /*                           INTEGRATION ET SUIVI DE PROJET                           */
@@ -1671,7 +888,7 @@ void on_editor_loaded_content_added(GStudyProject *project, GLoadedContent *cont
     name = g_loaded_content_describe(content, false);
     lname = g_loaded_content_describe(content, true);
 
-    panel = g_panel_item_new(PIP_BINARY_VIEW, name, lname, selected, true, "N");
+    panel = g_panel_item_new(PIP_BINARY_VIEW, name, lname, selected, true, "M");
     register_panel_item(panel, get_main_configuration());
 
     g_signal_connect(selected, "size-allocate", G_CALLBACK(scroll_for_the_first_time), content);
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index 4dca039..bf8976c 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -46,9 +46,6 @@
 /* Met à jour les accès du menu "Affichage -> Basculer...". */
 static void update_switch_access_in_menu_view(void);
 
-/* Réagit avec le menu "Affichage -> Panneaux latéraux". */
-static void mcb_view_update_side_panels_list(GtkMenuItem *, GMenuBar *);
-
 /* Réagit avec le menu "Affichage -> Panneaux latéraux -> ...". */
 static void mcb_view_change_panel_docking(GtkCheckMenuItem *, GPanelItem *);
 
@@ -98,17 +95,12 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
 
     /* Affichage -> Panneaux latéraux */
 
-    submenuitem = qck_create_menu_item(NULL, NULL, _("Side panels"), NULL, NULL);
+    submenuitem = qck_create_menu_item(ref, "mnu_view_side_panels", _("Side panels"), NULL, NULL);
     g_signal_connect(submenuitem, "select", G_CALLBACK(mcb_view_update_side_panels_list), bar);
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
     qck_create_menu(GTK_MENU_ITEM(submenuitem));
 
-    /**
-     * Charge une liste initiale pour activer les raccourcis clavier.
-     */
-    mcb_view_update_side_panels_list(GTK_MENU_ITEM(submenuitem), bar);
-
     /* Séparation */
 
     submenuitem = qck_create_menu_separator();
@@ -117,12 +109,12 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar)
 
     /* Types de panneau de code */
 
-    submenuitem = qck_create_menu_item(ref, "mcb_view_switch_to_next_support", _("Switch to next"),
+    submenuitem = qck_create_menu_item(ref, "mnu_view_switch_to_next_support", _("Switch to next"),
                                        G_CALLBACK(mcb_view_switch_to_next_support), NULL);
     add_accelerator_to_widget(submenuitem, "Tab");
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
-    submenuitem = qck_create_menu_item(ref, "mcb_view_switch_to_prev_support", _("Switch to previous"),
+    submenuitem = qck_create_menu_item(ref, "mnu_view_switch_to_prev_support", _("Switch to previous"),
                                        G_CALLBACK(mcb_view_switch_to_prev_support), NULL);
     add_accelerator_to_widget(submenuitem, "<Shift>Tab");
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
@@ -463,12 +455,12 @@ static void update_switch_access_in_menu_view(void)
 
     access = (panel != NULL && (index + 1) < count);
 
-    item = GTK_WIDGET(g_object_get_data(ref, "mcb_view_switch_to_next_support"));
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_switch_to_next_support"));
     gtk_widget_set_sensitive(item, access);
 
     access = (panel != NULL && index > 0);
 
-    item = GTK_WIDGET(g_object_get_data(ref, "mcb_view_switch_to_prev_support"));
+    item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_switch_to_prev_support"));
     gtk_widget_set_sensitive(item, access);
 
     if (panel != NULL)
@@ -493,7 +485,7 @@ static void update_switch_access_in_menu_view(void)
 *                                                                             *
 ******************************************************************************/
 
-static void mcb_view_update_side_panels_list(GtkMenuItem *menuitem, GMenuBar *bar)
+void mcb_view_update_side_panels_list(GtkMenuItem *menuitem, GMenuBar *bar)
 {
     GtkWidget *menubar;                     /* Support pour éléments       */
 
diff --git a/src/gui/menus/view.h b/src/gui/menus/view.h
index a6491bd..2271d4c 100644
--- a/src/gui/menus/view.h
+++ b/src/gui/menus/view.h
@@ -46,6 +46,9 @@ void rebuild_menu_view_for_view(GtkWidget *, GLoadedPanel *);
 /* Met à jour les accès du menu "Affichage" selon le contenu. */
 void update_access_for_view_in_menu_view(GObject *, GLoadedPanel *);
 
+/* Réagit avec le menu "Affichage -> Panneaux latéraux". */
+void mcb_view_update_side_panels_list(GtkMenuItem *, GMenuBar *);
+
 
 
 #endif  /* _GUI_MENUS_VIEW_H */
diff --git a/src/gui/panels/bintree.c b/src/gui/panels/bintree.c
index e425e92..d45fa0b 100644
--- a/src/gui/panels/bintree.c
+++ b/src/gui/panels/bintree.c
@@ -273,7 +273,7 @@ static void g_bintree_panel_init(GBintreePanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Binary tree");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("eN");
+    pitem->path = strdup("MEN");
 
     /* Compléments propres */
 
diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c
index 3c1e719..b6a5deb 100644
--- a/src/gui/panels/bookmarks.c
+++ b/src/gui/panels/bookmarks.c
@@ -267,7 +267,7 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Bookmarks");
     pitem->dock_at_startup = false;
-    pitem->path = strdup("SE");
+    pitem->path = strdup("Ms");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/errors.c b/src/gui/panels/errors.c
index fa86a84..b405d04 100644
--- a/src/gui/panels/errors.c
+++ b/src/gui/panels/errors.c
@@ -281,7 +281,7 @@ static void g_error_panel_init(GErrorPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Disassembling errors");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("S");
+    pitem->path = strdup("Ms");
 
     /* Compléments propres */
 
diff --git a/src/gui/panels/glance.c b/src/gui/panels/glance.c
index b7ce9da..638adc7 100644
--- a/src/gui/panels/glance.c
+++ b/src/gui/panels/glance.c
@@ -188,7 +188,7 @@ static void g_glance_panel_init(GGlancePanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Glance");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("es");
+    pitem->path = strdup("MEs");
 
     /* Support de dessin */
 
diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c
index 50e72da..179c46f 100644
--- a/src/gui/panels/history.c
+++ b/src/gui/panels/history.c
@@ -178,7 +178,7 @@ static void g_history_panel_init(GHistoryPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Change history");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("eN");
+    pitem->path = strdup("MEN");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/log.c b/src/gui/panels/log.c
index e547a03..3a2e102 100644
--- a/src/gui/panels/log.c
+++ b/src/gui/panels/log.c
@@ -159,7 +159,7 @@ static void g_log_panel_init(GLogPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Misc information");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("S");
+    pitem->path = strdup("Ms");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/regedit.c b/src/gui/panels/regedit.c
index a0761aa..16887e7 100644
--- a/src/gui/panels/regedit.c
+++ b/src/gui/panels/regedit.c
@@ -227,7 +227,7 @@ static void g_regedit_panel_init(GRegeditPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Configuration parameters");
     pitem->dock_at_startup = false;
-    pitem->path = strdup("N");
+    pitem->path = strdup("M");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c
index 0c147d5..f25cf52 100644
--- a/src/gui/panels/strings.c
+++ b/src/gui/panels/strings.c
@@ -303,7 +303,7 @@ static void g_strings_panel_init(GStringsPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Strings");
     pitem->dock_at_startup = false;
-    pitem->path = strdup("S");
+    pitem->path = strdup("Ms");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c
index 8168313..a6cfb32 100644
--- a/src/gui/panels/symbols.c
+++ b/src/gui/panels/symbols.c
@@ -332,7 +332,7 @@ static void g_symbols_panel_init(GSymbolsPanel *panel)
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Binary symbols");
     pitem->dock_at_startup = true;
-    pitem->path = strdup("eN");
+    pitem->path = strdup("MEN");
 
     /* Représentation graphique */
 
diff --git a/src/gui/panels/welcome.c b/src/gui/panels/welcome.c
index fc4b314..30652d8 100644
--- a/src/gui/panels/welcome.c
+++ b/src/gui/panels/welcome.c
@@ -198,8 +198,8 @@ static void g_welcome_panel_init(GWelcomePanel *panel)
 
     pitem->personality = PIP_SINGLETON;
     pitem->lname = _("Welcome");
-    pitem->dock_at_startup = true;
-    pitem->path = strdup("N");
+    pitem->dock_at_startup = false;
+    pitem->path = strdup("M");
 
     panel->uorigin = !pitem->dock_at_startup;
 
diff --git a/src/main.c b/src/main.c
index ee805df..05e2b15 100644
--- a/src/main.c
+++ b/src/main.c
@@ -278,12 +278,12 @@ int main(int argc, char **argv)
 
     if (!batch_mode)
     {
-        status = load_all_gui_components();
-        if (!status) goto failed_to_load_editor;
-
         editor = create_editor();
         if (editor == NULL) goto failed_to_load_editor;
 
+        status = load_all_gui_components();
+        if (!status) goto failed_to_load_editor;
+
         gtk_widget_show_now(editor);
 
     }
-- 
cgit v0.11.2-87-g4458