/* Chrysalide - Outil d'analyse de fichiers binaires * gtkdockable.c - éléments acceptés dans les composants de rassemblement * * Copyright (C) 2015 Cyrille Bagard * * This file is part of Chrysalide. * * OpenIDA 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. * * OpenIDA 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 Foobar. If not, see . */ #include "gtkdockable.h" #include #include #include #include "easygtk.h" #include "gtkdockable-int.h" /* --------------------- DEFINITIONS PRINCIPALES DE L'INTERFACE --------------------- */ /* Procède à l'initialisation de l'interface de rassemblement. */ static void gtk_dockable_default_init(GtkDockableInterface *); /* ------------------------ FONCTIONS DE RECHERCHE INTEGREES ------------------------ */ /* Construit une zone de recherches vouée à être intégrée. */ static GtkWidget *build_search_area(GtkDockable *, GtkWidget **); /* Met à jour l'expression de filtrage de la zone intégrée. */ static void on_dockable_search_changed(GtkSearchEntry *, GtkDockable *); /* ---------------------------------------------------------------------------------- */ /* DEFINITIONS PRINCIPALES DE L'INTERFACE */ /* ---------------------------------------------------------------------------------- */ /* Détermine le type d'une interface pour rassemblement. */ G_DEFINE_INTERFACE(GtkDockable, gtk_dockable, G_TYPE_OBJECT) /****************************************************************************** * * * Paramètres : iface = interface GTK à initialiser. * * * * Description : Procède à l'initialisation de l'interface de rassemblement. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void gtk_dockable_default_init(GtkDockableInterface *iface) { } /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * * * * Description : Fournit le nom court du composant encapsulable. * * * * Retour : Désignation humaine pour titre d'onglet ou de fenêtre. * * * * Remarques : - * * * ******************************************************************************/ const char *gtk_dockable_get_name(const GtkDockable *dockable) { GtkDockableIface *iface; /* Interface utilisée */ iface = GTK_DOCKABLE_GET_IFACE(dockable); return iface->get_name(dockable); } /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * * * * Description : Fournit le nom long du composant encapsulable. * * * * Retour : Désignation humaine pour titre d'onglet ou de fenêtre. * * * * Remarques : - * * * ******************************************************************************/ const char *gtk_dockable_get_desc(const GtkDockable *dockable) { GtkDockableIface *iface; /* Interface utilisée */ iface = GTK_DOCKABLE_GET_IFACE(dockable); return iface->get_desc(dockable); } /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * * * * Description : Indique si le composant représenté à du contenu à fouiller. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ bool gtk_dockable_can_search(const GtkDockable *dockable) { GtkDockableIface *iface; /* Interface utilisée */ iface = GTK_DOCKABLE_GET_IFACE(dockable); return iface->can_search; } /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * * * * Description : Indique si le composant peut être désencapsulé manuellement. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ bool gtk_dockable_can_be_closed(const GtkDockable *dockable) { GtkDockableIface *iface; /* Interface utilisée */ iface = GTK_DOCKABLE_GET_IFACE(dockable); return iface->can_be_closed; } /****************************************************************************** * * * Paramètres : dockable = instance GTK dont l'interface est à consulter. * * * * Description : Fournit le composant graphique intégrable dans un ensemble. * * * * Retour : Composant graphique prêt à emploi. * * * * Remarques : - * * * ******************************************************************************/ GtkWidget *gtk_dockable_get_widget(GtkDockable *dockable) { GtkWidget *result; /* Composant à retourner */ GtkDockableIface *iface; /* Interface utilisée */ GtkWidget *widget; /* Composant graphique interne */ GtkWidget *revealer; /* Révélateur à intégrer ? */ GtkWidget *search; /* Zone de recherche */ iface = GTK_DOCKABLE_GET_IFACE(dockable); widget = iface->get_widget(dockable); g_object_ref(G_OBJECT(widget)); /* Encapsulation avec un panneau coulissant ? */ if (iface->can_search) { revealer = gtk_revealer_new(); gtk_widget_show(revealer); gtk_container_add(GTK_CONTAINER(revealer), build_search_area(dockable, &search)); result = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); gtk_widget_show(result); gtk_box_pack_start(GTK_BOX(result), revealer, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(result), widget, TRUE, TRUE, 0); g_object_set_data(G_OBJECT(result), "revealer", revealer); g_object_set_data(G_OBJECT(result), "search", search); } /* Ou bien non ! */ else result = widget; 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. * * * * Description : Révèle ou cache la zone de recherches. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void gtk_dockable_toggle_revealer(GtkDockable *dockable, GtkWidget *built, gboolean reveal) { GtkRevealer *revealer; /* Révélateur à actionner */ GtkWidget *entry; /* Zone de recherche à activer */ revealer = GTK_REVEALER(g_object_get_data(G_OBJECT(built), "revealer")); assert(revealer != NULL); gtk_revealer_set_reveal_child(revealer, reveal); if (reveal) { entry = GTK_WIDGET(g_object_get_data(G_OBJECT(built), "search")); gtk_widget_grab_focus(entry); } } /* ---------------------------------------------------------------------------------- */ /* FONCTIONS DE RECHERCHE INTEGREES */ /* ---------------------------------------------------------------------------------- */ /****************************************************************************** * * * Paramètres : dockable = élément encapsulable à avertir des changements. * * search = zone de saisie pour lancer les recherches. * * * * Description : Construit une zone de recherches vouée à être intégrée. * * * * Retour : Composant GTK prêt à être intégré. * * * * Remarques : - * * * ******************************************************************************/ static GtkWidget *build_search_area(GtkDockable *dockable, GtkWidget **search) { GtkWidget *result; /* Support à retourner */ GtkWidget *label; /* Etiquette à utiliser */ result = gtk_grid_new(); gtk_grid_set_row_spacing(GTK_GRID(result), 8); gtk_widget_show(result); label = qck_create_label(NULL, NULL, _("Look for:")); g_object_set(label, "margin", 8, NULL); gtk_grid_attach(GTK_GRID(result), label, 0, 0, 1, 1); *search = gtk_search_entry_new(); g_signal_connect(*search, "search-changed", G_CALLBACK(on_dockable_search_changed), dockable); gtk_widget_set_hexpand(*search, TRUE); gtk_widget_show(*search); gtk_grid_attach_next_to(GTK_GRID(result), *search, label, GTK_POS_RIGHT, 1, 1); return result; } /****************************************************************************** * * * Paramètres : entry = entrée de texte contenant le filtre brut. * * Paramètres : dockable = élément encapsulable à avertir des changements. * * * * Description : Met à jour l'expression de filtrage de la zone intégrée. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void on_dockable_search_changed(GtkSearchEntry *entry, GtkDockable *dockable) { regex_t *filter; /* Expression régulière */ const gchar *text; /* Texte de l'utilisateur */ int ret; /* Bilan de mise en place */ GdkRGBA error; /* Couleur d'erreur */ GtkDockableIface *iface; /* Interface utilisée */ filter = g_object_get_data(G_OBJECT(entry), "preg_filter"); text = gtk_entry_get_text(GTK_ENTRY(entry)); /* Mise en place d'une nouvelle règle */ if (strlen(text) > 0) { if (filter == NULL) { void destroy_filter(regex_t *preg) { regfree(preg); free(preg); } filter = (regex_t *)calloc(1, sizeof(regex_t)); g_object_set_data_full(G_OBJECT(entry), "preg_filter", filter, (GDestroyNotify)destroy_filter); } else regfree(filter); ret = regcomp(filter, text, REG_EXTENDED); if (ret != 0) { error.red = 1.0; error.green = 0.0; error.blue = 0.0; error.alpha = 1.0; gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, &error); return; } } /* Suppresion de toute règle existante */ else if (filter != NULL) { g_object_set_data(G_OBJECT(entry), "preg_filter", NULL); filter = NULL; } /* Mises à jour */ gtk_widget_override_color(GTK_WIDGET(entry), GTK_STATE_NORMAL, NULL); iface = GTK_DOCKABLE_GET_IFACE(dockable); iface->update_filtered(dockable, filter); }