From d88ad56a86f0e538795d3b075833d3665457c1d8 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Thu, 3 Nov 2016 10:50:40 +0100
Subject: Prepared the capacity to display more than one view per binary.

---
 ChangeLog                   |  10 +
 src/analysis/project.c      | 432 ++++++++++++++++++++++++++++++++------------
 src/analysis/project.h      |  30 ++-
 src/gtkext/gtkdockstation.c |   1 -
 src/gui/menus/view.c        |  36 ++--
 5 files changed, 367 insertions(+), 142 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5660ec0..214664f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+16-11-03  Cyrille Bagard <nocbos@gmail.com>
+
+	* src/analysis/project.c:
+	* src/analysis/project.h:
+	Prepare the capacity to display more than one view per binary.
+
+	* src/gtkext/gtkdockstation.c:
+	* src/gui/menus/view.c:
+	Update code.
+
 16-10-29  Cyrille Bagard <nocbos@gmail.com>
 
 	* src/analysis/disass/area.c:
diff --git a/src/analysis/project.c b/src/analysis/project.c
index bf78a49..658bb22 100644
--- a/src/analysis/project.c
+++ b/src/analysis/project.c
@@ -24,6 +24,7 @@
 #include "project.h"
 
 
+#include <assert.h>
 #include <inttypes.h>
 #include <malloc.h>
 #include <string.h>
@@ -62,10 +63,9 @@ typedef struct _loaded_content
 typedef struct _loaded_binary
 {
     GLoadedBinary *binary;                  /* Binaire en question         */
-    GtkViewPanel *views[BVW_COUNT];         /* Composants pour l'affichage */
-    GtkWidget *scrollwindows[BVW_COUNT];    /* Supports pour l'affichage   */
 
-    GPanelItem *item;                       /* Support d'affichage final   */
+    GPanelItem **items;                     /* Supports d'affichage final  */
+    size_t count;                           /* Nombre de ces supports      */
 
 } loaded_binary;
 
@@ -109,6 +109,12 @@ static void g_study_project_hide(const GStudyProject *);
 
 
 
+/* ----------------------- VUES ET BASCULEMENT ENTRE LES VUES ----------------------- */
+
+
+/* Met en place un ensemble de vues pour un binaire. */
+GPanelItem *_setup_new_panel_item_for_binary(GStudyProject *, GLoadedBinary *, BinaryView, GtkViewPanel **);
+
 
 
 /* ----------------------- AMORCE POUR CHARGEMENT DE CONTENUS ----------------------- */
@@ -562,9 +568,46 @@ GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *project,
 
 void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *project)
 {
-    size_t index;                           /* Indice du nouveau binaire   */
+    g_study_project_attach_binary(project, binary);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = project à effacer de la mémoire.                   *
+*                binary  = fichier binaire à associer au projet actuel.       *
+*                                                                             *
+*  Description : Attache un fichier donné à un projet donné.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *binary)
+{
+    loaded_binary *new;                     /* Nouveau binaire à présenter */
+    GtkViewPanel *view;                     /* Composant d'affichage       */
+    GPanelItem *panel;                      /* Nouveau panneau associé     */
+
+    /* Mise en place */
+
+    new = (loaded_binary *)calloc(1, sizeof(loaded_binary));
+
+    new->binary = binary;
+
+    /* Enregistrement dans le projet */
+
+    g_mutex_lock(&project->bin_mutex);
+
+    project->binaries = (loaded_binary **)realloc(project->binaries,
+                                                  ++project->binaries_count * sizeof(loaded_binary *));
+
+    project->binaries[project->binaries_count - 1] = new;
 
-    index = g_study_project_attach_binary(project, binary);
+    /* Premier affichage */
 
     gboolean scroll_for_the_first_time(GtkWidget *widget, GdkEvent *event, GLoadedBinary *binary)
     {
@@ -592,10 +635,15 @@ void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *pro
 
     }
 
-    g_signal_connect(project->binaries[index]->views[BVW_BLOCK], "size-allocate",
-                     G_CALLBACK(scroll_for_the_first_time), binary);
+    panel = _setup_new_panel_item_for_binary(project, binary, BVW_BLOCK, &view);
 
-    g_panel_item_dock(project->binaries[index]->item);
+    g_mutex_unlock(&project->bin_mutex);
+
+    g_signal_connect(view, "size-allocate", G_CALLBACK(scroll_for_the_first_time), binary);
+
+    g_panel_item_dock(panel);
+
+    update_project_area(project);
 
 }
 
@@ -603,29 +651,181 @@ void g_study_project_add_loaded_binary(GLoadedBinary *binary, GStudyProject *pro
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : project = project à effacer de la mémoire.                   *
-*                binary  = fichier binaire à associer au projet actuel.       *
+*                binary  = fichier binaire à dissocier au projet actuel.      *
 *                                                                             *
-*  Description : Attache un fichier donné à un projet donné.                  *
+*  Description : Détache un fichier donné à un projet donné.                  *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_study_project_detach_binary(GStudyProject *project, GLoadedBinary *binary)
+{
+    //GtkDockPanel *dpanel;                   /* Support de panneaux         */
+    //GDockItem *ditem;                       /* Support d'affichage utilisé */
+    size_t i;                               /* Boucle de parcours          */
+
+    //dpanel = GTK_DOCK_PANEL(g_object_get_data(project->ref, "binpanel"));
+    //ditem = gtk_dock_panel_get_item_from_binary(project, binary); FIXME !!
+
+    //gtk_dock_panel_remove_item(dpanel, ditem);
+
+
+
+    for (i = 0; i < project->binaries_count; i++)
+        if (project->binaries[i]->binary == binary) break;
+
+    if ((i + 1) < project->binaries_count)
+        memmove(&project->binaries[i], &project->binaries[i + 1], (project->binaries_count - i - 1) * sizeof(loaded_binary *));
+
+    project->binaries = (loaded_binary **)realloc(project->binaries,
+                                                   --project->binaries_count * sizeof(loaded_binary *));
+
+    update_project_area(project);
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à afficher.             *
+*                                                                             *
+*  Description : Met en place un projet à l'écran.                            *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+void g_study_project_display(const GStudyProject *project)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    loaded_binary *handled;                 /* Binaire prise en compte     */
+    size_t j;                               /* Boucle de parcours #2       */
+
+    for (i = 0; i < project->binaries_count; i++)
+    {
+        handled = project->binaries[i];
+
+        for (j = 0; j < handled->count; j++)
+            g_panel_item_dock(handled->items[j]);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à cacher.               *
+*                                                                             *
+*  Description : Supprime de l'écran un projet en place.                      *
+*                                                                             *
+*  Retour      : -                                                            *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+static void g_study_project_hide(const GStudyProject *project)
+{
+    size_t i;                               /* Boucle de parcours #1       */
+    loaded_binary *handled;                 /* Binaire prise en compte     */
+    size_t j;                               /* Boucle de parcours #2       */
+
+    for (i = 0; i < project->binaries_count; i++)
+    {
+        handled = project->binaries[i];
+
+        for (j = 0; j < handled->count; j++)
+            g_panel_item_undock(handled->items[j]);
+
+    }
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = projet dont le contenu est à afficher.             *
+*                count = nombre de binaires pris en compte. [OUT]             *
+*                                                                             *
+*  Description : Fournit l'ensemble des binaires associés à un projet.        *
 *                                                                             *
-*  Retour      : Emplacement de l'élément créé.                               *
+*  Retour      : Liste à libérer de la mémoire.                               *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *binary)
+GLoadedBinary **g_study_project_get_binaries(const GStudyProject *project, size_t *count)
 {
-    size_t result;                          /* Indice à retourner          */
-    loaded_binary *loaded;                  /* Structure à renvoyer        */
-    BinaryView i;                           /* Boucle de parcours          */
+    GLoadedBinary **result;                 /* Tableau à retourner         */
+    size_t i;                               /* Boucle de parcours          */
+
+    *count = project->binaries_count;
+    result = (GLoadedBinary **)calloc(*count, sizeof(GLoadedBinary *));
+
+    for (i = 0; i < *count; i++)
+    {
+        result[i] = project->binaries[i]->binary;
+        g_object_ref(G_OBJECT(result[i]));
+    }
+
+    return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/*                         VUES ET BASCULEMENT ENTRE LES VUES                         */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : project = zone d'inscription du nouveau panneau.             *
+*                binary  = fichier binaire dont les vues sont à créer.        *
+*                wanted  = interface de visualisation demandée.               *
+*                panel   = interface de visualisation principale. [OUT]       *
+*                                                                             *
+*  Description : Met en place un ensemble de vues pour un binaire.            *
+*                                                                             *
+*  Retour      : Panneau mis en place et prêt à être inséré.                  *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+GPanelItem *_setup_new_panel_item_for_binary(GStudyProject *project, GLoadedBinary *binary, BinaryView wanted, GtkViewPanel **panel)
+{
+    GPanelItem *result;                     /* Nouveau panneau à renvoyer  */
+    size_t k;                               /* Boucle de parcours #3       */
+    loaded_binary *handled;                 /* Dossier de suivi à compléter*/
+    GtkViewPanel *views[BVW_COUNT];         /* Composants pour l'affichage */
+    BinaryView i;                           /* Boucle de parcours #1       */
     GtkWidget *view;                        /* Affichage du binaire        */
     GtkWidget *scroll;                      /* Surface d'exposition        */
+    GtkWidget *selected;                    /* Interface de prédilection   */
     const char *name;                       /* Titre associé au binaire    */
     const char *lname;                      /* Description du binaire      */
+    BinaryView j;                           /* Boucle de parcours #2       */
+
+    /* Recherche du dossier correspondant */
+
+    for (k = 0; k < project->binaries_count; k++)
+        if (project->binaries[k]->binary == binary)
+            break;
+
+    assert(k < project->binaries_count);
 
-    loaded = (loaded_binary *)calloc(1, sizeof(loaded_binary));
+    handled = project->binaries[k];
 
-    loaded->binary = binary;
+    /* Créations */
 
     for (i = 0; i < BVW_COUNT; i++)
     {
@@ -634,7 +834,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
         switch (i)
         {
             case BVW_BLOCK:
-                view = gtk_block_view_new(/*MRD_BLOCK*/);
+                view = gtk_block_view_new();
                 break;
             case BVW_GRAPH:
                 view = gtk_graph_view_new();
@@ -648,42 +848,58 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
 
         gtk_widget_show(view);
 
-        loaded->views[i] = GTK_VIEW_PANEL(view);
+        views[i] = GTK_VIEW_PANEL(view);
 
-        gtk_view_panel_attach_binary(loaded->views[i], binary, i);
+        gtk_view_panel_attach_binary(views[i], binary, i);
 
         /* Intégration finale dans un support défilant */
 
         scroll = qck_create_scrolled_window(NULL, NULL);
         gtk_container_add(GTK_CONTAINER(scroll), view);
 
-        loaded->scrollwindows[i] = scroll;
+        if (i == wanted)
+        {
+            selected = scroll;
+            *panel = GTK_VIEW_PANEL(view);
+        }
 
     }
 
     /* Support graphique final */
 
-    scroll = loaded->scrollwindows[BVW_BLOCK];
     name = g_loaded_binary_get_name(binary, false);
     lname = g_loaded_binary_get_name(binary, true);
 
-    loaded->item = g_panel_item_new(PIP_BINARY_VIEW, name, lname, scroll, true, "N");
-    register_panel_item(loaded->item, project->ref, get_main_configuration());
+    result = g_panel_item_new(PIP_BINARY_VIEW, name, lname, selected, true, "N");
+    register_panel_item(result, project->ref, get_main_configuration());
 
-    /* Enregistrement dans le projet */
-
-    g_mutex_lock(&project->bin_mutex);
-
-    project->binaries = (loaded_binary **)realloc(project->binaries,
-                                                  ++project->binaries_count * sizeof(loaded_binary *));
+    handled->items = (GPanelItem **)realloc(handled->items, ++handled->count * sizeof(GPanelItem *));
+    handled->items[handled->count - 1] = result;
 
-    result = project->binaries_count - 1;
+    /* Etablissement des liens */
 
-    project->binaries[result] = loaded;
+    for (i = 0; i < BVW_COUNT; i++)
+        for (j = 0; j < BVW_COUNT; j++)
+        {
+            if (j == i)
+                continue;
 
-    g_mutex_unlock(&project->bin_mutex);
+            switch (j)
+            {
+                case BVW_BLOCK:
+                    g_object_set_data(G_OBJECT(views[i]), "block_alt_view", views[j]);
+                    break;
+                case BVW_GRAPH:
+                    g_object_set_data(G_OBJECT(views[i]), "graph_alt_view", views[j]);
+                    break;
+                case BVW_SOURCE:
+                    g_object_set_data(G_OBJECT(views[i]), "source_alt_view", views[j]);
+                    break;
+                default: /* GCC ! */
+                    break;
+            }
 
-    update_project_area(project);
+        }
 
     return result;
 
@@ -692,149 +908,136 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = project à effacer de la mémoire.                   *
-*                binary  = fichier binaire à dissocier au projet actuel.      *
+*  Paramètres  : project = zone d'inscription du nouveau panneau.             *
+*                binary  = fichier binaire dont les vues sont à créer.        *
+*                wanted  = interface de visualisation demandée.               *
+*                panel   = interface de visualisation principale. [OUT]       *
 *                                                                             *
-*  Description : Détache un fichier donné à un projet donné.                  *
+*  Description : Met en place un ensemble de vues pour un binaire.            *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Panneau mis en place et prêt à être inséré.                  *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_study_project_detach_binary(GStudyProject *project, GLoadedBinary *binary)
+GPanelItem *setup_new_panel_item_for_binary(GStudyProject *project, GLoadedBinary *binary, BinaryView wanted, GtkViewPanel **panel)
 {
-    //GtkDockPanel *dpanel;                   /* Support de panneaux         */
-    //GDockItem *ditem;                       /* Support d'affichage utilisé */
-    size_t i;                               /* Boucle de parcours          */
-
-    //dpanel = GTK_DOCK_PANEL(g_object_get_data(project->ref, "binpanel"));
-    //ditem = gtk_dock_panel_get_item_from_binary(project, binary); FIXME !!
-
-    //gtk_dock_panel_remove_item(dpanel, ditem);
-
+    GPanelItem *result;                     /* Nouveau panneau à renvoyer  */
 
+    /**
+     * La liste des binaires pris en charge ne doit pas évoluer en cours
+     * de traitement. On place donc le verrou adapté...
+     */
 
-    for (i = 0; i < project->binaries_count; i++)
-        if (project->binaries[i]->binary == binary) break;
+    g_mutex_lock(&project->bin_mutex);
 
-    if ((i + 1) < project->binaries_count)
-        memmove(&project->binaries[i], &project->binaries[i + 1], (project->binaries_count - i - 1) * sizeof(loaded_binary *));
+    result = _setup_new_panel_item_for_binary(project, binary, wanted, panel);
 
-    project->binaries = (loaded_binary **)realloc(project->binaries,
-                                                   --project->binaries_count * sizeof(loaded_binary *));
+    g_mutex_unlock(&project->bin_mutex);
 
-    update_project_area(project);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = projet à consulter.                                *
-*                binary  = binaire chargé, encadré et concerné.               *
-*                kind    = type d'affichage requis.                           *
-*                view    = afficheur effectif quelconque. [OUT]               *
+*  Paramètres  : panel = panneau affichant un contenu binaire.                *
 *                                                                             *
-*  Description : Fournit un support d'affichage donné pour un binaire chargé. *
+*  Description : Fournit la station d'accueil d'un panneau d'affichage.       *
 *                                                                             *
-*  Retour      : Composant GTK dédié à un affichage particulier.              *
+*  Retour      : Composant GTK fourni sans transfert de propriété.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GtkWidget *g_study_project_get_view_for_binary(const GStudyProject *project, const GLoadedBinary *binary, BinaryView kind, GtkViewPanel **view)
+GtkDockStation *get_dock_station_for_view_panel(GtkViewPanel *panel)
 {
-    GtkWidget *result;                      /* Composant GTK à retourner   */
-    size_t i;                               /* Boucle de parcours          */
+    GtkWidget *result;                      /* Support trouvé à retourner  */
 
-    result = NULL;
-    *view = NULL;
+    /**
+     * La hiérarchie des composants empilés est la suivante :
+     *
+     *  - GtkBlockView / GtkGraphView / GtkSourceView (avec GtkViewport intégré)
+     *  - GtkScrolledWindow
+     *  - GtkDockStation
+     *
+     */
 
-    for (i = 0; i < project->binaries_count; i++)
-        if (project->binaries[i]->binary == binary)
-        {
-            result = project->binaries[i]->scrollwindows[kind];
-            *view = project->binaries[i]->views[kind];
-            break;
-        }
+    result = gtk_widget_get_parent(GTK_WIDGET(panel));  /* ScrolledWindow */
+    result = gtk_widget_get_parent(result);             /* DockStation */
 
-    return result;
+    return GTK_DOCK_STATION(result);
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = projet dont le contenu est à afficher.             *
+*  Paramètres  : panel = panneau affichant un contenu binaire.                *
 *                                                                             *
-*  Description : Met en place un projet à l'écran.                            *
+*  Description : Fournit le support défilant d'un panneau d'affichage.        *
 *                                                                             *
-*  Retour      : -                                                            *
+*  Retour      : Composant GTK fourni sans transfert de propriété.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-void g_study_project_display(const GStudyProject *project)
+GtkWidget *get_scroll_window_for_view_panel(GtkViewPanel *panel)
 {
-    size_t i;                               /* Boucle de parcours          */
+    GtkWidget *result;                      /* Support trouvé à retourner  */
 
-    for (i = 0; i < project->binaries_count; i++)
-        g_panel_item_dock(project->binaries[i]->item);
-
-}
+    /**
+     * La hiérarchie des composants empilés est la suivante :
+     *
+     *  - GtkBlockView / GtkGraphView / GtkSourceView (avec GtkViewport intégré)
+     *  - GtkScrolledWindow
+     *  - GtkDockStation
+     *
+     */
 
+    result = gtk_widget_get_parent(GTK_WIDGET(panel));  /* ScrolledWindow */
 
-/******************************************************************************
-*                                                                             *
-*  Paramètres  : project = projet dont le contenu est à cacher.               *
-*                                                                             *
-*  Description : Supprime de l'écran un projet en place.                      *
-*                                                                             *
-*  Retour      : -                                                            *
-*                                                                             *
-*  Remarques   : -                                                            *
-*                                                                             *
-******************************************************************************/
-
-static void g_study_project_hide(const GStudyProject *project)
-{
-    size_t i;                               /* Boucle de parcours          */
-
-    for (i = 0; i < project->binaries_count; i++)
-        g_panel_item_undock(project->binaries[i]->item);
+    return result;
 
 }
 
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : project = projet dont le contenu est à afficher.             *
-*                count = nombre de binaires pris en compte. [OUT]             *
+*  Paramètres  : panel = panneau affichant un contenu binaire.                *
+*                view  = autre vision recherchée.                             *
 *                                                                             *
-*  Description : Fournit l'ensemble des binaires associés à un projet.        *
+*  Description : Fournit une vision alternative d'un panneau d'affichage.     *
 *                                                                             *
-*  Retour      : Liste à libérer de la mémoire.                               *
+*  Retour      : Composant GTK fourni sans transfert de propriété.            *
 *                                                                             *
 *  Remarques   : -                                                            *
 *                                                                             *
 ******************************************************************************/
 
-GLoadedBinary **g_study_project_get_binaries(const GStudyProject *project, size_t *count)
+GtkViewPanel *get_alt_view_for_view_panel(GtkViewPanel *panel, BinaryView view)
 {
-    GLoadedBinary **result;                 /* Tableau à retourner         */
-    size_t i;                               /* Boucle de parcours          */
+    GtkViewPanel *result;                   /* Panneau visé à renvoyer     */
 
-    *count = project->binaries_count;
-    result = (GLoadedBinary **)calloc(*count, sizeof(GLoadedBinary *));
-
-    for (i = 0; i < *count; i++)
+    switch (view)
     {
-        result[i] = project->binaries[i]->binary;
-        g_object_ref(G_OBJECT(result[i]));
+        case BVW_BLOCK:
+            result = GTK_VIEW_PANEL(g_object_get_data(G_OBJECT(panel), "block_alt_view"));
+            break;
+        case BVW_GRAPH:
+            result = GTK_VIEW_PANEL(g_object_get_data(G_OBJECT(panel), "graph_alt_view"));
+            break;
+        case BVW_SOURCE:
+            result = GTK_VIEW_PANEL(g_object_get_data(G_OBJECT(panel), "source_alt_view"));
+            break;
+        default:
+            assert(false);
+            result = NULL;
+            break;
     }
 
     return result;
@@ -842,6 +1045,7 @@ GLoadedBinary **g_study_project_get_binaries(const GStudyProject *project, size_
 }
 
 
+
 /* ---------------------------------------------------------------------------------- */
 /*                           GESTION GLOBALISEE DES PROJETS                           */
 /* ---------------------------------------------------------------------------------- */
diff --git a/src/analysis/project.h b/src/analysis/project.h
index 5f5b38c..a8fafb0 100644
--- a/src/analysis/project.h
+++ b/src/analysis/project.h
@@ -29,9 +29,17 @@
 
 
 #include "binary.h"
+#include "../gtkext/gtkdockstation.h"
 #include "../gtkext/gtkviewpanel.h"
 
 
+/**
+ * Comme "gui/panels/panel.h" inclut "gui/editem.h", qui inclut lui même
+ * ce fichier pour la mise à jour de la zone de projet, on redéfinit...
+ */
+typedef struct _GPanelItem GPanelItem;
+
+
 
 /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */
 
@@ -87,14 +95,11 @@ GBinContent *g_study_project_find_binary_content_by_hash(GStudyProject *, const
 void g_study_project_add_loaded_binary(GLoadedBinary *, GStudyProject *);
 
 /* Attache un fichier donné à un projet donné. */
-size_t g_study_project_attach_binary(GStudyProject *, GLoadedBinary *);
+void g_study_project_attach_binary(GStudyProject *, GLoadedBinary *);
 
 /* Détache un fichier donné à un projet donné. */
 void g_study_project_detach_binary(GStudyProject *, GLoadedBinary *);
 
-/* Fournit un support d'affichage donné pour un binaire chargé. */
-GtkWidget *g_study_project_get_view_for_binary(const GStudyProject *, const GLoadedBinary *, BinaryView, GtkViewPanel **);
-
 /* Met en place un projet à l'écran. */
 void g_study_project_display(const GStudyProject *);
 
@@ -103,6 +108,23 @@ GLoadedBinary **g_study_project_get_binaries(const GStudyProject *, size_t *);
 
 
 
+/* ----------------------- VUES ET BASCULEMENT ENTRE LES VUES ----------------------- */
+
+
+/* Met en place un ensemble de vues pour un binaire. */
+GPanelItem *setup_new_panel_item_for_binary(GStudyProject *, GLoadedBinary *, BinaryView, GtkViewPanel **);
+
+/* Fournit la station d'accueil d'un panneau d'affichage. */
+GtkDockStation *get_dock_station_for_view_panel(GtkViewPanel *);
+
+/* Fournit le support défilant d'un panneau d'affichage. */
+GtkWidget *get_scroll_window_for_view_panel(GtkViewPanel *);
+
+/* Fournit une vision alternative d'un panneau d'affichage. */
+GtkViewPanel *get_alt_view_for_view_panel(GtkViewPanel *, BinaryView);
+
+
+
 /* ------------------------- GESTION GLOBALISEE DES PROJETS ------------------------- */
 
 
diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c
index cc567ad..619267e 100644
--- a/src/gtkext/gtkdockstation.c
+++ b/src/gtkext/gtkdockstation.c
@@ -393,7 +393,6 @@ void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *wid
     old = gtk_notebook_get_nth_page(notebook, index);
     label = gtk_notebook_get_tab_label(notebook, old);
 
-    g_object_ref(G_OBJECT(old));
     g_object_ref(G_OBJECT(label));
     str = g_object_get_data(G_OBJECT(old), "title");
 
diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c
index 43c1a69..780f8c0 100644
--- a/src/gui/menus/view.c
+++ b/src/gui/menus/view.c
@@ -32,7 +32,6 @@
 #include "../core/panels.h"
 #include "../../analysis/project.h"
 #include "../../gtkext/easygtk.h"
-#include "../../gtkext/gtkdockstation.h"
 
 
 
@@ -99,7 +98,7 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar)
 
     submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_textview", NULL, _("Text view"),
                                              G_CALLBACK(mcb_view_change_support), bar);
-    add_accelerator_to_menu_item(submenuitem, "F2", accgroup);
+    add_accelerator_to_menu_item(submenuitem, "F3", accgroup);
     g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_BLOCK));
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
@@ -107,7 +106,7 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar)
 
     submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_graphview", rgroup, _("Graph view"),
                                              G_CALLBACK(mcb_view_change_support), bar);
-    add_accelerator_to_menu_item(submenuitem, "F3", accgroup);
+    add_accelerator_to_menu_item(submenuitem, "F4", accgroup);
     g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_GRAPH));
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
@@ -115,7 +114,7 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar)
 
     submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_sourceview", rgroup, _("Source code"),
                                              G_CALLBACK(mcb_view_change_support), bar);
-    add_accelerator_to_menu_item(submenuitem, "F4", accgroup);
+    add_accelerator_to_menu_item(submenuitem, "F5", accgroup);
     g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_SOURCE));
     gtk_container_add(GTK_CONTAINER(menubar), submenuitem);
 
@@ -431,10 +430,9 @@ static void mcb_view_change_support(GtkRadioMenuItem *menuitem, GMenuBar *bar)
 {
     GSList *group;                          /* Liste de menus radio        */
     GSList *iter;                           /* Boucle de parcours          */
-    BinaryView view;                        /* Nouvelle vue à présenter    */
+    BinaryView wanted;                      /* Nouvelle vue à présenter    */
     GtkViewPanel *vpanel;                   /* Afficheur effectif de code  */
-    GtkWidget *station;                     /* Base du remplacement        */
-    GLoadedBinary *binary;                  /* Edition courante            */
+    GtkDockStation *station;                /* Base du remplacement        */
     GtkWidget *scroll;                      /* Nouveau support à utiliser  */
 
     /* On ne traite qu'une seule fois ! */
@@ -446,26 +444,18 @@ static void mcb_view_change_support(GtkRadioMenuItem *menuitem, GMenuBar *bar)
     {
         if (!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(iter->data))) continue;
 
-        view = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(iter->data), "kind_of_view"));
-
-        /**
-         * La hiérarchie des composants empilés est la suivante :
-         *
-         *  - GtkBlockView / GtkGraphView / GtkSourceView (avec GtkViewport intégré)
-         *  - GtkScrolledWindow
-         *  - GtkDockStation
-         *
-         */
+        wanted = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(iter->data), "kind_of_view"));
 
         vpanel = g_editor_item_get_current_view(G_EDITOR_ITEM(bar));
-        station = gtk_widget_get_parent(GTK_WIDGET(vpanel));   /* ScrollWindow */
-        station = gtk_widget_get_parent(station);   /* DockStation */
+        station = get_dock_station_for_view_panel(vpanel);
+
+        /* En vue du retrait de la station d'accueil... */
+        g_object_ref(G_OBJECT(vpanel));
 
-        binary = g_editor_item_get_current_binary(G_EDITOR_ITEM(bar));
-        scroll = g_study_project_get_view_for_binary(get_current_project(),
-                                                     binary, view, &vpanel);
+        vpanel = get_alt_view_for_view_panel(vpanel, wanted);
+        scroll = get_scroll_window_for_view_panel(vpanel);
 
-        gtk_dock_panel_change_active_widget(GTK_DOCK_STATION(station), scroll);
+        gtk_dock_panel_change_active_widget(station, scroll);
 
         change_editor_items_current_view(G_EDITOR_ITEM(bar)->ref, vpanel);
 
-- 
cgit v0.11.2-87-g4458