From 235b34006d734d55333a182ffd8bbe7fbf8f54bc Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 8 Mar 2016 22:44:52 +0100 Subject: Loaded a dynamic list of dockable panels in the View menu. --- ChangeLog | 51 ++ plugins/pychrysa/gui/panels/panel.c | 43 +- plugins/python/welcome/panel.py | 2 +- src/analysis/project.c | 2 +- src/gtkext/gtkdockable.c | 35 +- src/gtkext/gtkdockable.h | 5 +- src/gtkext/gtkdockstation.c | 183 +++---- src/gtkext/gtkdockstation.h | 9 +- src/gtkext/gtkviewpanel.c | 4 +- src/gui/editem.c | 21 +- src/gui/editem.h | 3 + src/gui/menus/menubar.c | 2 + src/gui/menus/project.c | 2 +- src/gui/menus/view.c | 168 ++++++- src/gui/panels/bookmarks.c | 5 + src/gui/panels/glance.c | 10 +- src/gui/panels/history.c | 7 +- src/gui/panels/log.c | 22 +- src/gui/panels/panel-int.h | 38 +- src/gui/panels/panel.c | 929 +++++++++++++++++++++--------------- src/gui/panels/panel.h | 46 +- src/gui/panels/regedit.c | 7 +- src/gui/panels/strings.c | 11 + src/gui/panels/symbols.c | 13 +- 24 files changed, 1111 insertions(+), 507 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09dc5d8..ca1655f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +16-03-08 Cyrille Bagard + + * plugins/pychrysa/gui/panels/panel.c: + Register new constants for panels. + + * plugins/python/welcome/panel.py: + * src/analysis/project.c: + Update code. + + * src/gtkext/gtkdockable.c: + * src/gtkext/gtkdockable.h: + Provide references of dockable items for UI. + + * src/gtkext/gtkdockstation.c: + * src/gtkext/gtkdockstation.h: + Inherit from GtkNotebook directly for dock stations. Dock and undock + widgets. + + * src/gtkext/gtkviewpanel.c: + Disable some code. + + * src/gui/editem.c: + * src/gui/editem.h: + Provide editor item name for external usage. + + * src/gui/menus/menubar.c: + Store the global accelerator group. + + * src/gui/menus/project.c: + Typo. + + * src/gui/menus/view.c: + Load a dynamic list of dockable panels in the View menu. Dock and undock + panels on demand. + + * src/gui/panels/bookmarks.c: + * src/gui/panels/glance.c: + * src/gui/panels/history.c: + * src/gui/panels/log.c: + Update code. + + * src/gui/panels/panel-int.h: + * src/gui/panels/panel.c: + * src/gui/panels/panel.h: + Give a personality to each panel. Rewrite the tree of docked widgets. + + * src/gui/panels/regedit.c: + * src/gui/panels/strings.c: + * src/gui/panels/symbols.c: + Update code. + 16-03-05 Cyrille Bagard * src/arch/arm/v7/helpers.h: diff --git a/plugins/pychrysa/gui/panels/panel.c b/plugins/pychrysa/gui/panels/panel.c index 3170a66..8046c0e 100644 --- a/plugins/pychrysa/gui/panels/panel.c +++ b/plugins/pychrysa/gui/panels/panel.c @@ -32,6 +32,7 @@ #include "../editem.h" +#include "../../helpers.h" #include "../../quirks.h" @@ -42,6 +43,9 @@ static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds); /* Place un panneau dans l'ensemble affiché. */ static PyObject *py_panel_item_dock(PyObject *, PyObject *); +/* Définit les constantes pour les panneaux. */ +static bool py_panel_item_define_constants(PyTypeObject *); + /****************************************************************************** @@ -60,6 +64,7 @@ static PyObject *py_panel_item_dock(PyObject *, PyObject *); static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds) { + unsigned long personality; /* Nature du panneau */ const char *name; /* Désignation humaine */ const char *lname; /* Nom version longue */ PyGObject *widget; /* Composant visuel du panneau */ @@ -67,10 +72,10 @@ static int py_panel_item_init(PyObject *self, PyObject *args, PyObject *kwds) int ret; /* Bilan de lecture des args. */ GEditorItem *item; /* Elément de l'éditeur */ - ret = PyArg_ParseTuple(args, "ssOs", &name, &lname, &widget, &path); + ret = PyArg_ParseTuple(args, "kssOs", &personality, &name, &lname, &widget, &path); if (!ret) return -1; - item = g_panel_item_new(get_internal_ref(), name, lname, + item = g_panel_item_new(personality, get_internal_ref(), name, lname, GTK_WIDGET(pygobject_get(widget)), path); /* Enregistrement auprès de PyGObject */ @@ -161,6 +166,37 @@ PyTypeObject *get_python_panel_item_type(void) /****************************************************************************** * * +* Paramètres : obj_type = type dont le dictionnaire est à compléter. * +* * +* Description : Définit les constantes pour les panneaux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool py_panel_item_define_constants(PyTypeObject *obj_type) +{ + bool result; /* Bilan à retourner */ + + result = true; + + result &= PyDict_AddIntMacro(obj_type, PIP_INVALID); + + result &= PyDict_AddIntMacro(obj_type, PIP_SINGLETON); + result &= PyDict_AddIntMacro(obj_type, PIP_BINARY_VIEW); + result &= PyDict_AddIntMacro(obj_type, PIP_OTHER); + + result &= PyDict_AddIntMacro(obj_type, PIP_COUNT); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : module = module dont la définition est à compléter. * * * * Description : Prend en charge l'objet 'pychrysalide.gui.panels.PanelItem'. * @@ -185,6 +221,9 @@ bool register_python_panel_item(PyObject *module) if (PyType_Ready(py_panel_item_type) != 0) return false; + if (!py_panel_item_define_constants(py_panel_item_type)) + return false; + Py_INCREF(py_panel_item_type); ret = PyModule_AddObject(module, "PanelItem", (PyObject *)py_panel_item_type); if (ret != 0) return false; diff --git a/plugins/python/welcome/panel.py b/plugins/python/welcome/panel.py index 811f008..7b46c57 100644 --- a/plugins/python/welcome/panel.py +++ b/plugins/python/welcome/panel.py @@ -19,7 +19,7 @@ class WelcomePanel(PanelItem): content = self._build_panel_content() - super(WelcomePanel, self).__init__('Welcome', 'First commands', content, 'M') + super(WelcomePanel, self).__init__(PanelItem.PIP_SINGLETON, 'Welcome', 'First commands', content, 'N') def _build_panel_content(self): diff --git a/src/analysis/project.c b/src/analysis/project.c index b787262..623779b 100644 --- a/src/analysis/project.c +++ b/src/analysis/project.c @@ -666,7 +666,7 @@ size_t g_study_project_attach_binary(GStudyProject *project, GLoadedBinary *bina name = g_loaded_binary_get_name(binary, false); lname = g_loaded_binary_get_name(binary, true); - loaded->item = g_panel_item_new(project->ref, name, lname, scroll, "M"); + loaded->item = g_panel_item_new(PIP_BINARY_VIEW, project->ref, name, lname, scroll, "N"); /* Enregistrement dans le projet */ diff --git a/src/gtkext/gtkdockable.c b/src/gtkext/gtkdockable.c index 954b651..98b1a04 100644 --- a/src/gtkext/gtkdockable.c +++ b/src/gtkext/gtkdockable.c @@ -241,7 +241,7 @@ bool gtk_dockable_can_be_closed(const GtkDockable *dockable) * * ******************************************************************************/ -GtkWidget *gtk_dockable_get_widget(GtkDockable *dockable) +GtkWidget *gtk_dockable_build_widget(GtkDockable *dockable) { GtkWidget *result; /* Composant à retourner */ GtkDockableIface *iface; /* Interface utilisée */ @@ -286,6 +286,39 @@ GtkWidget *gtk_dockable_get_widget(GtkDockable *dockable) /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * +* support = composant à partir duquel décrocher ou NULL. [OUT]* +* * +* Description : Fournit tous les éléments pour un retrait graphique. * +* * +* Retour : Composant graphique à décrocher. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkWidget *gtk_dockable_decompose(GtkDockable *dockable, GtkWidget **support) +{ + GtkWidget *result; /* Composant à retourner */ + GtkDockableIface *iface; /* Interface utilisée */ + + iface = GTK_DOCKABLE_GET_IFACE(dockable); + + result = iface->get_widget(dockable); + + if (iface->can_search) + result = gtk_widget_get_parent(result); /* GtkBox */ + + if (support != NULL) + *support = gtk_widget_get_parent(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : dockable = instance GTK dont l'interface est à consulter. * * built = composant graphique d'encapsulation mis en place. * * reveal = détermine l'action à mener. * * * diff --git a/src/gtkext/gtkdockable.h b/src/gtkext/gtkdockable.h index e939fad..31a3310 100644 --- a/src/gtkext/gtkdockable.h +++ b/src/gtkext/gtkdockable.h @@ -62,7 +62,10 @@ const char *gtk_dockable_get_name(const GtkDockable *); const char *gtk_dockable_get_desc(const GtkDockable *); /* Fournit le composant graphique intégrable dans un ensemble. */ -GtkWidget *gtk_dockable_get_widget(GtkDockable *); +GtkWidget *gtk_dockable_build_widget(GtkDockable *); + +/* Fournit tous les éléments pour un retrait graphique. */ +GtkWidget *gtk_dockable_decompose(GtkDockable *, GtkWidget **); /* Révèle ou cache la zone de recherches. */ void gtk_dockable_toggle_revealer(GtkDockable *, GtkWidget *, gboolean); diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c index e10e55f..35006ef 100644 --- a/src/gtkext/gtkdockstation.c +++ b/src/gtkext/gtkdockstation.c @@ -57,7 +57,7 @@ static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *); /* Détermine le type du composant d'affichage concentré. */ -G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_BOX) +G_DEFINE_TYPE(GtkDockStation, gtk_dock_station, GTK_TYPE_NOTEBOOK) /****************************************************************************** @@ -115,53 +115,14 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class) static void gtk_dock_station_init(GtkDockStation *station) { - GtkWidget *eventbox; /* Réceptacle actif */ + GtkNotebook *notebook; /* Autre version du composant */ GtkWidget *hbox; /* Division supérieure */ GtkWidget *button; /* Bouton de contrôle */ - GtkWidget *image; /* Image associée */ - gtk_orientable_set_orientation(GTK_ORIENTABLE(station), GTK_ORIENTATION_VERTICAL); + notebook = GTK_NOTEBOOK(station); - eventbox = gtk_event_box_new(); - gtk_widget_show(eventbox); - //gtk_box_pack_start(GTK_BOX(station), eventbox, FALSE, TRUE, 0); - - hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show(hbox); - gtk_container_add(GTK_CONTAINER(eventbox), hbox); - - station->title = GTK_LABEL(qck_create_label(NULL, NULL, "titre")); - gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(station->title), TRUE, TRUE, 0); - gtk_label_set_use_markup(station->title, TRUE); - - button = gtk_button_new(); - gtk_widget_show(button); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); - - image = gtk_image_new_from_icon_name("gtk-media-play", GTK_ICON_SIZE_MENU); - gtk_widget_show(image); - gtk_container_add(GTK_CONTAINER(button), image); - gtk_widget_set_size_request(image, 10, 10); - - button = gtk_button_new(); - gtk_widget_show(button); - gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); - - image = gtk_image_new_from_icon_name("gtk-close", GTK_ICON_SIZE_MENU); - gtk_widget_show(image); - gtk_container_add(GTK_CONTAINER(button), image); - gtk_widget_set_size_request(image, 10, 10); - - - - - station->notebook = GTK_NOTEBOOK(gtk_notebook_new()); - gtk_widget_show(GTK_WIDGET(station->notebook)); - gtk_box_pack_start(GTK_BOX(station), GTK_WIDGET(station->notebook), TRUE, TRUE, 0); - gtk_notebook_set_show_border(station->notebook, FALSE); - gtk_notebook_set_scrollable(station->notebook, TRUE); + gtk_notebook_set_show_border(notebook, FALSE); + gtk_notebook_set_scrollable(notebook, TRUE); /* Définition de la zone de contrôle */ @@ -188,9 +149,9 @@ static void gtk_dock_station_init(GtkDockStation *station) gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - gtk_notebook_set_action_widget(station->notebook, hbox, GTK_PACK_END); + gtk_notebook_set_action_widget(notebook, hbox, GTK_PACK_END); - g_signal_connect(station->notebook, "switch-page", + g_signal_connect(notebook, "switch-page", G_CALLBACK(gtk_dock_station_switch_panel), station); } @@ -267,10 +228,8 @@ static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *p /****************************************************************************** * * -* Paramètres : station = plateforme GTK à compléter. * -* widget = nouvel élément à intégrer. * -* caption = intitulé court à afficher sur les onglets. * -* desc = intitulé long pour le titre et la description. * +* Paramètres : station = plateforme GTK à compléter. * +* dockable = nouvel élément à intégrer. * * * * Description : Ajoute un paquet d'informations à l'affichage centralisé. * * * @@ -279,7 +238,8 @@ static gboolean gtk_dock_station_switch_panel(GtkNotebook *notebook, gpointer *p * Remarques : - * * * ******************************************************************************/ - +#include "gtkviewpanel.h" +#include "../gui/panels/history.h" void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockable) { GtkWidget *widget; /* Composant GTK à intégrer */ @@ -288,10 +248,34 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl size_t max; /* Taille maximale des titres */ char *str; /* Titre des prochaines fois */ GtkWidget *label; /* Etiquette d'onglet */ + GtkNotebook *notebook; /* Autre version du composant */ /* Récupération des éléments utiles */ - widget = gtk_dockable_get_widget(dockable); + 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"); + */ + + //widget = gtk_button_new_with_label("123"); + gtk_widget_show(widget); + g_object_set_data(G_OBJECT(widget), "dockable", dockable); @@ -307,24 +291,52 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl label = qck_create_label(NULL, NULL, str); free(str); - if (gtk_notebook_get_n_pages(station->notebook) > 0) - g_signal_handlers_disconnect_by_func(station->notebook, + notebook = GTK_NOTEBOOK(station); + + if (gtk_notebook_get_n_pages(notebook) > 0) + g_signal_handlers_disconnect_by_func(notebook, G_CALLBACK(gtk_dock_station_switch_panel), station); - gtk_notebook_insert_page(station->notebook, widget, label, -1); + gtk_notebook_insert_page(notebook, widget, label, -1); gtk_widget_set_tooltip_text(label, desc); - if (gtk_notebook_get_n_pages(station->notebook) > 1) - g_signal_connect(station->notebook, "switch-page", + if (gtk_notebook_get_n_pages(notebook) > 1) + g_signal_connect(notebook, "switch-page", G_CALLBACK(gtk_dock_station_switch_panel), station); /* Lancement des mises à jour */ - if (gtk_notebook_get_n_pages(station->notebook) > 1) - gtk_notebook_set_current_page(station->notebook, -1); + 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); + + + + + + //g_signal_emit_by_name(station, "dock-widget", widget); } @@ -344,32 +356,35 @@ void gtk_dock_station_add_dockable(GtkDockStation *station, GtkDockable *dockabl void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *widget) { + GtkNotebook *notebook; /* Autre version du composant */ gint index; /* Indice de l'onglet actif */ GtkWidget *old; /* Ancien composant */ GtkWidget *label; /* Etiquette d'onglet */ char *str; /* Titre des prochaines fois */ - index = gtk_notebook_get_current_page(station->notebook); + notebook = GTK_NOTEBOOK(station); + + index = gtk_notebook_get_current_page(notebook); - g_signal_handlers_disconnect_by_func(station->notebook, + g_signal_handlers_disconnect_by_func(notebook, G_CALLBACK(gtk_dock_station_switch_panel), station); - old = gtk_notebook_get_nth_page(station->notebook, index); - label = gtk_notebook_get_tab_label(station->notebook, old); + 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"); - gtk_notebook_remove_page(station->notebook, index); - gtk_notebook_insert_page(station->notebook, widget, label, index); + gtk_notebook_remove_page(notebook, index); + gtk_notebook_insert_page(notebook, widget, label, index); g_object_unref(G_OBJECT(label)); g_object_set_data(G_OBJECT(widget), "title", str); - gtk_notebook_set_current_page(station->notebook, index); + gtk_notebook_set_current_page(notebook, index); - g_signal_connect(station->notebook, "switch-page", + g_signal_connect(notebook, "switch-page", G_CALLBACK(gtk_dock_station_switch_panel), station); } @@ -378,7 +393,7 @@ void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *wid /****************************************************************************** * * * Paramètres : station = plateforme GTK à compléter. * -* widget = nouvel élément à intégrer. * +* dockable = élément existant à retirer. * * * * Description : Retire un paquet d'informations de l'affichage centralisé. * * * @@ -388,26 +403,19 @@ void gtk_dock_panel_change_active_widget(GtkDockStation *station, GtkWidget *wid * * ******************************************************************************/ -void gtk_dock_panel_remove_widget(GtkDockStation *station, GtkWidget *widget) +void gtk_dock_station_remove_dockable(GtkDockStation *station, GtkDockable *dockable) { + GtkNotebook *notebook; /* Autre version du composant */ + GtkWidget *widget; /* Composant GTK à retirer */ gint index; /* Indice de l'onglet visé */ - gint count; /* Nombre d'onglets en place */ + notebook = GTK_NOTEBOOK(station); - return; + widget = gtk_dockable_decompose(dockable, NULL); + index = gtk_notebook_page_num(notebook, widget); - index = gtk_notebook_page_num(station->notebook, widget); - - gtk_notebook_remove_page(station->notebook, index); - - count = gtk_notebook_get_n_pages(station->notebook); - - //gtk_notebook_set_show_tabs(station->notebook, count > 1); - - if (count == 0) - gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(GTK_WIDGET(station))), - GTK_WIDGET(station)); + gtk_notebook_remove_page(notebook, index); } @@ -427,7 +435,7 @@ void gtk_dock_panel_remove_widget(GtkDockStation *station, GtkWidget *widget) GtkWidget *gtk_dock_panel_get_widget(GtkDockStation *station, gint index) { - return gtk_notebook_get_nth_page(station->notebook, index); + return gtk_notebook_get_nth_page(GTK_NOTEBOOK(station), index); } @@ -447,12 +455,15 @@ GtkWidget *gtk_dock_panel_get_widget(GtkDockStation *station, gint index) static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station) { + GtkNotebook *notebook; /* Autre version du composant */ gint index; /* Indice de l'onglet courant */ GtkWidget *widget; /* Panneau concerné */ GtkDockable *dockable; /* Elément encapsulé */ - index = gtk_notebook_get_current_page(station->notebook); - widget = gtk_notebook_get_nth_page(station->notebook, index); + notebook = GTK_NOTEBOOK(station); + + index = gtk_notebook_get_current_page(notebook); + widget = gtk_notebook_get_nth_page(notebook, index); dockable = GTK_DOCKABLE(g_object_get_data(G_OBJECT(widget), "dockable")); diff --git a/src/gtkext/gtkdockstation.h b/src/gtkext/gtkdockstation.h index d64a0b8..953ceb8 100644 --- a/src/gtkext/gtkdockstation.h +++ b/src/gtkext/gtkdockstation.h @@ -51,17 +51,14 @@ typedef struct _GtkDockStationClass GtkDockStationClass; /* Station de réception pour concentration d'éléments (instance) */ struct _GtkDockStation { - GtkBox vbox; /* Présence obligatoire en 1er */ - - GtkLabel *title; /* Title du support principal */ - GtkNotebook *notebook; /* Support à onglets */ + GtkNotebook parent; /* A laisser en premier */ }; /* Station de réception pour concentration d'éléments (classe) */ struct _GtkDockStationClass { - GtkBoxClass parent_class; /* Présence obligatoire en 1er */ + GtkNotebookClass parent_class; /* A laisser en premier */ /* Signaux */ @@ -86,7 +83,7 @@ void gtk_dock_station_add_dockable(GtkDockStation *, GtkDockable *); void gtk_dock_panel_change_active_widget(GtkDockStation *, GtkWidget *); /* Retire un paquet d'informations de l'affichage centralisé. */ -void gtk_dock_panel_remove_widget(GtkDockStation *, GtkWidget *); +void gtk_dock_station_remove_dockable(GtkDockStation *, GtkDockable *); /* Renvoie un composant intégré dans l'affichage centralisé. */ GtkWidget *gtk_dock_panel_get_widget(GtkDockStation *, gint); diff --git a/src/gtkext/gtkviewpanel.c b/src/gtkext/gtkviewpanel.c index a347ad8..b7829c2 100644 --- a/src/gtkext/gtkviewpanel.c +++ b/src/gtkext/gtkviewpanel.c @@ -121,8 +121,8 @@ static void gtk_view_panel_class_init(GtkViewPanelClass *class) widget_class->realize = gtk_view_panel_realize; widget_class->size_allocate = gtk_view_panel_size_allocate; widget_class->draw = gtk_view_panel_draw; - widget_class->get_preferred_height = gtk_view_panel_get_preferred_height; - widget_class->get_preferred_width = gtk_view_panel_get_preferred_width; + //widget_class->get_preferred_height = gtk_view_panel_get_preferred_height; + //widget_class->get_preferred_width = gtk_view_panel_get_preferred_width; panel_class->compute_inc = gtk_view_panel_compute_scroll_inc; diff --git a/src/gui/editem.c b/src/gui/editem.c index 1dc77c9..f4d9d71 100644 --- a/src/gui/editem.c +++ b/src/gui/editem.c @@ -131,9 +131,28 @@ GObject *g_editor_item_get_global_ref(const GEditorItem *item) * * * Paramètres : item = instance à consulter. * * * +* Description : Fournit le nom humain attribué à l'élément réactif. * +* * +* Retour : Désignation (courte) de l'élément de l'éditeur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_editor_item_get_name(const GEditorItem *item) +{ + return item->name; + +} + + +/****************************************************************************** +* * +* Paramètres : item = instance à consulter. * +* * * Description : Fournit le composant GTK associé à l'élément réactif. * * * -* Retour : - * +* Retour : Instance de composant graphique chargé. * * * * Remarques : - * * * diff --git a/src/gui/editem.h b/src/gui/editem.h index 90b1919..08f76fa 100644 --- a/src/gui/editem.h +++ b/src/gui/editem.h @@ -59,6 +59,9 @@ GType g_editor_item_get_type(void); /* Fournit l'adresse de l'espace de référencement global. */ GObject *g_editor_item_get_global_ref(const GEditorItem *); +/* Fournit le nom humain attribué à l'élément réactif. */ +const char *g_editor_item_get_name(const GEditorItem *); + /* Fournit le composant GTK associé à l'élément réactif. */ GtkWidget *g_editor_item_get_widget(const GEditorItem *); diff --git a/src/gui/menus/menubar.c b/src/gui/menus/menubar.c index db1905c..e2ad155 100644 --- a/src/gui/menus/menubar.c +++ b/src/gui/menus/menubar.c @@ -208,6 +208,8 @@ GEditorItem *g_menu_bar_new(GObject *ref, GtkAccelGroup *accgroup) result = g_object_new(G_TYPE_MENU_BAR, NULL); + g_object_set_data(G_OBJECT(result), "accgroup", accgroup); + /* Initialisation générique */ item = G_EDITOR_ITEM(result); diff --git a/src/gui/menus/project.c b/src/gui/menus/project.c index f4f6233..9e43616 100644 --- a/src/gui/menus/project.c +++ b/src/gui/menus/project.c @@ -66,7 +66,7 @@ static void mcb_project_remove_binary(GtkMenuItem *, GStudyProject *); GtkWidget *build_menu_project(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) { GtkWidget *result; /* Support à retourner */ - GtkWidget *menubar; /* Support pour éléments */ + GtkWidget *menubar; /* Support pour éléments #1 */ GtkWidget *submenuitem; /* Sous-élément de menu #1 */ GtkWidget *deepmenubar; /* Support pour éléments #2 */ GtkWidget *deepmenuitem; /* Sous-élément de menu #2 */ diff --git a/src/gui/menus/view.c b/src/gui/menus/view.c index cbfa9bf..e80077a 100644 --- a/src/gui/menus/view.c +++ b/src/gui/menus/view.c @@ -29,12 +29,19 @@ #include "../editem-int.h" +#include "../panels/panel.h" #include "../../analysis/project.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdockstation.h" +/* 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 *); + /* Réagit avec le menu "Affichage -> Vue xxx". */ static void mcb_view_change_support(GtkRadioMenuItem *, GMenuBar *); @@ -63,8 +70,9 @@ static void mcb_view_show_full_screen(GtkCheckMenuItem *, GMenuBar *); GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) { GtkWidget *result; /* Support à retourner */ - GtkWidget *menubar; /* Support pour éléments */ + GtkWidget *menubar; /* Support pour éléments #1 */ GtkWidget *submenuitem; /* Sous-élément de menu */ + GtkWidget *deepmenubar; /* Support pour éléments #2 */ GSList *rgroup; /* Groupe des boutons radio */ result = gtk_menu_item_new_with_mnemonic(_("_View")); @@ -73,6 +81,20 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) menubar = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(result), menubar); + /* Affichage -> Panneaux latéraux */ + + submenuitem = qck_create_menu_item(NULL, NULL, _("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); + + deepmenubar = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenuitem), deepmenubar); + + /* - */ + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + submenuitem = qck_create_radio_menu_item(ref, "textview", NULL, _("Text view"), G_CALLBACK(mcb_view_change_support), bar); add_accelerator_to_menu_item(submenuitem, "F2", accgroup); @@ -113,6 +135,8 @@ GtkWidget *build_menu_view(GObject *ref, GtkAccelGroup *accgroup, GMenuBar *bar) g_object_set_data(G_OBJECT(submenuitem), "kind_of_col", GUINT_TO_POINTER(BLC_BINARY)); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + /* - */ + submenuitem = qck_create_menu_separator(); gtk_container_add(GTK_CONTAINER(menubar), submenuitem); @@ -194,6 +218,148 @@ void update_menu_view_for_view(GtkWidget *widget, GtkViewPanel *view, GMenuBar * /****************************************************************************** * * +* Paramètres : menuitem = élément de menu sélectionné. * +* bar = barre de menu parente. * +* * +* Description : Réagit avec le menu "Affichage -> Panneaux latéraux". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_view_update_side_panels_list(GtkMenuItem *menuitem, GMenuBar *bar) +{ + GtkWidget *menubar; /* Support pour éléments */ + GtkAccelGroup *accgroup; /* Groupe de raccourcis */ + + typedef struct _panels_loading_filter + { + GtkContainer *support; /* Support pour éléments */ + GtkAccelGroup *accel; /* Groupe de raccourcis */ + + PanelItemPersonality personality; /* Nature des éléments attendus*/ + bool first; /* Premier ajout ? */ + + } panels_loading_filter; + + panels_loading_filter pfilter; + + + menubar = gtk_menu_item_get_submenu(menuitem); + + /* Réinitialisation */ + + void remove_panel_menu_item(GtkWidget *widget, GtkContainer *container) + { + gtk_container_remove(container, widget); + + } + + gtk_container_foreach(GTK_CONTAINER(menubar), (GtkCallback)remove_panel_menu_item, menubar); + + /* Ajout des panneaux uniques */ + + bool add_side_panel_to_list(GPanelItem *panel, panels_loading_filter *filter) + { + const char *name; /* Désignation de l'entrée */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + const char *bindings; /* Raccourcis clavier bruts */ + + if (gtk_panel_item_get_personality(panel) != filter->personality) + goto aptl_exit; + + /* Séparation */ + + if (filter->first) + { + filter->first = false; + + submenuitem = qck_create_menu_separator(); + gtk_container_add(GTK_CONTAINER(menubar), submenuitem); + + } + + /* Elément de menu */ + + name = g_editor_item_get_name(G_EDITOR_ITEM(panel)); + + submenuitem = qck_create_check_menu_item(NULL, NULL, name, + G_CALLBACK(mcb_view_change_panel_docking), panel); + + bindings = gtk_panel_item_get_key_bindings(panel); + + if (bindings != NULL) + add_accelerator_to_menu_item(submenuitem, bindings, filter->accel); + + gtk_container_add(filter->support, submenuitem); + + /* Statut de la coche */ + + if (g_panel_item_is_docked(panel)) + { + g_signal_handlers_disconnect_by_func(submenuitem, G_CALLBACK(mcb_view_change_panel_docking), panel); + + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(submenuitem), TRUE); + + g_signal_connect(submenuitem, "toggled", G_CALLBACK(mcb_view_change_panel_docking), panel); + + } + + aptl_exit: + + return true; + + } + + accgroup = GTK_ACCEL_GROUP(g_object_get_data(G_OBJECT(bar), "accgroup")); + + pfilter.support = GTK_CONTAINER(menubar); + pfilter.accel = accgroup; + + pfilter.personality = PIP_SINGLETON; + pfilter.first = false; + + browse_all_item_panels((handle_panel_item_fc)add_side_panel_to_list, &pfilter); + + pfilter.personality = PIP_OTHER; + pfilter.first = true; + + browse_all_item_panels((handle_panel_item_fc)add_side_panel_to_list, &pfilter); + +} + + +/****************************************************************************** +* * +* Paramètres : menuitem = élément de menu ayant basculé. * +* bar = barre de menu parente. * +* * +* Description : Réagit avec le menu "Affichage -> Panneaux latéraux -> ...". * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void mcb_view_change_panel_docking(GtkCheckMenuItem *menuitem, GPanelItem *item) +{ + gboolean active; /* Etat de sélection du menu */ + + active = gtk_check_menu_item_get_active(menuitem); + + if (active) + g_panel_item_dock(item); + else + g_panel_item_undock(item); + +} + + +/****************************************************************************** +* * * Paramètres : menuitem = élément de menu ayant basculé. * * bar = barre de menu parente. * * * diff --git a/src/gui/panels/bookmarks.c b/src/gui/panels/bookmarks.c index e06b891..9eaa1df 100644 --- a/src/gui/panels/bookmarks.c +++ b/src/gui/panels/bookmarks.c @@ -236,6 +236,7 @@ static void g_bookmarks_panel_class_init(GBookmarksPanelClass *klass) static void g_bookmarks_panel_init(GBookmarksPanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GObject *ref; /* Espace de référencement */ GtkTreeStore *store; /* Modèle de gestion */ GtkWidget *treeview; /* Affichage de la liste */ @@ -255,6 +256,10 @@ static void g_bookmarks_panel_init(GBookmarksPanel *panel) ref = G_OBJECT(base->widget); g_object_set_data(ref, "panel", panel); + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + /* Partie signets */ store = gtk_tree_store_new(BMC_COUNT, G_TYPE_OBJECT, diff --git a/src/gui/panels/glance.c b/src/gui/panels/glance.c index 306281a..6373edd 100644 --- a/src/gui/panels/glance.c +++ b/src/gui/panels/glance.c @@ -173,16 +173,24 @@ static void g_glance_panel_class_init(GGlancePanelClass *klass) static void g_glance_panel_init(GGlancePanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GtkWidget *area; /* Surface de dessin réelle */ base = G_EDITOR_ITEM(panel); base->name = _("Glance"); + base->widget = gtk_event_box_new(); + + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + + /* Support de dessin */ + area = gtk_drawing_area_new(); gtk_widget_show(area); - base->widget = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(base->widget), area); gtk_widget_show(base->widget); diff --git a/src/gui/panels/history.c b/src/gui/panels/history.c index 74945c7..4d4be0c 100644 --- a/src/gui/panels/history.c +++ b/src/gui/panels/history.c @@ -156,6 +156,7 @@ static void g_history_panel_class_init(GHistoryPanelClass *klass) static void g_history_panel_init(GHistoryPanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GObject *ref; /* Espace de référencement */ GtkWidget *scrollwnd; /* Support défilant */ GtkWidget *treeview; /* Affichage de la liste */ @@ -173,6 +174,10 @@ static void g_history_panel_init(GHistoryPanel *panel) ref = G_OBJECT(panel); + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + /* Liste des éléments d'évolution */ scrollwnd = gtk_scrolled_window_new(NULL, NULL); @@ -305,7 +310,7 @@ GEditorItem *g_history_panel_new(GObject *ref) result = g_object_new(G_TYPE_HISTORY_PANEL, NULL); g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_HISTORY_ID, - _("Change history"), G_EDITOR_ITEM(result)->widget, "eM"); + _("Change history"), G_EDITOR_ITEM(result)->widget, "eN"); return result; diff --git a/src/gui/panels/log.c b/src/gui/panels/log.c index ab815e4..7893666 100644 --- a/src/gui/panels/log.c +++ b/src/gui/panels/log.c @@ -120,12 +120,18 @@ G_DEFINE_TYPE(GLogPanel, g_log_panel, G_TYPE_PANEL_ITEM); static void g_log_panel_class_init(GLogPanelClass *klass) { GObjectClass *object; /* Autre version de la classe */ + GPanelItemClass *panel; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_log_panel_dispose; object->finalize = (GObjectFinalizeFunc)g_log_panel_finalize; + panel = G_PANEL_ITEM_CLASS(klass); + + panel->unique = true; + panel->bindings = "F1"; + } @@ -143,16 +149,27 @@ static void g_log_panel_class_init(GLogPanelClass *klass) static void g_log_panel_init(GLogPanel *panel) { + GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GtkWidget *scrolled; /* Fenêtre avec défilements */ GtkTreeStore *store; /* Modèle de gestion */ GtkWidget *treeview; /* Affichage de la liste */ GtkCellRenderer *renderer; /* Moteur de rendu de colonne */ GtkTreeViewColumn *column; /* Colonne de la liste */ - GEditorItem *base; /* Version basique d'instance */ + + base = G_EDITOR_ITEM(panel); scrolled = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(scrolled); + base->widget = scrolled; + + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + + /* Construction graphique */ + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN); @@ -184,9 +201,6 @@ static void g_log_panel_init(GLogPanel *panel) gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); - base = G_EDITOR_ITEM(panel); - base->widget = scrolled; - } diff --git a/src/gui/panels/panel-int.h b/src/gui/panels/panel-int.h index b3a9f10..e902722 100644 --- a/src/gui/panels/panel-int.h +++ b/src/gui/panels/panel-int.h @@ -29,8 +29,7 @@ #include "panel.h" -#include -#include +#include #include "../editem-int.h" @@ -45,10 +44,14 @@ struct _GPanelItem DL_LIST_ITEM(link); /* Maillon de liste chaînée */ + PanelItemPersonality personality; /* Nature de l'élément */ + const char *lname; /* Description longue */ const char *path; /* Chemin vers la place idéale */ + bool docked; /* Panneau inscrusté ? */ + }; @@ -57,18 +60,25 @@ typedef struct _panel_node { struct _panel_node *parent; /* Noeud parent */ - char *path; /* Chemin du nom courant */ - size_t depth; /* Profondeur utilisée */ + union + { + GtkWidget *widget; /* Accès généraliste */ + GtkWidget *station; /* Station d'accueil simple */ + GtkWidget *paned; /* Station d'accueil composée */ - bool simple; /* Noeud sans division */ + }; union { - GtkWidget *station; /* Station d'accueil simple */ + /* Version simple */ + struct + { + char *path; /* Chemin du nom courant */ + }; + /* Version composée */ struct { - GtkWidget *paned; /* Station d'accueil composée */ struct _panel_node *first; /* Premier sous élément */ struct _panel_node *second; /* Second sous élément */ }; @@ -78,7 +88,16 @@ typedef struct _panel_node } panel_node; -#define GET_PANEL_NODE_WIDGET(node) (node->simple ? node->station : node->paned) + +#define IS_SIMPLE_NODE(nd) \ + ({ \ + bool __result; \ + __result = GTK_IS_DOCK_STATION(nd->station); \ + assert(__result || GTK_IS_PANED(nd->paned)); \ + __result; \ + }) + + /* Elément réactif pour panneaux de l'éditeur (classe) */ @@ -86,6 +105,9 @@ struct _GPanelItemClass { GEditorItemClass parent; /* A laisser en premier */ + bool unique; /* Panneau instanciable ? */ + const char *bindings; /* Raccourci clavier éventuel */ + GtkBin *first; /* Elément racine */ }; diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c index 01307cb..8af8672 100644 --- a/src/gui/panels/panel.c +++ b/src/gui/panels/panel.c @@ -25,6 +25,7 @@ #include "panel.h" +#include #include #include #include @@ -38,6 +39,7 @@ #include "regedit.h" #include "strings.h" #include "symbols.h" +#include "../../common/extstr.h" #include "../../gtkext/easygtk.h" #include "../../gtkext/gtkdockable-int.h" #include "../../gtkext/gtkdockstation.h" @@ -80,7 +82,7 @@ static GtkWidget *gtk_panel_item_get_widget(GPanelItem *); /* Crée un nouveau noeud pour un panneau particulier. */ -static panel_node *create_simple_panel_node_for_item(GPanelItem *, const char *, size_t); +//static panel_node *create_simple_panel_node_for_item(GPanelItem *, const char *, size_t); /* Prépare une nouvelle sous-division pour deux panneaux. */ static void switch_panel_node_into_paned(panel_node *, bool, bool); @@ -88,41 +90,34 @@ 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); -/* Valorise la correspondance entre un noeud et un chemin. */ -static int compute_panel_node_matching_score(const panel_node *, const char *); -/* Calcule la longueur du plus court chemin vers un 'M'. */ -static size_t _compute_panel_node_main_level(const panel_node *); -/* Recherche le noeud constituant la branche principale. */ -static panel_node *find_main_panel_node_branch(panel_node *, panel_node *); -/* Place au bon endroit un panneau donné. */ -static void insert_item_as_panel_node(GPanelItem *, panel_node *, const char *, size_t); +/* Crée un nouveau noeud pour un panneau particulier. */ +static panel_node *create_simple_panel_node_for_item(GPanelItem *, const char *); -/* Met à jour l'affichage suite à un changement hiérarchique. */ -static void rebuild_panels_interface(const panel_node *); -/* ---------------------- REAJUSTEMENT AUTOMATIQUE DE L'ESPACE ---------------------- */ +/* Obtient la désignation d'un élément hiérarchie des noeuds. */ +static char *get_panel_node_path(const panel_node *); +/* Détermine la plus grande longueur commune entre éléments. */ +static size_t compute_path_common_length(const panel_node *, const char *); -/* Part réservée aux parties principales (en %) */ -#define MAIN_PART_PERCENT 70 +/* Détermine la plus grande profondeur d'un noeud de panneaux. */ +static unsigned int compute_deepest_depth(const panel_node *); -/* Part minimale des petits composants (en %) */ -#define MIN_PART_PERCENT 20 +/* Place au bon endroit un panneau donné. */ +static void 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 *); -/* Met à jour l'affichage suite à un changement hiérarchique. */ -static void auto_resize_panels(GtkWidget *, GdkRectangle *, gpointer); +/* Efface de l'organisation un noeud donné en place. */ +static void delete_panel_node(panel_node *); -/* S'enquiert de la taille idéale pour un noeud. */ -static void get_panel_node_size_request(const panel_node *, GtkRequisition *); -/* Impose une taille accordée à un noeud. */ -static void set_panel_node_size_request(const panel_node *, const GtkRequisition *); @@ -167,6 +162,8 @@ static void g_panel_item_init(GPanelItem *item) { DL_LIST_ITEM_INIT(&item->link); + item->personality = PIP_INVALID; + } @@ -239,7 +236,8 @@ void g_panel_item_init_ext(GPanelItem *item, GObject *ref, const char *name, con /****************************************************************************** * * -* Paramètres : ref = espace de référencement global. * +* Paramètres : personality = nature du panneau à mettre en place. * +* ref = espace de référencement global. * * name = nom associé à l'élément. * * lname = description longue du panneau. * * widget = composant à présenter à l'affichage. * @@ -253,12 +251,15 @@ void g_panel_item_init_ext(GPanelItem *item, GObject *ref, const char *name, con * * ******************************************************************************/ -GEditorItem *g_panel_item_new(GObject *ref, const char *name, const char *lname, GtkWidget *widget, const char *path) +GEditorItem *g_panel_item_new(PanelItemPersonality personality, GObject *ref, const char *name, const char *lname, GtkWidget *widget, const char *path) { GPanelItem *result; /* Structure à retourner */ result = g_object_new(G_TYPE_PANEL_ITEM, NULL); + assert(personality > PIP_INVALID && personality < PIP_COUNT); + result->personality = personality; + g_panel_item_init_ext(result, ref, name, lname, widget, path); return G_EDITOR_ITEM(result); @@ -325,6 +326,44 @@ static GtkWidget *gtk_panel_item_get_widget(GPanelItem *item) /****************************************************************************** * * +* Paramètres : item = instance GTK à consulter. * +* * +* Description : Fournit une indication sur la personnalité du panneau. * +* * +* Retour : Identifiant lié à la nature du panneau. * +* * +* Remarques : - * +* * +******************************************************************************/ + +PanelItemPersonality gtk_panel_item_get_personality(const GPanelItem *item) +{ + return item->personality; + +} + + +/****************************************************************************** +* * +* Paramètres : item = instance GTK dont l'interface est à consulter. * +* * +* Description : Indique la définition d'un éventuel raccourci clavier. * +* * +* Retour : Description d'un raccourci ou NULL si aucun de défini. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *gtk_panel_item_get_key_bindings(const GPanelItem *item) +{ + return G_PANEL_ITEM_GET_CLASS(item)->bindings; + +} + + +/****************************************************************************** +* * * Paramètres : name = désignation courte servant de clef. * * * * Description : Recherche un panneau à partir de son nom court. * @@ -364,16 +403,95 @@ GPanelItem *g_panel_item_get(const char *name) * * ******************************************************************************/ +static void dump_tree(GtkWidget *root, unsigned int level) +{ + unsigned int i; + GList *list; + GList *iter; + + if (strcmp(G_OBJECT_TYPE_NAME(G_OBJECT(root)), "GtkButton") == 0) + return; + + for (i = 0; i < level; i++) + fprintf(stderr, " "); + + fprintf(stderr, "%s (%p)\n", G_OBJECT_TYPE_NAME(G_OBJECT(root)), root); + + if (GTK_IS_CONTAINER(root)) + { + list = gtk_container_get_children(GTK_CONTAINER(root)); + + for (iter = list; iter != NULL; iter = g_list_next(iter)) + dump_tree(GTK_WIDGET(iter->data), level + 1); + + } + +} + + +void dump_node(panel_node *node, unsigned int level) +{ + unsigned i; + + for (i = 0; i < level; i++) + fprintf(stderr, " "); + + fprintf(stderr, "%p %p -- widget %p -- '%s'\n", node->parent, node, node->station, + IS_SIMPLE_NODE(node) ? node->path : "-"); + + if (!IS_SIMPLE_NODE(node)) + { + dump_node(node->first, level + 1); + dump_node(node->second, level + 1); + } + + +} + + + void g_panel_item_dock(GPanelItem *item) { + assert(!item->docked); + + fprintf(stderr, "\n---------\n\n"); + /* Tout est à faire... */ if (_nodes == NULL) { - _nodes = create_simple_panel_node_for_item(item, item->path, 0); - gtk_container_add(GTK_CONTAINER(_support), _nodes->station); + _nodes = create_simple_panel_node_for_item(item, item->path); + gtk_container_add(GTK_CONTAINER(_support), _nodes->widget); } else insert_item_as_panel_node(item, _nodes, item->path, 0); + item->docked = true; + + + + dump_tree(_support, 0); + fprintf(stderr, "\n"); + dump_node(_nodes, 0); + + +} + + +/****************************************************************************** +* * +* Paramètres : item = composant d'affichage à consulter. * +* * +* Description : Indique si le composant repose sur un support de l'éditeur. * +* * +* Retour : true si le composant est bien incrusté quelque part. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_panel_item_is_docked(const GPanelItem *item) +{ + return item->docked; + } @@ -391,12 +509,25 @@ void g_panel_item_dock(GPanelItem *item) void g_panel_item_undock(GPanelItem *item) { - GtkWidget *station; /* Base du remplacement */ + GtkWidget *station; /* Support courant */ + panel_node *node; /* Noeud à supprimer */ - station = gtk_widget_get_parent(G_EDITOR_ITEM(item)->widget); /* NoteBook */ - station = gtk_widget_get_parent(station); /* DockStation */ + assert(item->docked); - gtk_dock_panel_remove_widget(GTK_DOCK_STATION(station), G_EDITOR_ITEM(item)->widget); + gtk_dockable_decompose(GTK_DOCKABLE(item), &station); + + gtk_dock_station_remove_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(item)); + + if (gtk_notebook_get_n_pages(GTK_NOTEBOOK(station)) == 0) + { + node = find_node_for_station(_nodes, station); + assert(node != NULL); + + delete_panel_node(node); + + } + + item->docked = false; } @@ -427,7 +558,7 @@ GtkWidget *init_panels2(GCallback handler, gpointer data) result = gtk_event_box_new(); gtk_widget_show(result); - g_signal_connect(result, "size-allocate", G_CALLBACK(auto_resize_panels), NULL); + //g_signal_connect(result, "size-allocate", G_CALLBACK(auto_resize_panels), NULL); _support = result; _handler = handler; @@ -454,10 +585,10 @@ void load_main_panels(GObject *ref) { GPanelItem *item; /* Panneau de base à charger */ - item = create_regedit_panel(ref); + item = create_log_panel(ref); g_panel_item_dock(item); - item = create_log_panel(ref); + item = create_regedit_panel(ref); g_panel_item_dock(item); item = create_symbols_panel(ref); @@ -478,54 +609,49 @@ void load_main_panels(GObject *ref) } - -/* ---------------------------------------------------------------------------------- */ -/* MECANISMES DE PLACEMENT DES PANNEAUX */ -/* ---------------------------------------------------------------------------------- */ - - /****************************************************************************** * * -* Paramètres : item = composant à présenter à l'affichage. * -* path = partie du chemin représentée ici. * -* depth = profondeur du chemin utilisé. * +* Paramètres : handle = routine à appeler pour chaque panneau. * +* data = données fournies pour accompagner cet appel. * * * -* Description : Crée un nouveau noeud pour un panneau particulier. * +* Description : Effectue le parcours de tous les panneaux chargés. * * * -* Retour : Structure d'accueil mise en place. * +* Retour : true si le parcours a été total, false sinon. * * * * Remarques : - * * * ******************************************************************************/ -static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const char *path, size_t depth) +bool browse_all_item_panels(handle_panel_item_fc handle, void *data) { - panel_node *result; /* Structure à retourner */ - GtkWidget *station; /* Premier support concentré */ - - result = (panel_node *)calloc(1, sizeof(panel_node)); - - result->path = strdup(path); - result->depth = depth; + bool result; /* Résultat à renvoyer */ + GPanelItem *iter; /* Boucle de parcours */ - result->simple = true; + result = true; - station = gtk_dock_station_new(); - g_signal_connect(station, "switch-widget", _handler, _data); - gtk_widget_show(station); + panels_list_for_each(iter, _panels_list) + { + result = handle(iter, data); - result->station = station; + if (!result) break; - gtk_dock_station_add_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(item)); + } return result; } + +/* ---------------------------------------------------------------------------------- */ +/* MECANISMES DE PLACEMENT DES PANNEAUX */ +/* ---------------------------------------------------------------------------------- */ + + + /****************************************************************************** * * -* Paramètres : item = composant à présenter à l'affichage. * +* Paramètres : node = noeud à diviser. * * horiz = indique le type d'orientation désiré. * * first = indication sur l'emplacement à utiliser. * * * @@ -537,51 +663,98 @@ static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const cha * * ******************************************************************************/ -static void switch_panel_node_into_paned(panel_node *current, bool horiz, bool first) +static void switch_panel_node_into_paned(panel_node *node, bool horiz, bool first) { - panel_node *moved; /* Noeud descendu d'un étage */ 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, current, sizeof(panel_node)); - moved->parent = current; + memcpy(moved, node, sizeof(panel_node)); - widget = GET_PANEL_NODE_WIDGET(current); + if (!IS_SIMPLE_NODE(moved)) + { + moved->first->parent = moved; + moved->second->parent = moved; + } - g_object_ref(G_OBJECT(widget)); - gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget); + /* Création du nouveau niveau intermédiaire */ - if (first) - current->first = moved; + if (horiz) + node->paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); else - current->second = moved; + node->paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); - /* Achève la transformation */ + gtk_widget_show(node->paned); - current->path = NULL; + if (parent == NULL) + attach_panel_node_to_paned(parent, node, true); + else + attach_panel_node_to_paned(parent, node, parent->first == node); - current->simple = false; - current->station = NULL; - if (horiz) - current->paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL); - else - current->paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL); - gtk_widget_show(current->paned); + /* Premier ajustement */ - /* Replace le composant d'origine */ + void split_paned_support(GtkWidget *support, GdkRectangle *alloc, gpointer data) + { + GtkOrientation orientation; + gint position; - if (first) - gtk_paned_add1(GTK_PANED(current->paned), widget); - else - gtk_paned_add2(GTK_PANED(current->paned), widget); + orientation = gtk_orientable_get_orientation(GTK_ORIENTABLE(support)); + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + position = alloc->width / 2; + else + position = alloc->height / 2; + + /* + if (position < 50) + position *= 2; + */ + + gtk_paned_set_position(GTK_PANED(support), position); + + fprintf(stderr, "widget size is currently %dx%d\n", alloc->width, alloc->height); + + + fprintf(stderr, "position = %d\n", position); + + fprintf(stderr, "---\n"); + + + g_signal_handlers_disconnect_by_func(support, G_CALLBACK(split_paned_support), NULL); + + } + + //g_signal_connect(current->paned, "size-allocate", G_CALLBACK(split_paned_support), NULL); + + static int __counter = 0; + + + + if (++__counter == 4) + gtk_paned_set_position(GTK_PANED(node->paned), 100); + + + + + /* Replace le composant d'origine */ - g_object_unref(G_OBJECT(widget)); + attach_panel_node_to_paned(node, moved, first); } @@ -602,67 +775,143 @@ static void switch_panel_node_into_paned(panel_node *current, bool horiz, bool f static void attach_panel_node_to_paned(panel_node *parent, panel_node *node, bool first) { - GtkWidget *widget; /* Composant à traiter */ + node->parent = parent; + + /* On se trouve à la racine... */ - /* Raccordement hiérarchique */ + if (parent == NULL) + gtk_container_add(GTK_CONTAINER(_support), node->widget); - if (first) - parent->first = node; else - parent->second = node; + { + /* Raccordement hiérarchique */ - node->parent = parent; + if (first) + parent->first = node; + else + parent->second = node; - /* Raccordement graphique */ + /* Raccordement graphique */ - widget = GET_PANEL_NODE_WIDGET(node); + assert(!IS_SIMPLE_NODE(parent)); - if (first) - gtk_paned_add1(GTK_PANED(parent->paned), widget); - else - gtk_paned_add2(GTK_PANED(parent->paned), widget); + 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); + + } } + + + + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + + + + + + + /****************************************************************************** * * -* Paramètres : node = noeud d'où lancer les recherches. * -* target = identifiant de la position visée. * +* Paramètres : item = composant à présenter à l'affichage. * +* path = partie du chemin représentée ici. * * * -* Description : Valorise la correspondance entre un noeud et un chemin. * +* Description : Crée un nouveau noeud pour un panneau particulier. * * * -* Retour : Bilan de l'évaluation. * +* Retour : Structure d'accueil mise en place. * * * * Remarques : - * * * ******************************************************************************/ -static int compute_panel_node_matching_score(const panel_node *node, const char *target) +static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const char *path) { - int result; /* Bilan à retourner */ - size_t len; /* Longueur de comparaison */ - size_t i; /* Boucle de parcours */ + panel_node *result; /* Structure à retourner */ + GtkWidget *station; /* Premier support concentré */ - if (node->simple) - { - result = 0; + /* Partie graphique */ - len = strlen(node->path); - len = MIN(len, strlen(target)); + station = gtk_dock_station_new(); + g_signal_connect(station, "switch-widget", _handler, _data); + gtk_widget_show(station); - for (i = 0; i < len; i++) - { - if (node->path[i] != target[i]) break; - else result++; - } + 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 dont la désignation est à obtenir. * +* * +* Description : Obtient la désignation d'un élément hiérarchie des noeuds. * +* * +* Retour : Chaîne construite à libérer de la mémoire après usage. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *get_panel_node_path(const panel_node *node) +{ + char *result; /* Valeur à retourner */ + char *extra; /* Complément à ajouter */ + + if (IS_SIMPLE_NODE(node)) + result = strdup(node->path); else { - result = compute_panel_node_matching_score(node->first, target); - result = MAX(result, compute_panel_node_matching_score(node->second, target)); + result = get_panel_node_path(node->first); + + extra = get_panel_node_path(node->second); + result = stradd(result, "-"); + result = stradd(result, extra); + free(extra); + + result = strprep(result, "("); + result = stradd(result, ")"); + + } return result; @@ -673,8 +922,9 @@ static int compute_panel_node_matching_score(const panel_node *node, const char /****************************************************************************** * * * Paramètres : node = noeud d'où lancer les recherches. * +* target = identifiant de la position visée. * * * -* Description : Calcule la longueur du plus court chemin vers un 'M'. * +* Description : Détermine la plus grande longueur commune entre éléments. * * * * Retour : Bilan de l'évaluation. * * * @@ -682,23 +932,34 @@ static int compute_panel_node_matching_score(const panel_node *node, const char * * ******************************************************************************/ -static size_t _compute_panel_node_main_level(const panel_node *node) +static size_t compute_path_common_length(const panel_node *node, const char *target) { - size_t result; /* Plus petit chemin à renvoyer*/ + 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 (node->simple) + if (IS_SIMPLE_NODE(node)) { - result = strcspn(&node->path[node->depth], "M"); + len = MIN(strlen(node->path), strlen(target)); - if (node->path[node->depth + result] == '\0') - result = SIZE_MAX; + /** + * 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 { - result = _compute_panel_node_main_level(node->first); - result = MIN(result, _compute_panel_node_main_level(node->second)); + common1 = compute_path_common_length(node->first, target); + common2 = compute_path_common_length(node->second, target); + + result = MAX(common1, common2); + } return result; @@ -708,31 +969,33 @@ static size_t _compute_panel_node_main_level(const panel_node *node) /****************************************************************************** * * -* Paramètres : a = première branche à analyser. * -* b = seconde branche à analyser. * +* Paramètres : node = noeud d'où lancer les mesures. * * * -* Description : Recherche le noeud constituant la branche principale. * +* Description : Détermine la plus grande profondeur d'un noeud de panneaux. * * * -* Retour : Branche principale ou NULL si aucune n'est idéale. * +* Retour : Valeur strictement positive. * * * * Remarques : - * * * ******************************************************************************/ -static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b) +static unsigned int compute_deepest_depth(const panel_node *node) { - panel_node *result; /* Trouvaille à remonter */ - size_t main_a; /* Proximité du 'M' côté a */ - size_t main_b; /* Proximité du 'M' côté b */ - - main_a = _compute_panel_node_main_level(a); - main_b = _compute_panel_node_main_level(b); + unsigned int result; /* Profondeur à renvoyer */ + unsigned int depth1; /* Profondeur du côté #1 */ + unsigned int depth2; /* Profondeur du côté #2 */ - if (main_a == SIZE_MAX && main_b == SIZE_MAX) - result = NULL; + if (IS_SIMPLE_NODE(node)) + result = 1; else - result = (main_a < main_b ? a : b); + { + depth1 = compute_deepest_depth(node->first); + depth2 = compute_deepest_depth(node->second); + + result = MAX(depth1, depth2); + + } return result; @@ -741,10 +1004,10 @@ static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b) /****************************************************************************** * * -* Paramètres : item = composant à présenter à l'affichage. * -* node = point d'insertion courant. * -* path = partie du chemin représentée ici. * -* depth = profondeur du chemin utilisé. * +* 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é. * * * @@ -754,58 +1017,47 @@ static panel_node *find_main_panel_node_branch(panel_node *a, panel_node *b) * * ******************************************************************************/ -static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const char *path, size_t depth) +static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const char *path, size_t consumed) { char div; /* Division demandée */ bool horiz; /* Traduction en composant */ bool first; /* Point d'insertion */ panel_node *new; /* Nouveau noeud créé */ - int score1; /* Score de la 1ère branche */ - int score2; /* Score de la 2nde branche */ - panel_node *support; /* Noeud d'accueil désigné */ + size_t common1; /* Tron common avec le côté #1 */ + size_t common2; /* Tron common avec le côté #2 */ - if (node->simple) - { - /* Si on est sur la bonne voie... */ - if (compute_panel_node_matching_score(node, path) > 0) - { - /* 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)); - /* On ne peut aller plus loin, on doit diviser... */ - else - { - div = toupper(path[depth]); - first = (div == 'E' || div == 'S'); - horiz = (div == 'W' || div == 'E'); - - switch_panel_node_into_paned(node, horiz, first); - - new = create_simple_panel_node_for_item(item, path, depth); + fprintf(stderr, "=== INSERTING '%s' (%zu)... -> '%s'\n", path, consumed, + IS_SIMPLE_NODE(node) ? node->path : "-"); - attach_panel_node_to_paned(node, new, !first); - rebuild_panels_interface(node); - } - - } + 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)); /* On ne peut aller plus loin, on doit diviser... */ else { - div = toupper(path[depth]); - first = (div == 'E' || div == 'S'); + div = toupper(path[consumed]); + first = (div == 'W' || div == 'N'); horiz = (div == 'W' || div == 'E'); - switch_panel_node_into_paned(node, horiz, first); + fprintf(stderr, "---%%<--- first=%d horiz=%d\n", first, horiz); - new = create_simple_panel_node_for_item(item, path, depth); + fprintf(stderr, "--- cutting %p\n", node->station); - attach_panel_node_to_paned(node, new, !first); + switch_panel_node_into_paned(node, horiz, !first); - rebuild_panels_interface(node); + new = create_simple_panel_node_for_item(item, path); + + attach_panel_node_to_paned(node, new, first); + + + fprintf(stderr, "1# [%p] widget = %p --- split :: %p // %p\n", + node, node->station, node->first, node->second); } @@ -815,62 +1067,44 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const else { - score1 = compute_panel_node_matching_score(node->first, path); - score2 = compute_panel_node_matching_score(node->second, path); + common1 = compute_path_common_length(node->first, path); + common2 = compute_path_common_length(node->second, path); + + + fprintf(stderr, " - L1 :: %zu <-> '%s'\n", common1, get_panel_node_path(node->first)); + fprintf(stderr, " - L2 :: %zu <-> '%s'\n", common2, get_panel_node_path(node->second)); + /* Si une descente est possible... */ - if (score1 > 0 || score2 > 0) + if (common1 > 0 || common2 > 0) { - if (node->first->simple || node->second->simple) - depth++; - - if (score1 > score2) - insert_item_as_panel_node(item, node->first, path, depth); + if (common1 > common2) + insert_item_as_panel_node(item, node->first, path, common1); else - insert_item_as_panel_node(item, node->second, path, depth); + insert_item_as_panel_node(item, node->second, path, common2); } /* Sinon, on doit diviser qqch... */ else { - /* Si l'élément doit passer en force */ - if (isupper(path[depth])) - { - div = path[depth]; - first = (div == 'E' || div == 'S'); - horiz = (div == 'W' || div == 'E'); - - switch_panel_node_into_paned(node, horiz, first); - - new = create_simple_panel_node_for_item(item, path, depth); - - attach_panel_node_to_paned(node, new, !first); - - rebuild_panels_interface(node); - - } - - else - { - support = find_main_panel_node_branch(node->first, node->second); - if (support == NULL) - support = node->first; + div = toupper(path[consumed]); + first = (div == 'W' || div == 'N'); + horiz = (div == 'W' || div == 'E'); - div = toupper(path[depth]); - first = (div == 'E' || div == 'S'); - horiz = (div == 'W' || div == 'E'); + fprintf(stderr, "---%%<--- first=%d horiz=%d\n", first, horiz); - switch_panel_node_into_paned(support, horiz, first); + switch_panel_node_into_paned(node, horiz, !first); - new = create_simple_panel_node_for_item(item, path, depth); + new = create_simple_panel_node_for_item(item, path); - attach_panel_node_to_paned(support, new, !first); + attach_panel_node_to_paned(node, new, first); - rebuild_panels_interface(support); - } + fprintf(stderr, "2# [%p] split :: %p-%p // %p-%p\n", node, + node->first, node->first->widget, + node->second, node->second->widget); } @@ -881,55 +1115,42 @@ static void insert_item_as_panel_node(GPanelItem *item, panel_node *node, const /****************************************************************************** * * -* Paramètres : current = point de départ de la réorganisation graphique. * +* Paramètres : node = point de départ des recherches locales. * * * -* Description : Met à jour l'affichage suite à un changement hiérarchique. * +* Description : Tente de mettre la main sur une station d'accueil. * * * -* Retour : - * +* Retour : Eventuel noeud trouvé ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -static void rebuild_panels_interface(const panel_node *current) +static panel_node *find_node_for_station(panel_node *node, GtkWidget *station) { - GtkWidget *widget; /* Composant à traiter */ - panel_node *parent; /* Raccourci confortable */ - - widget = GET_PANEL_NODE_WIDGET(current); + panel_node *result; /* Bilan à remonter */ - /* On se trouve à la racine... */ - if (current->parent == NULL) - gtk_container_add(GTK_CONTAINER(_support), widget); + if (IS_SIMPLE_NODE(node)) + result = (node->station == station ? node : NULL); - /* Sinon, une sous-division ne peut venir que d'une division... */ else { - /* BUG_ON(parent->simple) */ - - parent = current->parent; + result = find_node_for_station(node->first, station); - if (current == parent->first) - gtk_paned_add1(GTK_PANED(parent->paned), widget); - else - gtk_paned_add2(GTK_PANED(parent->paned), widget); + if (result == NULL) + result = find_node_for_station(node->second, station); } -} - - + return result; -/* ---------------------------------------------------------------------------------- */ -/* REAJUSTEMENT AUTOMATIQUE DE L'ESPACE */ -/* ---------------------------------------------------------------------------------- */ +} /****************************************************************************** * * -* Paramètres : current = point de départ de la réorganisation graphique. * +* Paramètres : node = noeud à supprimer de l'arbre des noeuds. * * * -* Description : Met à jour l'affichage suite à un changement hiérarchique. * +* Description : Efface de l'organisation un noeud donné en place. * * * * Retour : - * * * @@ -937,77 +1158,91 @@ static void rebuild_panels_interface(const panel_node *current) * * ******************************************************************************/ -static void auto_resize_panels(GtkWidget *support, GdkRectangle *alloc, gpointer data) +static void delete_panel_node(panel_node *node) { - GtkRequisition available; /* Taille disponible */ + panel_node *parent; /* Noeud parent à transformer */ + GtkWidget *widget; /* Composant à traiter */ + panel_node *grandparent; /* Noeud supérieur au parent */ + panel_node *remaining; /* Noeud restant */ - //g_signal_handlers_disconnect_by_func(support, G_CALLBACK(auto_resize_panels), NULL); + assert(IS_SIMPLE_NODE(node)); - available.width = alloc->width; - available.height = alloc->height; + parent = node->parent; - set_panel_node_size_request(_nodes, &available); + /* Destruction du noeud */ - //g_signal_connect(support, "size-allocate", G_CALLBACK(auto_resize_panels), NULL); + widget = node->station; + gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget); -} + free(node->path); + free(node); -/****************************************************************************** -* * -* Paramètres : node = noeud à consulter. * -* req = taille demandée par le noeud. [OUT] * -* * -* Description : S'enquiert de la taille idéale pour un noeud. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ + /* Suppression du niveau intermédiaire */ -static void get_panel_node_size_request(const panel_node *node, GtkRequisition *req) -{ - gint handle_size; /* Taille de la séparation */ - GtkRequisition tmp; /* Stockage temporaire */ + if (parent != NULL) + { + remaining = (node == parent->first ? parent->second : parent->first); - if (node->simple) - gtk_widget_get_preferred_size(node->station, NULL, req); + /* Décroche graphiquement le support */ - else - { - gtk_widget_style_get(node->paned, "handle-size", &handle_size, NULL); + widget = remaining->widget; - if (HAS_H_ORIENTATION(node->paned)) - { - req->width = handle_size; - req->height = 0; - } - else + 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)) { - req->width = 0; - req->height = handle_size; + parent->first->parent = parent; + parent->second->parent = parent; } - get_panel_node_size_request(node->first, &tmp); - req->width += tmp.width; - req->height += tmp.height; + free(remaining); - get_panel_node_size_request(node->second, &tmp); - req->width += tmp.width; - req->height += tmp.height; + if (grandparent == NULL) + attach_panel_node_to_paned(grandparent, parent, true); + else + attach_panel_node_to_paned(grandparent, parent, grandparent->first == parent); } } + + + + + + + + + + + + +#if 1 + + +#include "../../core/params.h" + + + /****************************************************************************** * * -* Paramètres : node = noeud à consulter. * -* space = taille disponible pour le noeud. * +* Paramètres : current = point de départ de la réorganisation graphique. * * * -* Description : Impose une taille accordée à un noeud. * +* Description : Met à jour l'affichage suite à un changement hiérarchique. * * * * Retour : - * * * @@ -1015,125 +1250,45 @@ static void get_panel_node_size_request(const panel_node *node, GtkRequisition * * * ******************************************************************************/ -static void set_panel_node_size_request(const panel_node *node, const GtkRequisition *space) +void save_panel_nodes(void) { - GtkRequisition first_req; /* Taille demandée par n°1 */ - GtkRequisition second_req; /* Taille demandée par n°2 */ - gint handle_size; /* Taille de la séparation */ - panel_node *main_node; /* Branche principale */ - gint position; /* Position de la séparation */ - bool can_lower; /* Diminution possible ? */ - bool can_upper; /* Augmentation possible ? */ - GtkAllocation allocation; /* Taille allouée */ - - /* Pour les cas simple, GTK gère très bien... */ - if (node->simple) return; - - get_panel_node_size_request(node->first, &first_req); - get_panel_node_size_request(node->second, &second_req); - gtk_widget_style_get(node->paned, "handle-size", &handle_size, NULL); - /** - * Définitions des bornes dans chacun des cas. - */ + fprintf(stderr, "Passage avec %p\n", _nodes); - main_node = find_main_panel_node_branch(node->first, node->second); - - /* Le premier noeud est le principal... */ - if (node->first == main_node) + return; + void store_handle_position(panel_node *node, GGenConfig *config) { - if (HAS_H_ORIENTATION(node->paned)) - position = (space->width * MAIN_PART_PERCENT) / 100; - else - position = (space->height * MAIN_PART_PERCENT) / 100; - can_lower = false; - can_upper = true; + size_t i; - } + for (i = 0; i < 0/*node->depth*/; i++) + fprintf(stderr, " "); - /* Le second noeud est le principal... */ - else if (node->second == main_node) - { - if (HAS_H_ORIENTATION(node->paned)) - position = space->width - (space->width * MAIN_PART_PERCENT) / 100; - else - position = space->height - (space->height * MAIN_PART_PERCENT) / 100; - can_lower = true; - can_upper = false; + ///fprintf(stderr, "[%s] %s\n", node->path, node->simple ? "[+]" : ">>"); - } - /* Les éléments sont quelconques... */ - else - { - if (HAS_H_ORIENTATION(node->paned)) - position = space->width / 2; - else - position = space->height / 2; - - can_lower = true; - can_upper = true; - - } - - /** - * Calcul des valeurs applicables et mise en application. - */ - - /* Correctifs éventuels pour les petits composants */ - if (node->first == main_node) - { - if (HAS_H_ORIENTATION(node->paned)) - second_req.width = MAX(second_req.width, (space->width * MIN_PART_PERCENT) / 100); - else - second_req.height = MAX(second_req.height, (space->height * MIN_PART_PERCENT) / 100); - } - else if (node->second == main_node) - { - if (HAS_H_ORIENTATION(node->paned)) - first_req.width = MAX(first_req.width, (space->width * MIN_PART_PERCENT) / 100); - else - first_req.height = MAX(first_req.height, (space->height * MIN_PART_PERCENT) / 100); - } + if (0/*!node->simple*/) + { + store_handle_position(node->first, config); + store_handle_position(node->second, config); + } - /* Une partie principale arrive en premier */ - if (!can_lower && can_upper) - { - if (HAS_H_ORIENTATION(node->paned)) - position = MAX(position, space->width - second_req.width - handle_size); - else - position = MAX(position, space->height - second_req.height - handle_size); - } - /* Une partie principale arrive en second */ - else if (can_lower && !can_upper) - { - if (HAS_H_ORIENTATION(node->paned)) - position = MIN(position, second_req.width + handle_size); - else - position = MIN(position, second_req.height + handle_size); } - /* Chacun pour soit ! */ - else - { + //get_main_configuration() - /* TODO */; + store_handle_position(_nodes, NULL); + fflush(NULL); - } - gtk_paned_set_position(GTK_PANED(node->paned), position); +} - gtk_widget_get_allocation(GET_PANEL_NODE_WIDGET(node->first), &allocation); - set_panel_node_size_request(node->first, ALLOC_2_REQ(&allocation)); +#endif - gtk_widget_get_allocation(GET_PANEL_NODE_WIDGET(node->second), &allocation); - set_panel_node_size_request(node->second, ALLOC_2_REQ(&allocation)); -} diff --git a/src/gui/panels/panel.h b/src/gui/panels/panel.h index 0bf5cb5..baf5fe7 100644 --- a/src/gui/panels/panel.h +++ b/src/gui/panels/panel.h @@ -26,6 +26,9 @@ #define _GUI_PANELS_PANEL_H +#include + + #include "../editem.h" @@ -45,11 +48,31 @@ typedef struct _GPanelItem GPanelItem; typedef struct _GPanelItemClass GPanelItemClass; +/* Types de panneaux pour éditeur */ +typedef enum _PanelItemPersonality +{ + PIP_INVALID, /* Information non initialisée */ + + PIP_SINGLETON, /* Instance unique */ + PIP_BINARY_VIEW, /* Affichage d'un binaire */ + PIP_OTHER, /* Reste du monde */ + + PIP_COUNT + +} PanelItemPersonality; + + /* Indique le type défini pour un élément destiné à un panneau. */ GType g_panel_item_get_type(void); /* Crée un élément de panneau réactif. */ -GEditorItem *g_panel_item_new(GObject *, const char *, const char *, GtkWidget *, const char *); +GEditorItem *g_panel_item_new(PanelItemPersonality, GObject *, const char *, const char *, GtkWidget *, const char *); + +/* Fournit une indication sur la personnalité du panneau. */ +PanelItemPersonality gtk_panel_item_get_personality(const GPanelItem *); + +/* Indique la définition d'un éventuel raccourci clavier. */ +const char *gtk_panel_item_get_key_bindings(const GPanelItem *); /* Recherche un panneau à partir de son nom court. */ GPanelItem *g_panel_item_get(const char *); @@ -57,11 +80,25 @@ GPanelItem *g_panel_item_get(const char *); /* Place un panneau dans l'ensemble affiché. */ void g_panel_item_dock(GPanelItem *); +/* Indique si le composant repose sur un support de l'éditeur. */ +bool g_panel_item_is_docked(const GPanelItem *); + /* Supprime un panneau de l'ensemble affiché. */ void g_panel_item_undock(GPanelItem *); + + + + +void save_panel_nodes(void); + + + + + + /* ----------------------- PLACEMENTS DES DIFFERENTS PANNEAUX ----------------------- */ @@ -72,5 +109,12 @@ GtkWidget *init_panels2(GCallback, gpointer); void load_main_panels(GObject *); +/* Réalise un traitement sur un panneau de l'éditeur. */ +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 *); + + #endif /* _GUI_PANELS_PANEL_H */ diff --git a/src/gui/panels/regedit.c b/src/gui/panels/regedit.c index a187a2d..cb4fe85 100644 --- a/src/gui/panels/regedit.c +++ b/src/gui/panels/regedit.c @@ -204,6 +204,7 @@ static void g_regedit_panel_class_init(GRegeditPanelClass *klass) static void g_regedit_panel_init(GRegeditPanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GObject *ref; /* Espace de référencement */ GtkWidget *label; /* Etiquette à utiliser */ GtkWidget *search; /* Zone de recherche */ @@ -224,6 +225,10 @@ static void g_regedit_panel_init(GRegeditPanel *panel) ref = G_OBJECT(base->widget); g_object_set_data(ref, "panel", panel); + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + /* Partie recherche */ label = qck_create_label(NULL, NULL, _("Look for:")); @@ -386,7 +391,7 @@ GEditorItem *g_regedit_panel_new(GObject *ref) result = g_object_new(G_TYPE_REGEDIT_PANEL, NULL); g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_REGEDIT_ID, - _("Configuration parameters"), G_EDITOR_ITEM(result)->widget, "M"); + _("Configuration parameters"), G_EDITOR_ITEM(result)->widget, "N"); reload_config_into_treeview(G_REGEDIT_PANEL(result), get_main_configuration()); diff --git a/src/gui/panels/strings.c b/src/gui/panels/strings.c index abbf7ed..9759e71 100644 --- a/src/gui/panels/strings.c +++ b/src/gui/panels/strings.c @@ -179,6 +179,7 @@ static void g_strings_panel_class_init(GStringsPanelClass *klass) { GObjectClass *object; /* Autre version de la classe */ GEditorItemClass *editem; /* Encore une autre vision... */ + GPanelItemClass *panel; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); @@ -189,6 +190,11 @@ static void g_strings_panel_class_init(GStringsPanelClass *klass) editem->update_binary = (update_item_binary_fc)change_strings_panel_current_binary; + panel = G_PANEL_ITEM_CLASS(klass); + + panel->unique = true; + panel->bindings = "F12"; + } @@ -207,6 +213,7 @@ static void g_strings_panel_class_init(GStringsPanelClass *klass) static void g_strings_panel_init(GStringsPanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GObject *ref; /* Espace de référencement */ GtkTreeStore *store; /* Modèle de gestion */ GtkWidget *treeview; /* Affichage de la liste */ @@ -227,6 +234,10 @@ static void g_strings_panel_init(GStringsPanel *panel) ref = G_OBJECT(base->widget); g_object_set_data(ref, "panel", panel); + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + /* Partie chaînes */ store = gtk_tree_store_new(STC_COUNT, G_TYPE_OBJECT, diff --git a/src/gui/panels/symbols.c b/src/gui/panels/symbols.c index 2a9d612..eebfc4c 100644 --- a/src/gui/panels/symbols.c +++ b/src/gui/panels/symbols.c @@ -181,6 +181,7 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass) GObjectClass *object; /* Autre version de la classe */ GEditorItemClass *editem; /* Encore une autre vision... */ gchar *filename; /* Chemin d'accès à utiliser */ + GPanelItemClass *panel; /* Version parente de la classe*/ object = G_OBJECT_CLASS(klass); @@ -212,6 +213,11 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass) g_free(filename); + panel = G_PANEL_ITEM_CLASS(klass); + + panel->unique = true; + panel->bindings = "F3"; + } @@ -230,6 +236,7 @@ static void g_symbols_panel_class_init(GSymbolsPanelClass *klass) static void g_symbols_panel_init(GSymbolsPanel *panel) { GEditorItem *base; /* Version basique d'instance */ + GPanelItem *pitem; /* Version parente du panneau */ GObject *ref; /* Espace de référencement */ GtkWidget *box; /* Séparation horizontale */ GtkWidget *toolbar; /* Barre d'outils */ @@ -250,6 +257,10 @@ static void g_symbols_panel_init(GSymbolsPanel *panel) ref = G_OBJECT(base->widget); g_object_set_data(ref, "panel", panel); + pitem = G_PANEL_ITEM(panel); + + pitem->personality = PIP_SINGLETON; + /* Barre d'outils supérieure */ box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); @@ -435,7 +446,7 @@ GEditorItem *g_symbols_panel_new(GObject *ref) result = g_object_new(G_TYPE_SYMBOLS_PANEL, NULL); g_panel_item_init_ext(G_PANEL_ITEM(result), ref, PANEL_SYMBOLS_ID, - _("Binary symbols"), G_EDITOR_ITEM(result)->widget, "eM"); + _("Binary symbols"), G_EDITOR_ITEM(result)->widget, "eN"); return result; -- cgit v0.11.2-87-g4458