diff options
Diffstat (limited to 'src/gui/window.c')
-rw-r--r-- | src/gui/window.c | 621 |
1 files changed, 621 insertions, 0 deletions
diff --git a/src/gui/window.c b/src/gui/window.c new file mode 100644 index 0000000..e14ecf7 --- /dev/null +++ b/src/gui/window.c @@ -0,0 +1,621 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * window.c - construction d'une fenêtre graphique principale + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "window.h" + + +#include "window-int.h" +#include "core/panels.h" +#include "dialogs/about.h" +#include "dialogs/preferences.h" +#include "panels/logs.h" +#include "panels/welcome.h" +#include "../gtkext/grid.h" +#include "../gtkext/helpers.h" + + + +/* Initialise la classe des applications majeures de Chrysalide. */ +static void gtk_framework_window_class_init(GtkFrameworkWindowClass *); + +/* Initialise une application principale pour Chrysalide. */ +static void gtk_framework_window_init(GtkFrameworkWindow *); + +/* Supprime toutes les références externes. */ +static void gtk_framework_window_dispose(GObject *); + +/* Procède à la libération totale de la mémoire. */ +static void gtk_framework_window_finalize(GObject *); + +/* Bascule l'affichage d'un panneau de bordure. */ +static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *, TilingGridBorder); + +/* Réagit à une activation de bascule du panneau supérieur. */ +static void gtk_framework_window_activate_toggle_top(GSimpleAction *, GVariant *, gpointer); + +/* Réagit à une activation de bascule du panneau de gauche. */ +static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *, gpointer); + +/* Réagit à une activation de bascule du panneau de droite. */ +static void gtk_framework_window_activate_toggle_right(GSimpleAction *, GVariant *, gpointer); + +/* Réagit à une activation de bascule du panneau inférieur. */ +static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *, GVariant *, gpointer); + +/* Réagit à une activation du menu "Préférences" de la fenetre. */ +static void gtk_framework_window_activate_preferences(GSimpleAction *, GVariant *, gpointer); + +/* Réagit à une activation du menu "A propos de" de la fenetre. */ +static void gtk_framework_window_activate_about(GSimpleAction *, GVariant *, gpointer); + + + +/* Indique le type défini pour une fenêtre graphique principale de Chrysalide. */ +G_DEFINE_TYPE(GtkFrameworkWindow, gtk_framework_window, GTK_TYPE_APPLICATION_WINDOW); + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* * +* Description : Initialise la classe des applications majeures de Chrysalide.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_class_init(GtkFrameworkWindowClass *class) +{ + GObjectClass *object; /* Plus haut niveau équivalent */ + GtkWidgetClass *widget; /* Classe de haut niveau */ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)gtk_framework_window_dispose; + object->finalize = (GObjectFinalizeFunc)gtk_framework_window_finalize; + + widget = GTK_WIDGET_CLASS(class); + + g_type_ensure(GTK_TYPE_TILING_GRID); + g_type_ensure(GTK_TYPE_STATUS_STACK); + + gtk_widget_class_set_template_from_resource(widget, "/re/chrysalide/framework/gui/window.ui"); + + gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, grid); + gtk_widget_class_bind_template_child(widget, GtkFrameworkWindow, status); + + /* Active une action native (cf. https://docs.gtk.org/gtk4/class.Window.html#actions) */ + gtk_widget_class_add_binding_action(widget, GDK_KEY_Q, GDK_CONTROL_MASK, "window.close", NULL); + + gtk_widget_class_add_binding_action(widget, GDK_KEY_comma, GDK_CONTROL_MASK, "win.preferences", NULL); + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance à initialiser. * +* * +* Description : Initialise une application principale pour Chrysalide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_init(GtkFrameworkWindow *window) +{ + GAction *action; /* Action mise en place */ + + static GActionEntry app_entries[] = { + { "toggle-top", gtk_framework_window_activate_toggle_top, NULL, NULL, NULL }, + { "toggle-left", gtk_framework_window_activate_toggle_left, NULL, NULL, NULL }, + { "toggle-right", gtk_framework_window_activate_toggle_right, NULL, NULL, NULL }, + { "toggle-bottom", gtk_framework_window_activate_toggle_bottom, NULL, NULL, NULL }, + { "preferences", gtk_framework_window_activate_preferences, NULL, NULL, NULL }, + { "about", gtk_framework_window_activate_about, NULL, NULL, NULL }, + }; + + gtk_widget_init_template(GTK_WIDGET(window)); + + window->settings = g_settings_new(FRAMEWORK_WINDOW_ID); + + g_settings_bind(window->settings, "window-width", G_OBJECT(window), "default-width", G_SETTINGS_BIND_DEFAULT); + g_settings_bind(window->settings, "window-height", G_OBJECT(window), "default-height", G_SETTINGS_BIND_DEFAULT); + g_settings_bind(window->settings, "window-maximized", G_OBJECT(window), "maximized", G_SETTINGS_BIND_DEFAULT); + + window->main = NULL; + + g_action_map_add_action_entries(G_ACTION_MAP(window), + app_entries, G_N_ELEMENTS(app_entries), + window); + + /** + * Définition de l'accès aux actions pour obtenir un effet de bord sur + * l'accès aux boutons graphiques de déclenchement. + */ + + action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-top"); + + g_object_bind_property(G_OBJECT(window->grid), "empty-top", + G_OBJECT(action), "enabled", + G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); + + action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-left"); + + g_object_bind_property(G_OBJECT(window->grid), "empty-left", + G_OBJECT(action), "enabled", + G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); + + action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-right"); + + g_object_bind_property(G_OBJECT(window->grid), "empty-right", + G_OBJECT(action), "enabled", + G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); + + action = g_action_map_lookup_action(G_ACTION_MAP(window), "toggle-bottom"); + + g_object_bind_property(G_OBJECT(window->grid), "empty-bottom", + G_OBJECT(action), "enabled", + G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); + +} + + +/****************************************************************************** +* * +* Paramètres : object = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_dispose(GObject *object) +{ + GtkFrameworkWindow *window; /* Version spécialisée */ + + window = GTK_FRAMEWORK_WINDOW(object); + + gtk_widget_dispose_template(GTK_WIDGET(window), GTK_TYPE_FRAMEWORK_WINDOW); + + g_clear_object(&window->settings); + + g_clear_object(&window->main); + + G_OBJECT_CLASS(gtk_framework_window_parent_class)->dispose(object); + +} + + +/****************************************************************************** +* * +* Paramètres : object = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_finalize(GObject *object) +{ + G_OBJECT_CLASS(gtk_framework_window_parent_class)->finalize(object); + +} + + +/****************************************************************************** +* * +* Paramètres : app = application GTK de rattachement. * +* * +* Description : Crée une nouvelle application principale pour Chrysalide. * +* * +* Retour : Mécanismes mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkApplicationWindow *gtk_framework_window_new(GtkApplication *app) +{ + GtkApplicationWindow *result; /* Instance à retourner */ + + result = g_object_new(GTK_TYPE_FRAMEWORK_WINDOW, NULL); + + if (!gtk_framework_window_create(GTK_FRAMEWORK_WINDOW(result), app)) + g_clear_object(&result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à remplir. * +* app = application GTK de rattachement. * +* * +* Description : Met en place une fenêtre principale pour Chrysalide. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool gtk_framework_window_create(GtkFrameworkWindow *window, GtkApplication *app) +{ + bool result; /* Bilan à retourner */ + GtkTiledPanel *panel; /* Panneau d'affichage */ + GtkCssProvider *css; /* Feuille de style maison */ + + result = true; + + gtk_window_set_application(GTK_WINDOW(window), app); + + /* Inclusion d'un écran d'accueil */ + + panel = get_framework_panel_singleton(GTK_TYPE_WELCOME_PANEL); + + gtk_framework_window_add(window, panel); + + if (1/* FIXME : first time */) + { + panel = get_framework_panel_singleton(GTK_TYPE_LOGS_PANEL); + + gtk_framework_window_add(window, panel); + + } + + /* Chargement des extensions de thème */ + + css = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gtkext/hexview.css"); + + gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)), + GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + unref_object(css); + + css = gtk_css_provider_new(); + + gtk_css_provider_load_from_resource(css, "/re/chrysalide/framework/gui/style.css"); + + gtk_style_context_add_provider_for_display(gtk_widget_get_display(GTK_WIDGET(window)), + GTK_STYLE_PROVIDER(css), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + + unref_object(css); + + /* Fin des chargements */ + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à manipuler. * +* border = sélection de la zone à considérer. * +* * +* Description : Bascule l'affichage d'un panneau de bordure. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_toggle_pannel_visibility(GtkFrameworkWindow *window, TilingGridBorder border) +{ + bool state; /* Etat courant à basculer */ + + state = gtk_tiling_grid_get_visible(window->grid, border); + + state = !state; + + gtk_tiling_grid_set_visible(window->grid, border, state); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation de bascule du panneau supérieur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_toggle_top(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + gtk_framework_window_toggle_pannel_visibility(_window, TGB_TOP); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation de bascule du panneau de gauche. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_toggle_left(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + gtk_framework_window_toggle_pannel_visibility(_window, TGB_LEFT); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation de bascule du panneau de droite. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_toggle_right(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + gtk_framework_window_toggle_pannel_visibility(_window, TGB_RIGHT); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation de bascule du panneau inférieur. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_toggle_bottom(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + gtk_framework_window_toggle_pannel_visibility(_window, TGB_BOTTOM); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation du menu "Préférences" de la fenetre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_preferences(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + GtkFrameworkWindow *window; /* Fenêtre principale associée */ + GtkWindow *dialog; /* Boîte de dialogue à afficher*/ + + window = _window; + + dialog = gtk_preferences_dialog_new(GTK_WINDOW(window)); + + gtk_window_present(dialog); + +} + + +/****************************************************************************** +* * +* Paramètres : action = désignation de l'action concernée par l'appel. * +* unused = adresse non utilisée ici. * +* _window = instance de fenêtre principale à manipuler. * +* * +* Description : Réagit à une activation du menu "A propos de" de la fenetre. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void gtk_framework_window_activate_about(GSimpleAction *action, GVariant *unused, gpointer _window) +{ + GtkFrameworkWindow *window; /* Fenêtre principale associée */ + GtkWindow *dialog; /* Boîte de dialogue à afficher*/ + + window = _window; + + dialog = gtk_app_about_dialog_new(GTK_WINDOW(window)); + + gtk_window_present(dialog); + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à consulter. * +* * +* Description : Fournit une référence à la barre de statut intégrée. * +* * +* Retour : Composant GTK en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GtkStatusStack *gtk_framework_window_get_status_stack(const GtkFrameworkWindow *window) +{ + GtkStatusStack *result; /* Instance à retourner */ + + result = window->status; + ref_object(result); + + return result; + +} + + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à remplir. * +* panel = nouveau panneau à afficher. * +* * +* Description : Ajoute un panneau à la fenêtre principale de Chrysalide. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_framework_window_add(GtkFrameworkWindow *window, /* __steal */GtkTiledPanel *panel) +{ + GtkWidget *bar; /* Barre de titre */ + GListStore *list; /* Liste éventuelle à intégrer */ + guint count; /* Nombre d'élements présents */ + guint i; /* Boucle de parcours */ + GtkWidget *widget; /* Composant à intégrer */ + FrameworkPanelPersonality personality; /* Propriétés du panneau */ + + + + gtk_tiling_grid_add_panel(window->grid, panel, G_OBJECT_TYPE(panel) == GTK_TYPE_WELCOME_PANEL); + + + + + bar = gtk_window_get_titlebar(GTK_WINDOW(window)); + + if (bar == NULL) ////////// REMME + { + bar = gtk_header_bar_new(); + gtk_window_set_titlebar(GTK_WINDOW(window), bar); + } ///////////////////////////// + + list = gtk_tiled_panel_get_title_widgets(panel, false); + + if (list != NULL) + { + count = g_list_model_get_n_items(G_LIST_MODEL(list)); + + for (i = 0; i < count; i++) + { + widget = GTK_WIDGET(g_list_model_get_item(G_LIST_MODEL(list), i)); + gtk_header_bar_pack_end(GTK_HEADER_BAR(bar), widget); + } + + unref_object(list); + + } + + /* Mise à jour des liens vers un panneau principal */ + + personality = get_framework_panel_personality(G_OBJECT_TYPE(panel)); + + if (personality & FPP_MAIN_PANEL) + gtk_framework_window_notify_new_main_panel_state(window, panel, true); + + else + { + if (window->main != NULL) + gtk_tiled_panel_notify_new_main_panel_state(panel, window->main, true); + } + +} + + +/****************************************************************************** +* * +* Paramètres : window = instance de fenêtre principale à manipuler. * +* main = panneau principal visé par l'opération. * +* activated = nature du changement de statut : ajout, retrait ?* +* * +* Description : Note un ajout ou un retrait de panneau principal. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void gtk_framework_window_notify_new_main_panel_state(GtkFrameworkWindow *window, GtkTiledPanel *main, bool activated) +{ + if (activated) + { + g_clear_object(&window->main); + + window->main = main; + ref_object(main); + + } + + else + { + if (main == window->main) + g_clear_object(&window->main); + + } + + gtk_tiling_grid_notify_new_main_panel_state(window->grid, main, activated); + +} |