From 491e9837f33831f94747a6063f709ba2c5d2703e Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 12 Mar 2016 00:55:50 +0100 Subject: Handled user actions on the dock station buttons. --- ChangeLog | 15 +++ src/gtkext/easygtk.c | 77 ++++++++++++ src/gtkext/easygtk.h | 3 + src/gtkext/gtkdockstation.c | 65 +++++++++- src/gtkext/gtkdockstation.h | 3 + src/gui/editor.c | 292 +++++++++++++++++++++++++++++++------------- src/gui/panels/panel.c | 39 ++++++ src/gui/panels/panel.h | 3 + 8 files changed, 409 insertions(+), 88 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8fed981..26b669b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +16-03-12 Cyrille Bagard + + * src/gtkext/easygtk.c: + * src/gtkext/easygtk.h: + Compute the coordinates of a popup menu attached to a given widget. + + * src/gtkext/gtkdockstation.c: + * src/gtkext/gtkdockstation.h: + * src/gui/editor.c: + Handle user actions on the dock station buttons. + + * src/gui/panels/panel.c: + * src/gui/panels/panel.h: + Set and store new panel attributes in the global configuration. + 16-03-09 Cyrille Bagard * plugins/pychrysa/gui/panels/panel.c: diff --git a/src/gtkext/easygtk.c b/src/gtkext/easygtk.c index 3ba6664..7db1bfc 100644 --- a/src/gtkext/easygtk.c +++ b/src/gtkext/easygtk.c @@ -1148,3 +1148,80 @@ gint qck_show_question(GtkWindow *parent, const char *title, const char *questio return result; } + + +/****************************************************************************** +* * +* Paramètres : menu = menu GTK à placer à l'écran. * +* x = abscisse absolue du coin supérieur du menu. [OUT] * +* y = ordonnée absolue du coin supérieur du menu. [OUT] * +* push = indique les relations avec les bordures. [OUT] * +* widget = composant auquel le menu doit être attaché. * +* * +* Description : Détermine la position d'un menu associé à un composant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void attach_popup_menu_to_widget(GtkMenu *menu, gint *x, gint *y, gboolean *push, GtkWidget *widget) +{ + GtkTextDirection dir; /* Direction de l'affichage */ + GtkAllocation alloc; /* Emplacement alloué */ + GtkStyleContext *context; /* Style associé pour le rendu */ + GtkStateFlags state; /* Etat courant du composant */ + GtkBorder border; /* Bordure #1 à considérer */ + GtkBorder padding; /* Bordure #2 à considérer */ + GtkRequisition req; /* Taille requis */ + + *x = 0; + *y = 0; + + dir = gtk_widget_get_direction(widget); + + /* Emplacement du composant */ + + gtk_widget_get_allocation(widget, &alloc); + + if (!gtk_widget_get_has_window(widget)) + { + *x += alloc.x; + *y += alloc.y; + } + + gdk_window_get_root_coords(gtk_widget_get_window(widget), *x, *y, x, y); + + /* Extension supplémentaire */ + + context = gtk_widget_get_style_context(widget); + state = gtk_style_context_get_state(context); + + gtk_style_context_get_border(context, state, &border); + gtk_style_context_get_padding(context, state, &padding); + + if (dir == GTK_TEXT_DIR_RTL) + *x += border.left + padding.left; + else + *x -= (border.left + padding.left); + + *y += border.top + padding.top; + + /* Sens de lecture */ + + if (dir == GTK_TEXT_DIR_RTL) + { + gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &req); + + *x += alloc.width - req.width; + + } + + /* Finalisation... */ + + *y += alloc.height; + + *push = TRUE; + +} diff --git a/src/gtkext/easygtk.h b/src/gtkext/easygtk.h index 02f2f18..ead9822 100644 --- a/src/gtkext/easygtk.h +++ b/src/gtkext/easygtk.h @@ -124,6 +124,9 @@ GtkWidget *qck_create_tool_separator(GObject *, const char *); /* Affiche une boîte de dialogue offrant un choix "Oui/Non". */ gint qck_show_question(GtkWindow *, const char *, const char *); +/* Détermine la position d'un menu associé à un composant. */ +void attach_popup_menu_to_widget(GtkMenu *, gint *, gint *, gboolean *, GtkWidget *); + #endif /* _EASYGTK_H */ diff --git a/src/gtkext/gtkdockstation.c b/src/gtkext/gtkdockstation.c index 35006ef..1672d5e 100644 --- a/src/gtkext/gtkdockstation.c +++ b/src/gtkext/gtkdockstation.c @@ -50,6 +50,11 @@ static gboolean gtk_dock_station_switch_panel(GtkNotebook *, gpointer *, guint, /* Révèle ou cache la zone de recherches. */ static void on_toggle_revealer(GtkToggleButton *, GtkDockStation *); +/* Demande l'apparition d'un menu pour inclure des composants. */ +static void on_click_for_menu(GtkButton *, GtkDockStation *); + +/* Demande la disparition du composant courant. */ +static void on_click_for_close(GtkButton *, GtkDockStation *); @@ -98,6 +103,22 @@ static void gtk_dock_station_class_init(GtkDockStationClass *class) g_cclosure_user_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_WIDGET); + g_signal_new("menu-requested", + GTK_TYPE_DOCK_STATION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkDockStationClass, menu_requested), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_WIDGET); + + g_signal_new("close-requested", + GTK_TYPE_DOCK_STATION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GtkDockStationClass, close_requested), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, GTK_TYPE_WIDGET); + } @@ -139,13 +160,13 @@ static void gtk_dock_station_init(GtkDockStation *station) button = qck_create_button_with_named_img(G_OBJECT(station), "menu", "go-down-symbolic", GTK_ICON_SIZE_MENU, NULL, - G_CALLBACK(NULL), station); + G_CALLBACK(on_click_for_menu), station); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); button = qck_create_button_with_named_img(G_OBJECT(station), "close", "window-close-symbolic", GTK_ICON_SIZE_MENU, NULL, - G_CALLBACK(NULL), station); + G_CALLBACK(on_click_for_close), station); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); @@ -470,3 +491,43 @@ static void on_toggle_revealer(GtkToggleButton *button, GtkDockStation *station) gtk_dockable_toggle_revealer(dockable, widget, gtk_toggle_button_get_active(button)); } + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* station = station d'accueil pour différents composants. * +* * +* Description : Demande l'apparition d'un menu pour inclure des composants. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_click_for_menu(GtkButton *button, GtkDockStation *station) +{ + g_signal_emit_by_name(station, "menu-requested", button); + +} + + +/****************************************************************************** +* * +* Paramètres : button = bouton à l'origine de la procédure. * +* station = station d'accueil pour différents composants. * +* * +* Description : Demande la disparition du composant courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_click_for_close(GtkButton *button, GtkDockStation *station) +{ + g_signal_emit_by_name(station, "close-requested", button); + +} diff --git a/src/gtkext/gtkdockstation.h b/src/gtkext/gtkdockstation.h index 953ceb8..82b41c6 100644 --- a/src/gtkext/gtkdockstation.h +++ b/src/gtkext/gtkdockstation.h @@ -67,6 +67,9 @@ struct _GtkDockStationClass void (* switch_widget) (GtkDockStation *, GtkWidget *); + void (* menu_requested) (GtkDockStation *, GtkWidget *); + void (* close_requested) (GtkDockStation *, GtkWidget *); + }; diff --git a/src/gui/editor.c b/src/gui/editor.c index fdf253f..e5ec4d7 100644 --- a/src/gui/editor.c +++ b/src/gui/editor.c @@ -27,6 +27,8 @@ #include #include +#include +#include #include @@ -35,6 +37,7 @@ #include "status.h" #include "menus/menubar.h" #include "core/core.h" +#include "core/panels.h" #include "panels/panel.h" #include "tb/portions.h" #include "tb/source.h" @@ -50,6 +53,13 @@ + + +/* Gestion des raccourcis clavier */ +static GtkAccelGroup *_accgroup = NULL; + + + /* Met en place la liste des icônes de l'éditeur. */ static GList *build_editor_icons_list(void); @@ -68,10 +78,6 @@ static void on_destroy_editor(GtkWidget *, gpointer); -/* Réagit au changement d'onglet d'un panneau quelconque. */ -static void on_dock_item_switch(GtkDockStation *, GtkWidget *, GObject *); - - @@ -172,6 +178,17 @@ void on_panel_item_dock_request(GPanelItem *, void *); /* Réagit à une demande de suppression d'un panneau d'affichage. */ void on_panel_item_undock_request(GPanelItem *, void *); +/* Réagit au changement d'onglet d'un panneau quelconque. */ +static void on_dock_item_switch(GtkDockStation *, GtkWidget *, GObject *); + +/* Réagit à une demande de menu pour rajouter des panneaux. */ +static void on_dock_menu_request(GtkDockStation *, GtkWidget *, GObject *); + +/* Réagit à une demande de fermeture du panneau courant. */ +static void on_dock_close_request(GtkDockStation *, GtkWidget *, GObject *); + + + @@ -239,8 +256,6 @@ GtkWidget *create_editor(void) GtkWidget *vbox1; - GtkAccelGroup *accgroup; - GtkWidget *widget; /* Composant à intégrer */ @@ -268,8 +283,8 @@ GtkWidget *create_editor(void) ref = G_OBJECT(result); - accgroup = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(result), accgroup); + _accgroup = gtk_accel_group_new(); + gtk_window_add_accel_group(GTK_WINDOW(result), _accgroup); @@ -280,7 +295,7 @@ GtkWidget *create_editor(void) /* Intégration des menus */ - editem = g_menu_bar_new(ref, accgroup); + editem = g_menu_bar_new(ref, _accgroup); register_editor_item(editem); menuboard = g_editor_item_get_widget(editem); @@ -436,83 +451,6 @@ static void on_destroy_editor(GtkWidget *widget, gpointer data) - - - - - - - - - - - - - - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : station = panneau de support des éléments concerné. * -* item = nouvel élément présenté à l'affichage. * -* ref = adresse de l'espace de référencement global. * -* * -* Description : Réagit au changement d'onglet d'un panneau quelconque. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void on_dock_item_switch(GtkDockStation *station, GtkWidget *widget, GObject *ref) -{ - GLoadedBinary *old_binary; /* Ancien binaire édité */ - GLoadedBinary *binary; /* Binaire en cours d'édition */ - - if (GTK_IS_SCROLLED_WINDOW(widget)) - widget = gtk_bin_get_child(GTK_BIN(widget)); - - if (GTK_IS_VIEWPORT(widget)) - widget = gtk_bin_get_child(GTK_BIN(widget)); - - if (GTK_IS_VIEW_PANEL(widget)) - { - /* Changement de binaire ? */ - - old_binary = G_LOADED_BINARY(g_object_get_data(ref, "current_binary")); - binary = gtk_view_panel_get_binary(GTK_VIEW_PANEL(widget)); - - if (old_binary != binary) - { - //notify_panels_of_binary_change(binary); - change_editor_items_current_binary(ref, binary); - } - - change_editor_items_current_view(ref, GTK_VIEW_PANEL(widget)); - - //notify_panels_of_view_change(GTK_VIEW_PANEL(widget), false); - - } - -} - - - - - - - - - - /* ---------------------------------------------------------------------------------- */ /* INTEGRATION DE LA BARRE D'OUTILS */ /* ---------------------------------------------------------------------------------- */ @@ -595,6 +533,8 @@ static panel_node *create_simple_panel_node_for_item(GPanelItem *item, const cha station = gtk_dock_station_new(); g_signal_connect(station, "switch-widget", G_CALLBACK(on_dock_item_switch), _global_ref); + g_signal_connect(station, "menu-requested", G_CALLBACK(on_dock_menu_request), _global_ref); + g_signal_connect(station, "close-requested", G_CALLBACK(on_dock_close_request), _global_ref); gtk_widget_show(station); gtk_dock_station_add_dockable(GTK_DOCK_STATION(station), GTK_DOCKABLE(item)); @@ -1220,3 +1160,183 @@ void on_panel_item_undock_request(GPanelItem *item, void *unused) g_panel_item_set_dock_status(item, false); } + + +/****************************************************************************** +* * +* Paramètres : station = panneau de support des éléments concerné. * +* item = nouvel élément présenté à l'affichage. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Réagit au changement d'onglet d'un panneau quelconque. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_dock_item_switch(GtkDockStation *station, GtkWidget *widget, GObject *ref) +{ + GLoadedBinary *old_binary; /* Ancien binaire édité */ + GLoadedBinary *binary; /* Binaire en cours d'édition */ + + if (GTK_IS_SCROLLED_WINDOW(widget)) + widget = gtk_bin_get_child(GTK_BIN(widget)); + + if (GTK_IS_VIEWPORT(widget)) + widget = gtk_bin_get_child(GTK_BIN(widget)); + + if (GTK_IS_VIEW_PANEL(widget)) + { + /* Changement de binaire ? */ + + old_binary = G_LOADED_BINARY(g_object_get_data(ref, "current_binary")); + binary = gtk_view_panel_get_binary(GTK_VIEW_PANEL(widget)); + + if (old_binary != binary) + { + //notify_panels_of_binary_change(binary); + change_editor_items_current_binary(ref, binary); + } + + change_editor_items_current_view(ref, GTK_VIEW_PANEL(widget)); + + //notify_panels_of_view_change(GTK_VIEW_PANEL(widget), false); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : station = panneau de support des éléments concerné. * +* button = bouton à l'origine de la procédure. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Réagit à une demande de menu pour rajouter des panneaux. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_dock_menu_request(GtkDockStation *station, GtkWidget *button, GObject *ref) +{ + GtkWidget *active; /* Composant actif modèle */ + GPanelItem *model; /* Panneau encapsulé */ + GtkContainer *menu; /* Support à retourner */ + GList *children; /* Composants mis en place */ + GtkWidget *nopanel; /* Sous-élément de menu */ + + menu = GTK_CONTAINER(gtk_menu_new()); + + active = gtk_notebook_get_nth_page(GTK_NOTEBOOK(station), 0); + + model = G_PANEL_ITEM(g_object_get_data(G_OBJECT(active), "dockable")); + + g_object_set_data_full(G_OBJECT(menu), "path", strdup(gtk_panel_item_get_path(model)), free); + + /* Ajout des panneaux uniques */ + + void dock_panel_into_current_station(GtkCheckMenuItem *menuitem, GPanelItem *item) + { + GtkWidget *parent; /* Menu parent avec chemin */ + const char *new_path; /* Nouveau chemin à appliquer */ + + parent = gtk_widget_get_parent(GTK_WIDGET(menuitem)); + + new_path = g_object_get_data(G_OBJECT(parent), "path"); + + gtk_panel_item_set_path(item, new_path); + + g_panel_item_dock(item); + + } + + bool add_side_panel_to_menu(GPanelItem *panel, GtkContainer *support) + { + const char *name; /* Désignation de l'entrée */ + GtkWidget *submenuitem; /* Sous-élément de menu */ + const char *bindings; /* Raccourcis clavier bruts */ + + /* Profil qui ne cadre pas ? */ + + if (gtk_panel_item_get_personality(panel) != PIP_SINGLETON) + goto aptm_exit; + + if (g_panel_item_is_docked(panel)) + goto aptm_exit; + + /* Elément de menu */ + + name = g_editor_item_get_name(G_EDITOR_ITEM(panel)); + + submenuitem = qck_create_menu_item(NULL, NULL, name, + G_CALLBACK(dock_panel_into_current_station), panel); + + bindings = gtk_panel_item_get_key_bindings(panel); + + if (bindings != NULL) + add_accelerator_to_menu_item(submenuitem, bindings, _accgroup); + + gtk_container_add(support, submenuitem); + + aptm_exit: + + return true; + + } + + browse_all_item_panels((handle_panel_item_fc)add_side_panel_to_menu, menu); + + /* Avertissement en cas d'indisponibilité */ + + children = gtk_container_get_children(GTK_CONTAINER(menu)); + + if (children == NULL) + { + nopanel = qck_create_menu_item(NULL, NULL, "No available free panel", NULL, NULL); + gtk_widget_set_sensitive(nopanel, FALSE); + gtk_container_add(GTK_CONTAINER(menu), nopanel); + } + else + g_list_free(children); + + /* Affichage du menu */ + + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + (GtkMenuPositionFunc)attach_popup_menu_to_widget, button, + 0, gtk_get_current_event_time()); + +} + + +/****************************************************************************** +* * +* Paramètres : station = panneau de support des éléments concerné. * +* button = bouton à l'origine de la procédure. * +* ref = adresse de l'espace de référencement global. * +* * +* Description : Réagit à une demande de fermeture du panneau courant. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void on_dock_close_request(GtkDockStation *station, GtkWidget *button, GObject *ref) +{ + GtkWidget *active; /* Composant actif modèle */ + GPanelItem *panel; /* Panneau encapsulé */ + + active = gtk_notebook_get_nth_page(GTK_NOTEBOOK(station), 0); + + panel = G_PANEL_ITEM(g_object_get_data(G_OBJECT(active), "dockable")); + + g_panel_item_undock(panel); + +} diff --git a/src/gui/panels/panel.c b/src/gui/panels/panel.c index 71fa155..ee0c102 100644 --- a/src/gui/panels/panel.c +++ b/src/gui/panels/panel.c @@ -31,6 +31,7 @@ #include "panel-int.h" #include "../../common/extstr.h" +#include "../../core/params.h" #include "../../gtkext/gtkdockable-int.h" @@ -406,6 +407,35 @@ const char *gtk_panel_item_get_path(const GPanelItem *item) } +/****************************************************************************** +* * +* Paramètres : item = instance GTK à consulter. * +* path = nouvelle emplacement d'inclusion. * +* * +* Description : Définit le chemin d'accès à utiliser pour les encapsulations.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_panel_item_set_path(GPanelItem *item, const char *path) +{ + char *key; /* Clef d'accès à un paramètre */ + + free(item->path); + + item->path = strdup(path); + + key = gtk_panel_item_build_configuration_key(item, "path"); + + g_generic_config_set_value(get_main_configuration(), key, item->path); + + free(key); + +} + /****************************************************************************** * * @@ -462,7 +492,16 @@ void g_panel_item_dock(GPanelItem *item) void g_panel_item_set_dock_status(GPanelItem *item, bool status) { + char *key; /* Clef d'accès à un paramètre */ + item->docked = status; + item->dock_at_startup = status; + + key = gtk_panel_item_build_configuration_key(item, "dock_at_startup"); + + g_generic_config_set_value(get_main_configuration(), key, item->dock_at_startup); + + free(key); } diff --git a/src/gui/panels/panel.h b/src/gui/panels/panel.h index cbe9030..cb716f8 100644 --- a/src/gui/panels/panel.h +++ b/src/gui/panels/panel.h @@ -81,6 +81,9 @@ PanelItemPersonality gtk_panel_item_get_personality(const GPanelItem *); /* Fournit le chemin d'accès à utiliser pour les encapsulations. */ const char *gtk_panel_item_get_path(const GPanelItem *); +/* Définit le chemin d'accès à utiliser pour les encapsulations. */ +void gtk_panel_item_set_path(GPanelItem *, const char *); + /* Indique la définition d'un éventuel raccourci clavier. */ const char *gtk_panel_item_get_key_bindings(const GPanelItem *); -- cgit v0.11.2-87-g4458