From a809d3517eb928d5d7a03d96a85f8af96daa1047 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 20 Jul 2018 18:43:23 +0200 Subject: Included dynamic items in the view menu. --- src/analysis/binary.c | 46 ++++++- src/analysis/loaded-int.h | 4 + src/analysis/loaded.c | 29 ++++ src/analysis/loaded.h | 3 + src/glibext/gdisplayoptions.c | 30 ++++ src/glibext/gdisplayoptions.h | 3 + src/gtkext/gtkdisplaypanel.c | 60 ++++---- src/gui/editor.c | 4 +- src/gui/menus/menubar.c | 5 +- src/gui/menus/view.c | 312 +++++++++++++++++++++++++++--------------- src/gui/menus/view.h | 7 +- 11 files changed, 351 insertions(+), 152 deletions(-) diff --git a/src/analysis/binary.c b/src/analysis/binary.c index 89370b2..44dfe6c 100644 --- a/src/analysis/binary.c +++ b/src/analysis/binary.c @@ -165,6 +165,9 @@ static const char *g_loaded_binary_describe(const GLoadedBinary *, bool); /* Détermine le nombre de vues disponibles pour un contenu. */ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *); +/* Fournit le nom d'une vue donnée d'un contenu chargé. */ +static const char *g_loaded_binary_get_view_name(const GLoadedBinary *, unsigned int); + /* Met en place la vue demandée pour un contenu binaire. */ static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *, unsigned int); @@ -278,6 +281,7 @@ static void g_loaded_binary_interface_init(GLoadedContentInterface *iface) iface->describe = (describe_loaded_fc)g_loaded_binary_describe; iface->count_views = (count_loaded_views_fc)g_loaded_binary_count_views; + iface->get_view_name = (get_loaded_view_name_fc)g_loaded_binary_get_view_name; iface->build_view = (build_loaded_view_fc)g_loaded_binary_build_view; iface->get_view_index = (get_loaded_view_index_fc)g_loaded_binary_get_view_index; @@ -1641,6 +1645,44 @@ static unsigned int g_loaded_binary_count_views(const GLoadedBinary *binary) * Paramètres : binary = contenu chargé à consulter. * * index = indice de la vue ciblée. * * * +* Description : Fournit le nom d'une vue donnée d'un contenu chargé. * +* * +* Retour : Désignation humainement lisible. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static const char *g_loaded_binary_get_view_name(const GLoadedBinary *binary, unsigned int index) +{ + const char *result; /* Désignation à retourner */ + + switch (index) + { + case BVW_BLOCK: + result = _("Text view"); + break; + + case BVW_GRAPH: + result = _("Graph view"); + break; + + default: + assert(false); + result = NULL; + break; + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : binary = contenu chargé à consulter. * +* index = indice de la vue ciblée. * +* * * Description : Met en place la vue demandée pour un contenu binaire. * * * * Retour : Composant graphique nouveau. * @@ -1654,8 +1696,6 @@ static GtkWidget *g_loaded_binary_build_view(GLoadedBinary *binary, unsigned int GtkWidget *result; /* Support à retourner */ GtkWidget *display; /* Composant d'affichage */ - assert(index < g_loaded_binary_count_views(binary)); - switch (index) { case BVW_BLOCK: @@ -1735,8 +1775,6 @@ static GDisplayOptions *g_loaded_binary_get_display_options(const GLoadedBinary { GDisplayOptions *result; /* Instance à renvoyer */ - assert(index < BVW_COUNT); - if (index < BVW_COUNT) result = binary->options[index]; else diff --git a/src/analysis/loaded-int.h b/src/analysis/loaded-int.h index 044dad7..ed7d84a 100644 --- a/src/analysis/loaded-int.h +++ b/src/analysis/loaded-int.h @@ -51,6 +51,9 @@ typedef const char * (* describe_loaded_fc) (const GLoadedContent *, bool); /* Détermine le nombre de vues disponibles pour un contenu. */ typedef unsigned int (* count_loaded_views_fc) (const GLoadedContent *); +/* Fournit le nom d'une vue donnée d'un contenu chargé. */ +typedef const char * (* get_loaded_view_name_fc) (const GLoadedContent *, unsigned int); + /* Met en place la vue demandée pour un contenu chargé. */ typedef GtkWidget * (* build_loaded_view_fc) (GLoadedContent *, unsigned int); @@ -79,6 +82,7 @@ struct _GLoadedContentIface describe_loaded_fc describe; /* Description de contenu */ count_loaded_views_fc count_views; /* Compteur de vues */ + get_loaded_view_name_fc get_view_name; /* Désignation d'une vue donnée*/ build_loaded_view_fc build_view; /* Mise en place de vues */ get_loaded_view_index_fc get_view_index;/* Récupération d'indice de vue*/ diff --git a/src/analysis/loaded.c b/src/analysis/loaded.c index 28aea43..4f8cfea 100644 --- a/src/analysis/loaded.c +++ b/src/analysis/loaded.c @@ -403,6 +403,35 @@ unsigned int g_loaded_content_count_views(const GLoadedContent *content) * Paramètres : content = contenu chargé à consulter. * * index = indice de la vue ciblée. * * * +* Description : Fournit le nom d'une vue donnée d'un contenu chargé. * +* * +* Retour : Désignation humainement lisible. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_loaded_content_get_view_name(const GLoadedContent *content, unsigned int index) +{ + const char *result; /* Désignation à retourner */ + GLoadedContentIface *iface; /* Interface utilisée */ + + iface = G_LOADED_CONTENT_GET_IFACE(content); + + assert(index <= g_loaded_content_count_views(content)); + + result = iface->get_view_name(content, index); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : content = contenu chargé à consulter. * +* index = indice de la vue ciblée. * +* * * Description : Met en place la vue demandée pour un contenu chargé. * * * * Retour : Composant graphique nouveau. * diff --git a/src/analysis/loaded.h b/src/analysis/loaded.h index 66d448a..71e1ff6 100644 --- a/src/analysis/loaded.h +++ b/src/analysis/loaded.h @@ -87,6 +87,9 @@ const char *g_loaded_content_describe(const GLoadedContent *, bool); /* Détermine le nombre de vues disponibles pour un contenu. */ unsigned int g_loaded_content_count_views(const GLoadedContent *); +/* Fournit le nom d'une vue donnée d'un contenu chargé. */ +const char *g_loaded_content_get_view_name(const GLoadedContent *, unsigned int); + /* Met en place la vue demandée pour un contenu chargé. */ GtkWidget *g_loaded_content_build_view(GLoadedContent *, unsigned int); diff --git a/src/glibext/gdisplayoptions.c b/src/glibext/gdisplayoptions.c index 8641f59..9ab2063 100644 --- a/src/glibext/gdisplayoptions.c +++ b/src/glibext/gdisplayoptions.c @@ -263,6 +263,36 @@ void g_display_options_add(GDisplayOptions *options, const char *name, bool valu * Paramètres : options = options à consulter. * * index = indice de l'option concernée. * * * +* Description : Fournit la désignation d'une option donnée. * +* * +* Retour : Nom humainement lisible. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_display_options_get_name(const GDisplayOptions *options, size_t index) +{ + char *result; /* Désignation à retourner */ + + assert(index < options->count); + + if (index < options->count) + result = options->names[index]; + + else + result = NULL; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : options = options à consulter. * +* index = indice de l'option concernée. * +* * * Description : Fournit la valeur d'une option donnée. * * * * Retour : Valeur attribuée. * diff --git a/src/glibext/gdisplayoptions.h b/src/glibext/gdisplayoptions.h index 5697385..7549897 100644 --- a/src/glibext/gdisplayoptions.h +++ b/src/glibext/gdisplayoptions.h @@ -57,6 +57,9 @@ size_t g_display_options_count(const GDisplayOptions *); /* Ajoute une nouvelle option à l'ensemble. */ void g_display_options_add(GDisplayOptions *, const char *, bool); +/* Fournit la désignation d'une option donnée. */ +const char *g_display_options_get_name(const GDisplayOptions *, size_t); + /* Fournit la valeur d'une option donnée. */ bool g_display_options_get(const GDisplayOptions *, size_t); diff --git a/src/gtkext/gtkdisplaypanel.c b/src/gtkext/gtkdisplaypanel.c index 706e8f7..97a4276 100644 --- a/src/gtkext/gtkdisplaypanel.c +++ b/src/gtkext/gtkdisplaypanel.c @@ -91,14 +91,14 @@ static void gtk_display_panel_update_adjustment(GtkDisplayPanel *, GtkOrientatio /* Réagit à un défilement chez une barre associée au composant.*/ static void gtk_display_panel_adjustment_value_changed(GtkAdjustment *, GtkDisplayPanel *); -/* Réagit à un changement des règles d'affichage. */ -static void on_view_panel_binary_option_change(GLoadedBinary *, BinaryView, BufferLineColumn, GtkDisplayPanel *); - /* ----------------------- INTERFACE DE PANNEAU DE CHARGEMENT ----------------------- */ +/* Réagit à un changement des règles d'affichage. */ +static void on_display_panel_option_change(GDisplayOptions *, size_t, bool, GtkDisplayPanel *); + /* Associe à un panneau d'affichage un binaire chargé. */ static void gtk_display_panel_set_content(GtkDisplayPanel *, GLoadedContent *); @@ -860,34 +860,6 @@ void gtk_display_panel_draw_border(GtkDisplayPanel *panel, cairo_t *cr) /****************************************************************************** * * -* Paramètres : binary = bianire dont les consignes d'affichage ont évolué. * -* view = type d'affichage à considérer. * -* col = colonne dont le statut a changé. * -* panel = composant GTK à consulter. * -* * -* Description : Réagit à un changement des règles d'affichage. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_view_panel_binary_option_change(GLoadedBinary *binary, BinaryView view, BufferLineColumn col, GtkDisplayPanel *panel) -{ - if (panel->view_index == view) - { - gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); - gtk_widget_queue_resize(GTK_WIDGET(panel)); - gtk_widget_queue_draw(GTK_WIDGET(panel)); - - } - -} - - -/****************************************************************************** -* * * Paramètres : panel = composant GTK à consulter. * * * * Description : Indique la position courante du curseur. * @@ -1047,6 +1019,30 @@ void gtk_display_panel_compute_relative_coords(GtkDisplayPanel *panel, gint *x, /****************************************************************************** * * +* Paramètres : options = options à mettre à jour. * +* index = indice de l'option concernée. * +* value = nouvelle valeur à intégrer. * +* panel = composant GTK à consulter. * +* * +* Description : Réagit à un changement des règles d'affichage. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_display_panel_option_change(GDisplayOptions *options, size_t index, bool value, GtkDisplayPanel *panel) +{ + gtk_widget_queue_resize(gtk_widget_get_parent(GTK_WIDGET(panel))); + gtk_widget_queue_resize(GTK_WIDGET(panel)); + gtk_widget_queue_draw(GTK_WIDGET(panel)); + +} + + +/****************************************************************************** +* * * Paramètres : panel = composant GTK à mettre à jour. * * content = binaire associé à intégrer. * * * @@ -1069,7 +1065,7 @@ static void gtk_display_panel_set_content(GtkDisplayPanel *panel, GLoadedContent if (GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach != NULL) /* REMME */ GTK_DISPLAY_PANEL_GET_CLASS(panel)->attach(panel, panel->binary); - g_signal_connect(content, "value-changed", G_CALLBACK(on_view_panel_binary_option_change), panel); + g_signal_connect(panel->options, "value-changed", G_CALLBACK(on_display_panel_option_change), panel); } diff --git a/src/gui/editor.c b/src/gui/editor.c index 5034104..9fffde8 100644 --- a/src/gui/editor.c +++ b/src/gui/editor.c @@ -1391,10 +1391,10 @@ static void on_dock_item_switch(GtkDockStation *station, GtkWidget *widget, gpoi GLoadedPanel *panel; /* Vue du contenu chargé */ GLoadedContent *content; /* Contenu en cours d'édition */ - if (GTK_IS_SCROLLED_WINDOW(widget)) + if (!G_IS_LOADED_PANEL(widget) && GTK_IS_SCROLLED_WINDOW(widget)) widget = gtk_bin_get_child(GTK_BIN(widget)); - if (GTK_IS_VIEWPORT(widget)) + if (!G_IS_LOADED_PANEL(widget) && GTK_IS_VIEWPORT(widget)) widget = gtk_bin_get_child(GTK_BIN(widget)); if (G_IS_LOADED_PANEL(widget)) diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c index bc5a045..863ac54 100644 --- a/src/gui/menus/menubar.c +++ b/src/gui/menus/menubar.c @@ -282,6 +282,8 @@ GEditorItem *g_menu_bar_new(GObject *ref) static void change_menubar_current_content(GMenuBar *bar, GLoadedContent *old, GLoadedContent *new) { + rebuild_menu_view_for_content(bar->view, new); + update_access_for_content_in_menu_binary(new); } @@ -305,7 +307,8 @@ static void change_menubar_current_view(GMenuBar *bar, GLoadedPanel *old, GLoade { update_access_for_view_in_menu_edition(new); - rebuild_menu_view(bar->view, new, bar); + rebuild_menu_view_for_view(bar->view, new); + update_access_for_view_in_menu_view(G_EDITOR_ITEM(bar)->ref, new); } diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c index 31726c7..8c34950 100644 --- a/src/gui/menus/view.c +++ b/src/gui/menus/view.c @@ -26,6 +26,8 @@ #include +#include +#include #include @@ -38,8 +40,6 @@ #include "../core/panels.h" #include "../../analysis/loaded.h" #include "../../gtkext/easygtk.h" -#include "../../gtkext/gtkblockdisplay.h" -#include "../../gtkext/gtkgraphdisplay.h" @@ -90,7 +90,6 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) GtkWidget *result; /* Support à retourner */ GtkWidget *menubar; /* Support pour éléments */ GtkWidget *submenuitem; /* Sous-élément de menu */ - GSList *rgroup; /* Groupe des boutons radio */ result = gtk_menu_item_new_with_mnemonic(_("_View")); gtk_widget_show(result); @@ -108,26 +107,11 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) /* Séparation */ submenuitem = qck_create_menu_separator(); + g_object_set_data(ref, "mnu_view_start_panels", submenuitem); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); /* Types de panneau de code */ - submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_textview", NULL, _("Text view"), - G_CALLBACK(mcb_view_change_support), NULL); - add_accelerator_to_widget(submenuitem, "F3"); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_BLOCK)); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_BLOCK_DISPLAY)); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - - rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem)); - - submenuitem = qck_create_radio_menu_item(ref, "mnu_view_switch_graphview", rgroup, _("Graph view"), - G_CALLBACK(mcb_view_change_support), NULL); - add_accelerator_to_widget(submenuitem, "F4"); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(BVW_GRAPH)); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_display", GSIZE_TO_POINTER(GTK_TYPE_GRAPH_DISPLAY)); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - submenuitem = qck_create_menu_item(ref, "mcb_view_switch_to_next_support", _("Switch to next"), G_CALLBACK(mcb_view_switch_to_next_support), NULL); add_accelerator_to_widget(submenuitem, "Tab"); @@ -141,23 +125,7 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) /* Séparation */ submenuitem = qck_create_menu_separator(); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - - /* Affichage des données */ - - submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_off", _("Physical offset"), - G_CALLBACK(mcb_view_display_column), NULL); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_PHYSICAL)); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - - submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_addr", _("Virtual address"), - G_CALLBACK(mcb_view_display_column), NULL); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_VIRTUAL)); - gtk_container_add(GTK_CONTAINER(menubar), submenuitem); - - submenuitem = qck_create_check_menu_item(ref, "mnu_view_display_code", _("Binary code"), - G_CALLBACK(mcb_view_display_column), NULL); - g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(BLC_BINARY)); + g_object_set_data(ref, "mnu_view_start_options", submenuitem); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); /* Séparation */ @@ -180,10 +148,9 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) /****************************************************************************** * * * Paramètres : widget = menu principal à actualiser. * -* panel = nouveau panneau d'affichage actif. * -* bar = barre de menu parente. * +* new = nouveau contenu chargé à analyser. * * * -* Description : Lance une actualisation du fait d'un changement de vue. * +* Description : Réagit à un changement d'affichage principal de contenu. * * * * Retour : - * * * @@ -191,105 +158,246 @@ GtkWidget *build_menu_view(GObject *ref, GMenuBar *bar) * * ******************************************************************************/ -void rebuild_menu_view(GtkWidget *widget, GLoadedPanel *panel, GMenuBar *bar) +void rebuild_menu_view_for_content(GtkWidget *widget, GLoadedContent *new) { - GObject *ref; /* Espace de référencements */ - GtkRadioMenuItem *item; /* Elément de menu arbitraire */ - GSList *radios; /* Liste des menus d'affichage */ - GSList *found; /* Elément de menu à activer */ - GLoadedContent *content; /* Contenu global représenté */ - unsigned int view_index; /* Indice de représentation */ - GDisplayOptions *options; /* Règles d'affichage courantes*/ + GObject *ref; /* Espace de références */ + GtkWidget *menubar; /* Support pour éléments */ + unsigned int i; /* Boucle de parcours */ + char *key; /* Clef pour accès ultérieurs */ GtkWidget *submenuitem; /* Sous-élément de menu */ - bool status; /* Consigne d'affichage */ - - ref = g_editor_item_get_global_ref(G_EDITOR_ITEM(bar)); + void *marker; /* Menu de référence */ + GList *list; /* Liste des éléments en place */ + gint position; /* Point d'insertion */ + GList *iter; /* Boucle de parcours */ + unsigned int count; /* Nombre d'itérations à mener */ + GSList *rgroup; /* Groupe des boutons radio */ - /* Types de panneau de code */ + ref = get_global_ref(); - item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, "mnu_view_switch_graphview")); + /* Retrait d'éventuels anciens menus */ - radios = gtk_radio_menu_item_get_group(item); + menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); - void disconnect_display_radio(GtkWidget *wgt, gpointer unused) + for (i = 0; ; i++) { - g_signal_handlers_disconnect_by_func(wgt, G_CALLBACK(mcb_view_change_support), NULL); + asprintf(&key, "mnu_view_panel_%u", i); - } + submenuitem = g_object_get_data(ref, key); - g_slist_foreach(radios, (GFunc)disconnect_display_radio, NULL); + free(key); - gint find_suitable_display_radio(GObject *rdo, GObject *pnl) + if (submenuitem == NULL) + break; + else + gtk_container_remove(GTK_CONTAINER(menubar), GTK_WIDGET(submenuitem)); + + } + + if (new != NULL) { - GType rdo_type; /* Type d'affichage supporté */ - GType pnl_type; /* Type du panneau affiché */ + /* Insertion des différentes vues */ + + marker = g_object_get_data(ref, "mnu_view_start_panels"); + + list = gtk_container_get_children(GTK_CONTAINER(menubar)); - rdo_type = GPOINTER_TO_SIZE(g_object_get_data(rdo, "kind_of_display")); + position = 0; - pnl_type = G_OBJECT_TYPE(pnl); + for (iter = list; iter != NULL; iter = g_list_next(iter)) + { + position++; + + if (marker == iter->data) + break; + + } + + g_list_free(list); + + count = g_loaded_content_count_views(new); + + rgroup = NULL; + + for (i = 0; i < count; i++) + { + asprintf(&key, "mnu_view_panel_%u", i); + + submenuitem = qck_create_radio_menu_item(ref, key, rgroup, + g_loaded_content_get_view_name(new, i), + G_CALLBACK(mcb_view_change_support), NULL); + g_object_set_data(G_OBJECT(submenuitem), "kind_of_view", GUINT_TO_POINTER(i)); + + free(key); + + asprintf(&key, "F%u", 3 + i); + + add_accelerator_to_widget(submenuitem, key); + + free(key); + + if (rgroup == NULL) + rgroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(submenuitem)); - return (rdo_type == pnl_type ? 0 : -1); + gtk_menu_shell_insert(GTK_MENU_SHELL(menubar), submenuitem, position + i); + + } } - found = g_slist_find_custom(radios, G_OBJECT(panel), (GCompareFunc)find_suitable_display_radio); +} + + +/****************************************************************************** +* * +* Paramètres : widget = menu principal à actualiser. * +* new = nouvelle vue du contenu chargé analysé. * +* * +* Description : Lance une actualisation du fait d'un changement de support. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void rebuild_menu_view_for_view(GtkWidget *widget, GLoadedPanel *new) +{ + GObject *ref; /* Espace de références */ + GLoadedContent *content; /* Contenu en cours d'analyse */ + unsigned int index; /* Indice de la vue */ + + GtkWidget *menubar; /* Support pour éléments */ + void *marker; /* Menu de référence */ + size_t i; /* Boucle de parcours */ + char *key; /* Clef pour accès ultérieurs */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + + + + GtkRadioMenuItem *item; /* Elément de menu arbitraire */ + GSList *radios; /* Liste des menus d'affichage */ + + GList *list; /* Liste des éléments en place */ + gint position; /* Point d'insertion */ + GList *iter; /* Boucle de parcours */ + + GDisplayOptions *options; /* Paramètres de rendus */ + size_t count; /* Nombre d'itérations à mener */ + bool status; /* Consigne d'affichage */ + + ref = get_global_ref(); + + content = get_current_content(); + assert((content == NULL && new == NULL) || (content != NULL && new != NULL)); - assert(found != NULL); + /* Retrait d'éventuels anciens menus */ - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(found->data), TRUE); + menubar = gtk_menu_item_get_submenu(GTK_MENU_ITEM(widget)); - void reconnect_display_radio(GtkWidget *wgt, gpointer unused) + marker = g_object_get_data(ref, "mnu_view_start_options"); + + for (i = 0; ; i++) { - g_signal_connect(wgt, "toggled", G_CALLBACK(mcb_view_change_support), NULL); + asprintf(&key, "mnu_view_display_option_%zu", i); + + submenuitem = g_object_get_data(ref, key); + + free(key); + + if (submenuitem == NULL) + break; + else + gtk_container_remove(GTK_CONTAINER(menubar), GTK_WIDGET(submenuitem)); } - g_slist_foreach(radios, (GFunc)reconnect_display_radio, NULL); + if (content != NULL) + { + index = g_loaded_content_get_view_index(content, GTK_WIDGET(new)); - /* Séparation */ + /* Mise à jour du choix de la vue */ - content = g_loaded_panel_get_content(panel); + item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, "mnu_view_panel_0")); - view_index = g_loaded_content_get_view_index(content, GTK_WIDGET(panel)); + radios = gtk_radio_menu_item_get_group(item); - options = g_loaded_content_get_display_options(content, view_index); + void disconnect_display_radio(GtkWidget *wgt, gpointer unused) + { + g_signal_handlers_disconnect_by_func(wgt, G_CALLBACK(mcb_view_change_support), NULL); + } - g_object_unref(G_OBJECT(content)); + g_slist_foreach(radios, (GFunc)disconnect_display_radio, NULL); + + asprintf(&key, "mnu_view_panel_%u", index); + + item = GTK_RADIO_MENU_ITEM(g_object_get_data(ref, key)); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), TRUE); + + free(key); - /* Positions physiques */ + void reconnect_display_radio(GtkWidget *wgt, gpointer unused) + { + g_signal_connect(wgt, "toggled", G_CALLBACK(mcb_view_change_support), NULL); + } + + g_slist_foreach(radios, (GFunc)reconnect_display_radio, NULL); + + /* Insertion des options de rendu */ - submenuitem = g_object_get_data(ref, "mnu_view_display_off"); + list = gtk_container_get_children(GTK_CONTAINER(menubar)); - g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL); + position = 0; - status = g_display_options_get(options, BLC_PHYSICAL); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status); + for (iter = list; iter != NULL; iter = g_list_next(iter)) + { + position++; - g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL); + if (marker == iter->data) + break; - /* Adresses virtuelles */ + } - submenuitem = g_object_get_data(ref, "mnu_view_display_addr"); + g_list_free(list); - g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL); + options = g_loaded_content_get_display_options(content, index); - status = g_display_options_get(options, BLC_VIRTUAL); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status); + count = g_display_options_count(options); - g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL); + for (i = 0; i < count; i++) + { + asprintf(&key, "mnu_view_display_option_%zu", i); - /* Code binaire */ + submenuitem = qck_create_check_menu_item(ref, key, + g_display_options_get_name(options, i), + G_CALLBACK(mcb_view_display_column), NULL); + g_object_set_data(G_OBJECT(submenuitem), "kind_of_opt", GUINT_TO_POINTER(i)); - submenuitem = g_object_get_data(ref, "mnu_view_display_code"); + gtk_menu_shell_insert(GTK_MENU_SHELL(menubar), submenuitem, position + i); - g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_display_column), NULL); + free(key); - status = g_display_options_get(options, BLC_BINARY); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status); + /** + * Un signal va être émis pour le menu, mais il n'ira pas très loin : + * l'ensemble des options ne notifie un changement que si changement il y a ! + */ - g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_display_column), NULL); + status = g_display_options_get(options, i); + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), status); - g_object_unref(G_OBJECT(options)); + } + + g_object_unref(G_OBJECT(options)); + + g_object_unref(G_OBJECT(content)); + + } + + else + count = 0; + + /* Utilité de la séparation ? */ + + gtk_widget_set_visible(GTK_WIDGET(marker), count > 0); } @@ -309,28 +417,10 @@ void rebuild_menu_view(GtkWidget *widget, GLoadedPanel *panel, GMenuBar *bar) void update_access_for_view_in_menu_view(GObject *ref, GLoadedPanel *panel) { - gboolean access; /* Accès à déterminer */ - GtkWidget *item; /* Elément de menu à traiter */ - - /* Préliminaire */ - - access = (panel != NULL); - /* Bascules */ update_switch_access_in_menu_view(); - /* Affichage des données */ - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_off")); - gtk_widget_set_sensitive(item, access); - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_addr")); - gtk_widget_set_sensitive(item, access); - - item = GTK_WIDGET(g_object_get_data(ref, "mnu_view_display_code")); - gtk_widget_set_sensitive(item, access); - } diff --git a/src/gui/menus/view.h b/src/gui/menus/view.h index fadf881..a6491bd 100644 --- a/src/gui/menus/view.h +++ b/src/gui/menus/view.h @@ -37,8 +37,11 @@ /* Construit le menu "Affichage". */ GtkWidget *build_menu_view(GObject *, GMenuBar *); -/* Lance une actualisation du fait d'un changement de vue. */ -void rebuild_menu_view(GtkWidget *, GLoadedPanel *, GMenuBar *); +/* Réagit à un changement d'affichage principal de contenu. */ +void rebuild_menu_view_for_content(GtkWidget *, GLoadedContent *); + +/* Lance une actualisation du fait d'un changement de support. */ +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 *); -- cgit v0.11.2-87-g4458