summaryrefslogtreecommitdiff
path: root/src/gui/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/window.c')
-rw-r--r--src/gui/window.c621
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);
+
+}